美文网首页
Redis笔记之有序集合对象

Redis笔记之有序集合对象

作者: slxixiha | 来源:发表于2021-08-28 12:02 被阅读0次

    集合对象的编码可以是ziplist或者skiplist。

    ziplist编码类型

    每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个节点则保存元素的分值。

    压缩列表内的集合元素按分值从小到大进行排序,分值较小的元素被防止在靠近表头的位置,而分值较大的元素则被放置在靠近表尾的位置。

    skiplist编码类型

    skiplist编码并不是只使用skiplist,而是skiplist和字典的集合,该集合命名为zset,定义见下:

    typedef struct zset {
        dict *dict;
        zskiplist *zsl;
    } zset;
    

    zset结构中的zsl跳跃表按照分值从小到大保存了所有集合元素,每个跳跃表节点都保存了一个集合元素:跳跃表节点的object属性保存了元素的成员,而跳跃表节点的score属性则保存了元素的分值。通过这个跳跃表,程序可以对有序集合进行范围操作,例如zrank、zrange等命令。

    zset中的dict字典,为有序集合创建了一个从成员到分值的映射,字典的键保存了元素的成员,而字典的值则保存了元素的分值。通过这个字典,程序可以用O(1)复杂度查找给定成员的分值,zscore就是通过这个特性实现的。

    看起来两个结构似乎有了两份数据,但是实际上两个对象会通过指针共享数据,所以不存在冗余数据的问题。

    这里两种结构的混合使用实际上就是一种空间换时间的典型案例。

    对象类型的结构图
    • 压缩列表编码类型

      压缩列表对象.PNG
    • 跳跃表编码类型

      zset对象.PNG
    对象中不同类型的适用条件:

    只有同时满足以下两个条件时才会使用ziplist编码:

    1. 有序集合保存的元素数量小于128个;
    2. 有序结合保存的所有元素成员的长度都小于64字节;

    不能满足以上条件的有序集合对象都将使用skiplist编码,这两个上限都可修改

    通过以下命令验证:

    127.0.0.1:6379> eval "for i=1, 128 do redis.call('zadd', KEYS[1], i, i) end" 1 znum
    (nil)
    127.0.0.1:6379> zcard znum
    (integer) 128
    127.0.0.1:6379> object encoding znum
    "ziplist"
    127.0.0.1:6379> zadd znum 3.14 pi
    (integer) 1
    127.0.0.1:6379> zcard znum
    (integer) 129
    127.0.0.1:6379> object encoding znum
    "skiplist"
    
    127.0.0.1:6379> zadd  blah 1.9 www
    (integer) 1
    127.0.0.1:6379> object encoding blah
    "ziplist"
    127.0.0.1:6379> zadd blah 2.0 ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
    (integer) 1
    127.0.0.1:6379> object encoding blah
    "skiplist"
    

    相关文章

      网友评论

          本文标题:Redis笔记之有序集合对象

          本文链接:https://www.haomeiwen.com/subject/yvsbiltx.html