二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现( 二 )

  • sz:ziplist个数
  • count:ziplist中包含的节点数
  • 在redis.conf通过设置每个ziplist的最大容量,quicklist的数据压缩范围,提升数据存取效率,单个ziplist节点最大能存储量,超过则进行分裂,将数据存储在新的ziplist节点中
    -5: max size: 64 Kb <— not recommended for normal workloads
    -4: max size: 32 Kb <— not recommended
    -3: max size: 16 Kb <— probably not recommended
    -2: max size: 8 Kb <— good
    -1: max size: 4 Kb <— good
    List-max-ziplist-size -20代表所有节点,都不进行压缩,1.代表从头节点往后一个,尾结点往前一个不用压缩,其它值以此类推List-compress-depth 1
    【二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现】Redis 的链表实现的特性可以总结如下:
    • 双端:链表节点带有prev和next指针,获取某个节点的前置节点和后置节点的复杂度都是O(1)。
    • 无环:表头节点的prev指针和表尾节点的next指针都指向NULL,对链表的访问以NULL为终点 。
    • 带表头指针和表尾指针:通过list结构的head指针和tail指针,程序获取链表的表头节点和表尾节点的复杂度为O(1)。
    • 带链表长度计数器:程序使用list结构的len属性来对list持有的链表节点进行计数,程序获取链表中节点数量的复杂度为O(1) 。
    3 Hash存储一个对象,可以直接将该对象进行序列化后使用String类型存储,再通过反序列化获取对象 。对于只需要获取对象的某个属性的场景,可以将将每个属性分别存储;但这样在Redis的dict中就会存在大量的key,对于键时效后的回收效率存在很大影响 。使用Map结构就可以再dict的存储中只存在一个key并将属性与值再做关联 。
    Redis的Hash数据结构也是使用的dict(具体实现可以查看上一篇,浅谈Redis数据结构(上)-Redis数据存储及String类型的实现)实现 。当数据量比较小,或者单个元素比较小时,底层使用ziplist存储,数据量大小和元素数量有如下配置:
    二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现

    文章插图
    ziplist元素个数超过512,将改为hashtable编码hash-max-ziplist-entries 512单个元素大小超过64byte时,将改为hashtable编码hash-max-ziplist-value 64
    二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现

    文章插图
    4 SetSet类型可以在对不重复集合操作时使用,可以判断元素是否存在于集合中 。Set数据结构底层实现为value为null的dict,当数据可以使用整形表示时,Set集合将被编码为intset结构 。
    typedef struct intset {uint32_t encoding;uint32_t length;int8_t contents[];} intset;整数集合是一个有序的,存储整型数据的结构 。整型集合在Redis中可以保存xxxx的整型数据,并且可以保证集合中不会出现重复数据 。
    二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现

    文章插图
    使用intset可以节省空间,会根据最大元素范围确定所有元素类型;元素有序存储在判断某个元素是否存在时可以基于二分查找 。但在以下任意条件不满足时将会使用hashtable存储数据 。
    • 元素个数大于配置的set-max-inset-entries值
    • 元素无法用整型表示

    二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现

    文章插图
    5 Sorted Set连续空间存储数据,每次增加数据都会对全量数据进行搬运 。对于有序链表查找指定元素,只能通过头、尾节点遍历方式进行查找,如果将每个数据增加不定层数的索引,索引之间相互关联,寻找指定或范围的元素时就可以通过遍历层级的索引来确定元素所处范围,减少空间复杂度 。跳跃表是一种可以对有序链表进行近似二分查找的数据结构,redis 在两个地方用到了跳跃表,一个是实现有序集合,另一个是在集群节点中用作内部数据结构 。

    经验总结扩展阅读