redis 系列——2、redis 鏈表原理

概述

上篇博客我簡單介紹了 redis 字符串的實現原理。除了字符串外,鏈表作爲一種常用的數據結構,提供了高效的節點重排能力以及順序性的節點訪問。redis 使用的C語言沒有內置鏈表結構,本篇博客我就來整理下 redis 鏈表類型的實現。


redis 數據類型

redis 有以下五種常用的數據類型:

  • String:字符串類型
  • Hash:哈希類型
  • list:鏈表類型
  • set:集合類型
  • zSet:有序集合類型

1、List 鏈表類型

C語言默認是不支持鏈表的,redis 使用頭文件 adlish.h 中的 ListNode 表示單個鏈表結構:

typedef struct listNode {
    // 前置節點
    struct listNode * prev;
    // 後置節點
    struct listNode * next;
    // 節點的值
    void * value;
}listNode;

多個節點之間通過 prev 和 next 指針組成雙端鏈表,具體結構如下所示:
鏈表結構
僅僅使用 ListNode 是可以組成鏈表,但使用 adlish.h 的 List 來持有鏈表的話,操作會更高效:

typedef struct list {
    // 表頭節點
    listNode * head;
    // 表尾節點
    listNode * tail;
    // 鏈表所包含的節點數量
    unsigned long len;
    // 節點值複製函數
    void *(*dup)(void *ptr);
    // 節點值釋放函數
    void (*free)(void *ptr);
    // 節點值對比函數
    int (*match)(void *ptr,void *key);
} list;

list 結構爲鏈表提供了表頭、表尾、鏈表節點數以及三個不同類型的函數:

  • dup 函數用於複製鏈表節點所保存的值;
  • free 函數用於釋放鏈表節點所保存的值;
  • match函數則用於對比鏈表節點所保存的值和另一個輸入值是否相等

dup、free,match 是用於實現多態鏈表所需的類型特定函數。下面我們看一張 List 和 ListNode 合用的結構圖:
List、ListNode
總結一下,redis 鏈表結構的實現有以下特性:

  1. 雙向鏈接,獲取某個節點的前驅節點以及後記節點的時間複雜度都爲O(1)
  2. 無環,head 的前驅節點以及 tail 的後繼節點都爲 NULL
  3. 訪問鏈表頭節點和鏈表尾節點的時間複雜度都爲O(1)
  4. 訪問鏈表長度的時間複雜度爲O(1)
  5. 多態,鏈表節點使用 void* 指針來保存節點值,並可以通過 list 結構提供的 dup、free、match 三個屬性爲節點值設定特定類型函數,所以鏈表可以保存各種類型的值

鏈表常用 API

下面我通過表格的形式給出 redis 鏈表常用的函數方法:

鏈表方法
鏈表方法


鏈表用途

鏈表在 redis 中的用途非常廣泛。除了在 列表鍵 中使用外,很多其他功能也用到了鏈表。

  • 鏈表鍵:當我們稱一個鍵爲列表鍵時,數據庫中該鍵鎖對應的值爲鏈表類型

redis 的發佈與訂閱、慢查詢、監視器等功能也用到了鏈表。redis 服務器本身還使用鏈表來保存多個客戶端的狀態信息,以及使用鏈表來構建客戶緩衝區。


概述:
《redis設計與實現》黃健宏著
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章