【精简版八股】Redis Zset底层结构

216 阅读2分钟

Redis相关文章

zset | socreset

Redis中的Set结构与Java中的HashSet如出一辙,可一看做一个value为null的HashTable,本质上也是通过Hash表实现去重。

ZSet或者叫SocreSet,是基于set数据结构基础之上增加score属性并按score排序的数据结构。因为可排序且元素不重复的特性通常用作排行榜等功能。

本质上是依赖两个核心数据结构,ziplist压缩链表skiplist跳跃链表实现。八股背的越多忘得越多,只需要背核心的哪些点即可。

ziplist

  • ziplist本质上是字节数组,每个元素可以是一个字节数组或一个整数。占用一块完整的内存,空间连续,避免内存碎片,节省内存

  • 对值存储采用变长形式,根据大小调整存储字节大小

  • 基础结构

    1. zlbytes:记录整个ziplist的大小。

    2. zltail:ziplist开始指针与最后一个entry之间的偏移量,通过该偏移量可以获得最后一个entry。

    3. zllen:entry数量。

    4. entry:存储具体数据的节点。

      • prelen:上一个entry的大小。
      • encoding:记录content的类型以及长度。
      • content:一个整形或者字节数组。
    1. zlend:ziplist结尾标识。

image.png

  • 总结

    • 本质为占用一段完整内存字节数组,空间连续避免内存碎片

    • 每个节点通过保存特殊节点位置实现双向链表特性

    • 新增元素可能会引起连锁更新(类似数组,引发后续下标变动)

skiplist

本质上由Node节点构造成的多层链表结构,每层都是有序链表,最底层包含所有元素,上下层元素比例约为1:2

  1. 通过空间换时间的思想,在原有的有序链表中增加多级索引,每个元素包含多指针,指针个数通过"丢硬币"的方式实现基本满足二分概率1/2,每丢一次指针个数+1,指向下一层的元素,直到扔到反面为止
  2. 新增删除操作需要把后面的节点都更新一遍
  3. redis为什么使用跳表而不是用红黑树
    1. 内存占用更少,自定义参数化决定使用多少内存
    2. 查询性能至少不比红黑树差
    3. 简单更容易实现和维护

image.png

总结

  1. 基于ziplist或skiplist
  2. 符合以下条件使用ziplist
    1. 服务器属性server.zset_max_ziplist_entries 的值大于 0
    2. 元素的member长度(成员长度)小于服务器属性server.zset_max_ziplist_value的值(默认64)
  1. 不符合使用skiplist