Redis radix tree源码解析
Redis實現了不定長壓縮前綴的radix tree,用在集群模式下存儲slot對應的的所有key信息。本文將詳述在Redis中如何實現radix tree。
核心數據結構
raxNode是radix tree的核心數據結構,其結構體如下代碼所示:
typedef struct raxNode {uint32_t iskey:1; uint32_t isnull:1; uint32_t iscompr:1; uint32_t size:29; unsigned char data[]; } raxNode;-
iskey:表示這個節點是否包含key
- 0:沒有key
- 1:表示從頭部到其父節點的路徑完整的存儲了key,查找的時候按子節點iskey=1來判斷key是否存在
- isnull:是否有存儲value值,比如存儲元數據就只有key,沒有value值。value值也是存儲在data中
- iscompr:是否有前綴壓縮,決定了data存儲的數據結構
- size:該節點存儲的字符個數
-
data:存儲子節點的信息
-
- iscompr=0:非壓縮模式下,數據格式是:[header strlen=0][abc][a-ptr][b-ptr][c-ptr](value-ptr?),有size個字符,緊跟著是size個指針,指向每個字符對應的下一個節點。size個字符之間互相沒有路徑聯系。
- iscompr=1:壓縮模式下,數據格式是:[header strlen=3][xyz][z-ptr](value-ptr?),只有一個指針,指向下一個節點。size個字符是壓縮字符片段
Rax Insert
以下用幾個示例來詳解rax tree插入的流程。假設j是遍歷已有節點的游標,i是遍歷新增節點的游標。
場景一:只插入abcd
z-ptr指向的葉子節點iskey=1,使用了壓縮前綴。
場景二:在abcd之后插入abcdef
從abcd父節點的每個壓縮前綴字符比較,遍歷完所有abcd節點后指向了其空子節點,j = 0, i < len(abcded)。
查找到abcd的空子節點,直接將ef賦值到子節點上,成為abcd的子節點。ef節點被標記為iskey=1,用來標識abcd這個key。ef節點下再創建一個空子節點,iskey=1來表示abcdef這個key。
場景三:在abcd之后插入ab
ab在abcd能找到前兩位的前綴,也就是i=len(ab),j < len(abcd)。
將abcd分割成ab和cd兩個子節點,cd也是一個壓縮前綴節點,cd同時被標記為iskey=1,來表示ab這個key。
cd下掛著一個空子節點,來標記abcd這個key。
場景四:在abcd之后插入abABC
abcABC在abcd中只找到了ab這個前綴,即i < len(abcABC),j < len(abcd)。這個步驟有點復雜,分解一下:
- step 1:將abcd從ab之后拆分,拆分成ab、c、d 三個節點。
- step 2:c節點是一個非壓縮的節點,c掛在ab子節點上。
- step 3:d節點只有一個字符,所以也是一個非壓縮節點,掛在c子節點上。
- step 4:將ABC 拆分成了A和BC, A掛在ab子節點上,和c節點屬于同一個節點,這樣A就和c同屬于父節點ab。
- step 5:將BC作為一個壓縮前綴的節點,掛在A子節點下。
- step 6:d節點和BC節點都掛一個空子節點分別標識abcd和abcABC這兩個key。
場景五:在abcd之后插入Aabc
abcd和Aabc沒有前綴匹配,i = 0,j = 0。
將abcd拆分成a、bcd兩個節點,a節點是一個非壓縮前綴節點。
將Aabc拆分成A、abc兩個節點,A節點也是一個非壓縮前綴節點。
將A節點掛在和a相同的父節點上。
同上,在bcd和abc這兩個節點下掛空子節點來分別表示兩個key。
Rax Remove
刪除
刪除一個key的流程比較簡單,找到iskey的節點后,向上遍歷父節點刪除非iskey的節點。如果是非壓縮的父節點并且size > 1,表示還有其他非相關的路徑存在,則需要按刪除子節點的模式去處理這個父節點,主要是做memove和realloc。
合并
刪除一個key之后需要嘗試做一些合并,以收斂樹的高度。
合并的條件是:
- iskey=1的節點不能合并
- 子節點只有一個字符
- 父節點只有一個子節點(如果父節點是壓縮前綴的節點,那么只有一個子節點,滿足條件。如果父節點是非壓縮前綴的節點,那么只能有一個字符路徑才能滿足條件)
結束語
云數據庫Redis版(ApsaraDB for Redis)是一種穩定可靠、性能卓越、可彈性伸縮的數據庫服務。基于飛天分布式系統和全SSD盤高性能存儲,支持主備版和集群版兩套高可用架構。提供了全套的容災切換、故障遷移、在線擴容、性能優化的數據庫解決方案。歡迎各位購買使用:云數據庫 Redis 版
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
總結
以上是生活随笔為你收集整理的Redis radix tree源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于TableStore的亿级订单管理解
- 下一篇: 数据清理的终极指南