乐趣区

关于后端:组织架构新型数据结构思考

1 前言

权限架构始终是企业中,中小型零碎绕不开的性能,这篇文章中,波及到的篇幅仅限于不是特地简单的中小心零碎。

以我遇到的为例,权限架构个别分为组织治理、角色治理、用户治理。

组织治理,主持的是数据权限,一个组织的横向之间互相隔离,纵向之间确定能见度,

角色治理,主持的是性能权限,不同的角色有不同的菜单,有不同的性能。

用户治理,是组织与角色的独特体现。

在这里,重点要说的是组织治理,因为在不同的零碎中,角色自身代表的含意差异很大,角色可能有上下级治理,也可能没有,或者是能看到的菜单不同,或者是能看到的按钮不同,这些性能的他体现还要依据前端架构的不同进行设计,能够说没有什么精确的设计,可能涵盖角色性能代表的意义。

然而组织个别共性较多一些,组织与前端关系不是很深,个别只须要一个治理性能,用户可能挂靠到组织下即可,次要还是看后端如何解决不同组织关系下的数据查问。

2 组织架构数据结构个别模式

在个别零碎中,大部分设计组织架构,都是应用一张表,利用 pid 作为关联本表 id 的外键,应用 pid 与 id 的层层递进的关联关系。

大略相似于上面的表格

id name pid
0 顶层组织 null
1 二层组织 0
2 三层组织 1

这样咱们通过 pid 为 null 来确定这是顶层机构,通过 pid 为 1 的记录找到二层组织的子记录,如果想找到三层组织,还须要使用简单的 sql,来从新组织数据关系,来不便找到一连串的组织关系。

例如这段在 oracle 中的 sql,这样的 sql 能够用来找到顶层组织所有的关联关系。

SELECT * FROM table_organ
            START WITH id = '0'
            CONNECT BY NOCYCLE PRIOR ID = pid

这样做问题不大,如果说只局限于组织关系表这一张表的查问,那么咱们的问题永远也不必回升档次。

然而针对于关联表的查问,这样的形式就显得有些轻便了。如果你要查问,顶层机构及其附属机构在某一张表的所属数据,就须要用到上面的 sql:

select * from some_table where organId in (SELECT id FROM table_organ
            START WITH id = '1'
            CONNECT BY NOCYCLE PRIOR ID = pid)

这样的实现没有任何问题,目前的数据库必定曾经思考到了在条件不变的状况下,子查问只会查问一次,也就是说,这样的查问,副作用只是会多带来一次查问。

然而在经验了屡次这样的功能设计之后,旧的状况曾经慢慢不能满足于我了。

3 组织架构数据结构的新模式

体现组织层级的不肯定要应用纵向的数据关系,也能够应用横向的数据关系。

什么是纵向、横向?上面来解释一下。

3.1 纵向数据关系表

纵向数据关系示意如下表,能够看到,示意层级关系的高下,是通过减少层级的深度的来示意的。

id pid
0 null
1 0
2 1

3.2 横向数据关系表

那么应用横向数据关系示意呢?如下表。在上面表中,示意层级关系是通过横向扩大数据的长度来示意的,层级关系的高下,取决于横向数据的长短。(order_seq 示意本人在以后层级下的程序,为的是不便数据处理,tier 为数据的层级,是否须要取决于理论场景是否用到,例如当心愿可能查问指定深度的数据时)

id authority order_seq tier
0 0/ 0 0
1 0/1/ 1 1
2 0/1/0/ 0 2

3.3 数据结构的设计要点

3.3.1 查问形式

在利用了横向设计的数据之后,查问就变得与众不同的简略。

当我心愿查问顶层组织的所有关联关系时:

SELECT * FROM table_organ where authority like '0/%'

当我心愿查问所属顶层组织的数据时:

select * from some_table where authority like '0/%'

当我心愿查问通过两头一层组织,找到所有上下级组织的数据时:

select * from some_table where authority like '0/1/%' or instr('0/1/', authority) = 1

当我心愿查问通过两头一层组织,找到所有上下级组织的数据时:

select * from some_table where authority like '0/1/%' or instr('0/1/', authority) = 1

3.3.2 分隔符

在下面的 3.2 中的横向数据关系表中,你可能看到我应用的是宰割是 /,并且数据也要以 / 分隔符作为结尾。

这是为了避免在下一层数据过多时,导致的数据判断异样,例如 0/10/10,在下面的 sql 中,若没有最初一位 / 的阻隔,查问后果就会呈现数据异样。

3.3.3 数字的抉择

在这种设计中,数字的抉择的正确与否至关重要,它是整个数据结构的根底。

须要准守上面两个要点:

  1. 有雷同下级的同级中不容许呈现反复数字,有不同下级的同级能够呈现反复数字,例如 0/0/1/0/
  2. 尽量不让数字只增大,而是可能填补之前的空缺,例如你有 0/1/3/ 这三个顶层组织,当 1/ 被删除之后,再次增加须要可能填补 1 的空缺

由此,设计出一个 sql,来帮忙咱们实现这个需要,sql 为 mysql 的版本。

select *
from (select *
      from (select c.rownum
            from (SELECT @rownum := @rownum + 1 as rownum, a.order_seq
                  from (select *
                        from cem_organ
                        where authority regexp '^[0-9]+/$') a,
                       (SELECT @rownum := -1) b
                  ORDER BY a.order_seq) c
            where c.rownum != c.order_seq
            limit 1) as e
      UNION
      select *
      from (select max(d.order_seq) as num
               from cem_organ d
               where d.authority regexp '^[0-9]+/$') as f
      where f.num is not null) as g
limit 1

这个 sql 分为三局部。

  1. 第一局部是为了找到缺失的数字,思路是利用 order_seqrow_num 的不相等记录。
  2. 第二局部是为了找到最大的数字。
  3. 最初合并第一局部与第二局部的后果,只取前一位,若此 sql 没有返回任何记录,那么程序取 0。

应用这个 sql 的同时,也要留神到利用 authority 通过正则,来限度你的下级,若是顶层组织,值为 ^[0-9]+/$,若是非顶层组织,值为 ^0/[0-9]+/$,以此类推 ^0/1/[0-9]+/$。(也能够通过 like 的模式做到同样的成果)

在这里还须要留神一个要害的问题,那就是并发产生的问题,如果同一时间执行此条 sql,会造成取值雷同的状况,因而须要在执行 sql 的中央加上分布式锁,来确保并发状况下可能失去惟一的值。锁的值应用父级 authority 来进步一些性能。

3.4 长处

3.4.1 查问逻辑简略容易移植

这个长处是不言而喻的,当你想找到组织关系中的所有的上级关系,查问逻辑只须要用一个 like,并且 like 基本上所有的数据库语法都是一样的,因为简略,所以容易移植。

regex 查问同样也是如此。

3.4.2 查问速度快

在领有百万数据级别时,特地是查问的条件为领有许多附属上级的顶层组织时,长处尤为显著。

另外,在有两层或者两层以上的上下级关系之间查问,有着无可比拟的劣势。

例如,当组织下分管着部门,部门下又分管着打印机,当你把雷同的思路利用于部门表以及打印机表时,你齐全能够跳过组织、部门,间接查问。

select * from table_printer where authority like '0/%'

在这里,你能够联想一下,如果应用 pid 关联的形式,该如何查问,特地是在一个大的组织关系中,当部门的数据量过千时,怎么破解数据库对 in 数量的限度,也是须要思考的中央。

3.4.1 数据更容易了解

相比于之前的 pid 连贯形式,authority 更加可能直观的体现数据之间的关系。

3.5 毛病

3.5.1 实现逻辑简单

由后面的文章能够看出,为了实现这种基于数据结构的上下级关系,咱们须要满足诸多条件,须要在各个中央小心翼翼的保护 authority 代表上下级关系的字符串,一旦出错,带来的影响将是微小的。

3.5.2 不适宜特地简单的逻辑

目前我还没有遇到可能会超过这种数据结构的需要,然而不免客户会从一些刁钻的角度提出另类的需要,而这种数据结构其实从根本上来说是非常精美软弱的,一旦呈现了变动,很可能会减少实现逻辑的复杂度,甚至于推倒重来。

因而须要小心的衡量这种数据所带来的利弊。

最初

这种新型的数据结构,是通过锻炼与验证的,的确从实际上帮忙你解决一些业务痛点。

但它同样也是一把双刃剑,可能残缺的驾驭它,须要较强的逻辑思维与代码设计能力。

否则最初的代码构造,会看起来到处是为了实现这种逻辑打上的补丁,因而一直的重构、精简代码、欠缺的回归测试,也是十分必要的。

退出移动版