一个多层级节点用户树的设计构思

背景:


       由于近期一个项目要开发一个多层级用户体系,并且还要支持部分链条的可移动性,经过初步构思,已经有了一个初步的思路,今天在这里简单分享一下。


要求:


1. 用户结点数要支持百万级,层级理论上支持无限级扩展
2. 支持节点动态插入(不支持删除,通常也不会有这种需求,需要的话采用节点状态来处理)
3. 支持叶子节点可移动(中间节点不可以移动)
4. 支持一级节点可替换(也就是说可以把某个一级节点下面的所有节点迁移到另外一个一级节点下面)


实现方式:


1. 采用mysql单表设计
2. 采用redis实现分布式锁  (本篇暂不讨论实现)



表设计:




说明:
id: 主键,自增
bid:  节点业务id(独立唯一索引,bid不允许重复)
layer: 节点所处层级,一级节点为1,二级节点为2,依此类推
parent_bid: 当前节点的上级节点业务 id
top_bid: 当前节点所属一级节点的 bid (独立索引)


初始数据:





初始结构:




操作:


1. 新增节点

    1) 新增一级节点

         layer = 1, parent_bid = 0 , top_bid = 0, 通过 top_bid = 0 可以查询出所有一级节点,别忘了 top_bid 有独立索引。

    2) 新增非一级节点 

        首先找到上级节点(parent),然后 cur(layer) = parent(layer)+1;  cur(parent_bid) = parent(bid);  

        cur(top_bid) =  parent为一级节点?  parent(bid) : parent(top_bid)
 

2. 移动节点

1) 移动叶子节点

       cur(layer) = target(layer)+1;  cur(parent_bid) = target(bid);  cur(top_bid) = target为一级节点?target(bid) : target(top_bid)

2) 替换一级节点

       比如,把 bid_1 下面整个子链条迁移到 bid_5的下面,用target表示 bid_5节点。

       2.1) bid_1 的直接下级要修改 parent_bid = target(bid)

       2.2)  bid_1整个子链条节点的新的top_bid:   new_top_bid = target为一级节点?  target(bid) : target(top_bid),
               用sql表示为 update tree set top_bid = new_top_bid where top_bid = "bid_1"

 3. 查询

       如果要查询节点的话,目前只能是一级一级的查看,不支持查看一个节点的整个下级网络


安全修改


       在新增和移动节点的过程当中,如果有并发操作的话,容易把数据弄乱,而且不可恢复,那
将是灾难性的后果。考虑到跨多个jvm,单纯的java锁是解决不了问题的,所以这里必须使用
分布式锁。

     1) 可以使用分布式读写锁,由于多个新增操作不会有冲突,所以新增操作可以使用读锁;
         所有的移动操作都是互斥的,所以可以使用写锁; 分布式读写锁自己实现的话会比较麻烦,
         如果系统并发量不是很大,可以考虑使用2)中的方式。
     2) 使用普通的分布式锁,相当于实现一个跨jvm的同步操作,可以使用redis简单实现一个
         分布式锁,以后有时间再单独写一篇来介绍如何实现。


安全日志:


       如果你的实现有bug,比如移动节点代码写的有问题,导致整个层级结构错乱了,该怎么办?
可以创建一张 log表,按时间顺序 ,记录下每一个新增操作和移动操作,修改用户名、手机之类
的不需要记录,如果层级出现错误了,以后还可以写个脚本执行log中的所有操作命令,还是
有机会重建出整个层级树出来的。


其它:


       需求的变化是无止境的,一个模型适应不了所有的需求,有时候,是需要商务去引导客户的。
基于以上模型也是有缺陷的,比如,不可以随便移动任意节点,不能简单就可以查看一个用户
所有下级网络等。 但也是有替代方案的,比如,查询下级用户的话,一层一层来查询; 任意移
动节点的话,由于操作肯定很少,真有需求,可以考虑找出所有相关节点,一个一个update,放
在一个事务中。


后话:


       多层级的设计是非常灵活多变的,要看场景和需求,以及多大的扩展能力和数据大小,没有最好,只有最适合。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章