还能更快吗?Redis的quicklist完美诠释“多快好省”

概览

Redis 3.2 版本前,列表的底层是采用 linkedlist 与 ziplist 作为数据结构实现,而在 3.2 版本之后则改为了 quicklist。

那 quicklist 究竟是什么样的数据结构,出现的原因又是什么?

这要源于 2014 年,一个名为 mattsta 的大佬给 Redis 提了一个 PR,号称自己实现了 twitter 之前所描述的一种非常高效的数据结构,而这种数据结构是链表与 ziplist 的结合体,原文如下:

My implementation of what Twitter has previously described as ziplists in a linked list for better memory efficiency.

Longer writeup with improvement graphs at https://matt.sh/redis-quicklist

PR 的链接:https://github.com/redis/redis/pull/2143。

首先 quicklist 是基于时间和空间效率上权衡的一个产物,原因如下:

  • linkedlist 在插入,删除节点时有较高的效率,但当数据规模较小时,空间的利用率很低(节点需要额外存储指针信息)
  • ziplist 拥有较高的空间利用率,但在数据规模较大时,它的插入,删除效率会大大降低(需要进行大范围的内存重分配操作)

quicklist 取长补短,既吸收了 ziplist 的内存压缩特性,又保持了 linkedlist 高效率增删节点的特性,因此 Redis 在 3.2 版本之后直接用 quicklist 作为列表的底层数据结构,替代了原本的 linkedlist 与 ziplist。

本文主要讲述 quicklist 的底层实现原理,揭秘它为何既“快”又“稳”。

数据结构

quicklist 本质是双向链表和压缩列表的结合体,整体数据结构模型如下:

数据结构如下:

  • head,tail 为头尾节点指针
  • count,所有 ziplist 中的 entry 总数
  • len,quicklist 节点总数
  • fill 属性,控制 ziplist 节点的最大容量,如果 fill 属性设置过大,quicklist 会退化成 ziplist
  • compress 属性,控制压缩深度,防止不必要的压缩工作(quicklist 会对部分节点,通过 LZF 算法进行压缩)

quicklistNode 节点的数据结构如下:

  • prev,next 指针分别指向前后节点
  • zl,指向节点对应的 ziplist
  • count,ziplist 中存储的数据量
  • encoding,数据类型编码 RAW1 or LZF2,标识节点数据是否被压缩

下面主要讲解 quicklist 的数据更新实现逻辑。

数据插入(头插和尾插)

头插和尾插相对更简单些:

  • 如果头/尾节点的 ziplist 空间未满(通过 fill 属性判断),则直接将数据插入对应的 ziplist 中
  • 如果头/尾节点的 ziplist 空间已满,则需要新建节点

如下图所示,往链表头部插入数据项,但头结点的 ziplist 数据已满,则生成新的头结点,将数据插入新生成的节点中,往尾部插入数据也同理。

数据插入(特定位置插入)

往特定位置插入就复杂多了,涉及多种情况。

1.如果当前被插入节点不满,直接插入;

2.如果当前被插入节点是满的,要插入的位置是当前节点的尾部,且后一个节点有空间,那就插入到后一个节点的头部,如下图所示;

3.如果当前被插入节点是满的,要插入的位置是当前节点的头部,且前一个节点有空间,那就插入到前一个节点的尾部,如下图所示;

4.如果当前被插入节点是满的,前后节点也都是满的,要插入的位置是当前节点的头部或者尾部,那就创建一个新的节点插进去,如下图所示;

5.如果当前节点是满的,且要插入的位置在当前节点的中间位置,我们需要把当前节点分裂成两个新节点,然后再插入,如下图所示;

数据删除

删除相对于插入而言就简单多了,直接把 ziplist 对应位置数据删除,并没有节点合并的操作。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值