一個多層級節點用戶樹的設計構思

背景:


       由於近期一個項目要開發一個多層級用戶體系,並且還要支持部分鏈條的可移動性,經過初步構思,已經有了一個初步的思路,今天在這裏簡單分享一下。


要求:


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,放
在一個事務中。


後話:


       多層級的設計是非常靈活多變的,要看場景和需求,以及多大的擴展能力和數據大小,沒有最好,只有最適合。

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