Redis的Set鏈表數據結構

Redis的Set鏈表數據結構

鏈表節點 -> 設計字段

typedef struct listNode {

    // 前置節點
    struct listNode *prev;

    // 後置節點
    struct listNode *next;

    // 節點的值
    void *value;

} listNode;

digraph {      label = "\n 图 3-1    由多个 listNode 组成的双端链表"      rankdir = LR;      node [shape = record];      //      more_prev [label = "...", shape = plaintext];     x [label = " listNode | value \n ..."];     y [label = " listNode | value \n ..."];     z [label = " listNode | value \n ..."];     more_next [label = "...", shape = plaintext];      //      more_prev -> x [label = "next"];     x -> more_prev [label = "prev"];       x -> y [label = "next"];     y -> x [label = "prev"];      y -> z [label = "next"];     z -> y [label = "prev"];      z -> more_next [label = "next"];     more_next -> z [label = "prev"]; }

但是你以爲set就這樣組成嗎,那簡直大錯特錯了!

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 結構和三個 listNode 結構組成的鏈

digraph {      label = "\n 图 3-2    由 list 结构和 listNode 结构组成的链表"      rankdir = LR;      node [shape = record];      //      list [label = "list |  head |  tail |  len \n 3 |  dup |  free |  match ", width = 2.0];      more_prev [label = "NULL", shape = plaintext];     x [label = " listNode | value \n ..."];     y [label = " listNode | value \n ..."];     z [label = " listNode | value \n ..."];     more_next [label = "NULL", shape = plaintext];      dup [label = "...", shape = plaintext];     free [label = "...", shape = plaintext];     match [label = "...", shape = plaintext];      //      list:head -> x;     list:tail -> z;      list:dup -> dup;     list:free -> free;     list:match -> match;      x -> y;     y -> x;      y -> z;     z -> y;      //      more_prev -> x [dir = back];     z -> more_next;  }

特點

  • 雙端: 鏈表節點帶有 prevnext 指針, 獲取某個節點的前置節點和後置節點的複雜度都是 O(1) 。
  • 無環: 表頭節點的 prev 指針和表尾節點的 next 指針都指向 NULL , 對鏈表的訪問以 NULL 爲終點。
  • 帶表頭指針和表尾指針: 通過 list 結構的 head 指針和 tail 指針, 程序獲取鏈表的表頭節點和表尾節點的複雜度爲 O(1) 。
  • 帶鏈表長度計數器: 程序使用 list 結構的 len 屬性來對 list 持有的鏈表節點進行計數, 程序獲取鏈表中節點數量的複雜度爲 O(1)。
  • 多態: 鏈表節點使用 void* 指針來保存節點值, 並且可以通過 list 結構的 dupfreematch 三個屬性爲節點值設置類型特定函數, 所以鏈表可以用於保存各種不同類型的值。

鏈表被廣泛用於實現 Redis 的各種功能, 比如列表鍵, 發佈與訂閱, 慢查詢, 監視器, 等等。

Set使用場景

Set類型特點就是唯一,依靠唯一性,我們可以實現推薦好友,安全提示等功能。

1. 推薦好友

每個人的好友都可以是一個Set集合,通過SINTER可以計算出兩個KEY之間的交集,如果交集大於某個閾值,就可以作爲可能認識的人或者好友進行推薦,當然前提是兩個人並非好友。
由於是陌生人推薦,因此需要計算這個人和其他非好友的所有人之間的好友交集,如果保證性能也是需要考慮的一個問題。

2. 安全提示

這個主要用於羣聊拉人的時候,新人入羣的提示,如果被拉進羣聊的新人除了拉取人之外,和其他羣友都不是好友關係或者跟不超過N個人是好友關係的時候,就可以給一個安全提示。此時用到的是SISMEMBER。

進羣聊的新人除了拉取人之外,和其他羣友都不是好友關係或者跟不超過N個人是好友關係的時候,就可以給一個安全提示。此時用到的是SISMEMBER。

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