Redis7--ziplist的替代者listpack

vincent0809
发布于 2022-4-13 15:57
浏览
0收藏

转自公众号Redis开发运维实战

 

一、ziplist简介


ziplist是一种连续内存空间并且有序的压缩链表,其主要的数据结构如下图:Redis7--ziplist的替代者listpack-鸿蒙开发者社区

结合以上数据结构的内存模型图,我们可以看出ziplist具有的一些优势与问题:Redis7--ziplist的替代者listpack-鸿蒙开发者社区

 

二、listpack简介


由于ziplist存在不可避免的问题 -- 连锁更新问题, 所以在Redis 5版本中,推出了ziplist替代版本listpack。

 

1. ziplist整体的结构与listpack的整体结构对比

 

Redis7--ziplist的替代者listpack-鸿蒙开发者社区

从以上整体的对比图可以看到,其实两者结构相差不大,listpack相对于ziplist,没有了指向末尾节点地址的偏移量,这样也可以解决ziplist内存长度限制的问题

 

2. entry结构对比


其数据结构对比如下图:Redis7--ziplist的替代者listpack-鸿蒙开发者社区

从以上结构中可以看到,listpack移除了prevlen,在data后新增了backlen,两者有着本质区别:

 

● 在ziplist中,prevlen代表前一个entry节点长度的偏移量;
●  在listpack中,backlen代表的是本entry节点的回朔起始地址长度的偏移量


Entry这样设计具有以下一些优势

 

●  在遍历最后一个entry时可以通过lp+totallen快速定位到lp尾地址,然后使用backlen快速定位到last entry的起始地址;***并且可以将head中的last offset字段节省出来;
● 由于backlen仅代表了回朔本entry起始地址长度的偏移量,所以在增/删/改时,无需再关心前一个节点的长度,仅需要整体移动entry即可,所以不会涉及到内存的连锁更新;具体的代码流程这里不再复述;


三、listpack替换quicklist收益


1. list相关命令性能对比(quicklist with ziplist -> quicklist with listpack)

 

Redis7--ziplist的替代者listpack-鸿蒙开发者社区

从以上结果可以看到,lpush/rpush/lpop/rpop性能略有提升,这得益于listpack避免了连锁更新的问题,符合预期;但是lrange性能下降是因为在lpNext与lpGet函数中需要计算整个entry的长度(包括计算data长度与backlen)以及进行有效性验证,在代码逻辑上相较于ziplistNext/ziplistGet要复杂一些。

 

2. hash/zset类命令性能影响


由于hash与zset类命令,具有两种编码模式,默认为ziplist,在entry个数达到配置的默认值时,会将数据结构分别转换为hash与skiplist,所以在entry个数较少时,性能影响不大;entry个数越长、变更更频繁,新版本会具有更好的性能,而且在实际业务场景中,这个值都不会被配置的很大,所以这里也不再测试,仅从理论上推测性能影响。

 

3. 关于RDB的性能影响


由于ziplist和listpack都是一段连续的内存,所以在写入和加载上,性能不会有明显的差异。

 

4. RDB加载时ziplist转换为listpack时的耗时


低版本的RDB在redis7中加载时,会自动将ziplist转换为listpack,其整体加载耗时会大约增加 9%-54% 左右

 

具体耗时结果如下:

 

●  List(38%-46%)

Redis7--ziplist的替代者listpack-鸿蒙开发者社区

●  hash (29%-54%)

Redis7--ziplist的替代者listpack-鸿蒙开发者社区

● Zset (9%-16%)

Redis7--ziplist的替代者listpack-鸿蒙开发者社区

 

四、ziplist替换为listpack后带来的连锁变更


1. 相关配置变更


* 新增list-max-listpack-size, 是list-max-ziplist-size的别名;
* 新增hash-max-listpack-entries, 是hash-max-ziplist-entries的别名;
* 新增hash-max-listpack-value, 是hash-max-ziplist-value的别名;
* 新增zset-max-listpack-entries, 是zset-max-ziplist-entries的别名;
* 新增zset-max-listpack-value, 是zset-max-ziplist-value的别名;

 

由于新增配置均是别名,所以原有针对ziplist的相关配置,均可在redis7中自动生效,无需再做配置修改。

 

2. RDB相关


● RDB类型新增


  ◆ RDB_TYPE_HASH_LISTPACK
  ◆ define RDB_TYPE_ZSET_LISTPACK
  ◆define RDB_TYPE_LIST_QUICKLIST_2


●版本号提升至 10


由于RDB类型和版本号的变更,所以需要更新迁移工具,解析并支持新的类型。

 

五、参考链接


1、listpack migration --  https://github.com/redis/redis/issues/8702
2、replace ziplist with listpack in quicklist -- https://github.com/redis/redis/pull/9740/

3、Replace all usage of ziplist with listpack for t_hash --

https://github.com/redis/redis/pull/8887
4、Replace all usage of ziplist with listpack for t_zset --

https://github.com/redis/redis/pull/9366

 

 

文章转自公众号:Redis开发运维实战

分类
标签
收藏
回复
举报
回复
    相关推荐