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。

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