Redis深度歷險-基數樹
Redis中的基數樹是一種有序字典樹,
zset
也是一種有序字典但是是按照score
進行排序的,rax
是按照key
進行排序的;平衡二叉樹、跳錶都可以用來實現這種有序集合,不過要考慮複雜度
數據結構
數據結構
基數樹有點類似與前綴樹trie
樹,主要用於Redis Stream
中存儲消息隊列,因爲消息的key
是時間戳+序號,而時間戳的編碼也是按照年月日時分秒毫秒微秒納秒一級一級劃分
有以下特點:
- 從根節點到葉子結點上的所有字符組合起來就是該葉子結點對應的字符串,即
key
- 如果節點只有一個字節點,允許跳多個字符,如圖中的
朋友
越過了end
- 如果節點有多個子節點,只允許跳一個字符到子節點,如圖中的
災難
節點必須先經過s
節點
typedef struct raxNode {
uint32_t iskey:1; //用來標識根節點,沒有key的是根節點
uint32_t isnull:1; //標誌數據結構所需的中間節點,沒有存儲value
uint32_t iscompr:1; //是否壓縮存儲
uint32_t size:29; //子節點數量或壓縮字符串的長度
unsigned char data[]; //數據
} raxNode;
raxNode
有多種情況
- 根節點
- 中間節點
- 壓縮節點:有多個字節點
- 非壓縮節點:只有一個字節點
壓縮節點
在代碼中並沒有通過結構體表述出來,而是通過內存排布來決定的
[header iscompr=1][xyz][z-ptr](value-ptr?)
一個壓縮節點的data
包含三部分
- 路由鍵:最多一個,如果是葉子結點就沒有路由鍵了
- 子節點指針:如果是葉子結點也沒有子節點了
-
value
:如果是中間節點(isnull
標識),就沒有value部分了
非壓縮節點
主要有兩部分:
- 路由鍵:也是一個字符串,但是每一個字符標識一個子節點
- 子節點指針:和路由鍵的字符一一對應
總結
涉及到這種內存操作的邏輯會非常複雜,很容易陷入細節邏輯中,有時間再補充細節吧