本文摘抄自 redis源碼學習筆記
雙端鏈表在Redis中的地位:它作為壹種 通用數據結構 ,在Redis的內部使用非常多。是 Redis列表結構的底層實現之壹,也被大量Redis模塊使用,用於構建其他功能 。
Redis雙端列表的定義可以參看 adlist.h 和 adlist.c 兩個文件。
與雙鏈表定義壹致,引入了鏈表節點,並在此基礎上增加頭尾節點構建雙端鏈表。
鏈表節點如下定義:
鏈表如下定義:
listCreate
創建新鏈表
O(1)
listRelease
釋放鏈表,以及該鏈表所包含的節點
O(N)
listDup
創建給定鏈表的副本
O(N)
listRotate
取出鏈表的表尾節點,並插入到表頭
O(1)
listAddNodeHead
將包含給定值的節點添加到鏈表的表頭
O(1)
listAddNodeTail
將包含給定值的節點添加到鏈表的表尾
O(1)
listInsertNode
將包含給定值的節點添加到某個節點的之前或之後
O(1)
listDelNode
刪除給定節點
O(1)
listSearchKey
在鏈表中查找和給定 key 匹配的節點
O(N)
listIndex
給據給定索引,返回列表中相應的節點
O(N)
listLength
返回給定鏈表的節點數量
O(1)
listFirst
返回鏈表的表頭節點
O(1)
listLast
返回鏈表的表尾節點
O(1)
listPrevNode
返回給定節點的前壹個節點
O(1)
listNextNode
返回給定節點的後壹個節點
O(1)
listNodeValue
返回給定節點的值
O(1)
雙端列表的結構對於增加、刪除 兩種常用操作,復雜度降到了O(1)
這對於實現壹些內部命令如LPUSH、RPOP 等平凡命令,降低了時間開銷。
Redis實現了壹個雙端鏈表的叠代器,方便從兩個方向對雙端鏈表進行叠代。
沿著節點 next 指針,從表頭向表尾叠代
沿著節點 prev 指針,從表尾向表頭叠代
叠代器定義如下:
獲取叠代器實現如下:
叠代器每次根據叠代方向,返回下壹個節點。
對列表類型的鍵進行操作時,程序底層操作可能就是用的雙端鏈表 。
比如執行 RPUSH、LPOP、LLEN 等命令。
RPUSH 的使用如下,其他命令可以查看.
將壹個或多個值 value 插入到列表 key 的表尾(最右邊)。
如果有多個 value 值,那麽各個 value 值按從左到右的順序依次插入到表尾:比如對壹個空列表 mylist 執行 RPUSH mylist a b c ,得出的結果列表為 a b c ,等同於執行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。
如果 key 不存在,壹個空列表會被創建並執行 RPUSH 操作。
當 key 存在但不是列表類型時,返回壹個錯誤。
除了實現列表類型以外, 雙端鏈表還被很多 Redis 內部模塊所應用:
事務模塊使用雙端鏈表 依序保存輸入的命令
服務器模塊使用雙端鏈表來 保存多個客戶端
訂閱/發送模塊使用雙端鏈表來保存訂閱模式的多個客戶端
事件模塊使用雙端鏈表來保存 時間事件