Redis Zset有序集合实现原理

概要:Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。

一、Redis编码简介
Redis对象的底层实现数据结构由对象的encoding属性决定,该属性记录了对象的编码,即对象使用的底层实现的数据结构。这些编码可以是:

编码格式

底层数据结构

REDIS_ENCODING_INT

long类型的整数

REDIS_ENCODING_ EMBSTR

embstr编码的简单动态字符串

REDIS_ENCODING_RAW

简单动态字符串

REDIS_ENCODING_HT

字典

REDIS_ENCODING_LINKEDLIST

双端链表

REDIS_ENCODING_ZIPLIST

压缩列表

REDIS_ENCODING_INTSET

整数集合

REDIS_ENCODING_SKIPLIST

跳跃表和字典

二、有序集合的编码可以是ziplist或者skiplist

  • ziplist编码
    ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。
    压缩列表内的集合元素按分值从小到大排序。

    zlbytes

    zltail

    zllen

    “apple”

    5.0

    “pen”

    6.0

    zlend

    属性

    说明

    zlbytes

    记录整个压缩列表占用的内存字节数;在对压缩列表进行内存重分配, 计算 zlend 的位置时使用。

    zltail

    记录压缩列表表尾节点距离压缩列表的起始地址有多少个字节:通过这个偏移量,程序无需遍历整个压缩列表就可以确定表尾节点的地址

    zllen

    记录了压缩列表包含的节点数量

    zlend

    特殊值oxFF(十进制255),用于标记压缩列表的末尾

  • skiplist编码
    skiplist编码使用跳跃表和字典实现底层数据结构
    字典(dict)为有序集合构造了一个成员和分值之间的映射,字典中的每个键保存了元素成员,字典的值保存了元素的分值。通过字典,可以以O(1)的时间复杂度查找成员对应的分值。
    因为字典的键是唯一的,字典与跳跃表之间共享元素的指针,所以不会存在重复元素。排序是在跳跃表中实现的。

    跳跃表的相关内容参考:跳跃表

参考:W3Cschool 和 Redis设计与实现(黄健宏)


版权声明:本文为asdfadafd原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。