Redis中的压缩列表(连锁更新)

Redis中压缩列表(ziplist)用于存储小规模数据,如列表和哈希键。压缩列表由节点组成,每个节点包含previous_entry_length、encoding和content。previous_entry_length字段可能导致连锁更新,即当节点长度变化时,影响后续节点的长度表示,可能导致多次空间重分配,最坏情况下复杂度为O(N^2)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

压缩列表的应用

压缩列表(ziplist)是列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,那么redis就会使用压缩列表来做列表键的底层实现。

redis> RPUSH lst 1 3 5 10086 "hello" "world"
(integer)6

redis> OBJECT ENCODING lst
"ziplist"

另外,当一个哈希键只包含少量键值对,并且每个键值对的键和值要么就是小整数值,要么就是长度较短的字符串,那么Redis就会使用压缩列表来做哈希键的底层实现。


redis> HMSET profile "name" "Jack" "age" 28 "job" "Programmer"
OK
redis> OBJECT ENCODING profile
"ziplist"

压缩列表的构成

压缩列表(ziplist)是列表和哈希的底层实现之一。当列表只包含少量的列表项,并且每个列表项要么是小整数值,要么就是长度比较短的字符串,那么redis就会使用压缩列表来做列表的底层实现。哈希同样。

压缩列表由一系列特殊编码的连续内存块组成的顺序型(sequential)数据结构。一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。

在这里插入图片描述

在这里插入图片描述

压缩列表结点的构成

每个压缩列表可以保存一个字节数组或者一个整数值。每个节点由previous_entry_length,encoding以及content组成。

在这里插入图片描述

previous_entry__length记录前一个节点的长度,所以程序可以通过指针运算(当前节点的起始位置-previous_entry__length得到上一个节点的起始位置。),压缩列表从表尾遍历操作就是通过这个原理实现的。encoding属性记录节点的content属性所保存数据的类型以及长度。content保存节点的内容,可以是整数或者是字节数组。

previous_entry_length(重点)

● 如果前一节点的长度小于254字节,那么previous_entry__length属性的长度为1字节:前一节点的长度就保存在这一字节里面。
● 如果前一节点的长度大于等于254字节,那么previous_entry__length属性的长度为5字节:其属性的第一字节会被设置为0xFE(十进制254),而之后的四个字节长度则用于保存前一节点的长度。

连锁更新

连锁更新是由于previous_entry_length造成的。
现在考虑这样一种情况:在一个压缩列表中,有多个连续的,长度介于250字节到253字节之间的节点e1-eN,如下图:

在这里插入图片描述

因为e1到eN的长度都介于250字节到253字节之间,所以它们的previous_entry__length均为1字节。

现在将一个长度大于254字节的节点插入到e1前面,如下图:

在这里插入图片描述

因为newE的长度大于254字节,所以他后面的e1的previous_entry__length长度需要从1字节变为5字节。但是由于e1原本的长度为250字节到253字节之间,这样子扩展后,长度必然超过254字节,就会导致后面的e2的previous_entry__length也需要改变…以此类推,后面的节点的previous_entry__length都需要扩展。Redis将这种特殊情况下产生的连续多次空间扩展操作称之为"连锁更新"。

除了插入节点会发生"连锁更新"。删除节点也会,如下图:

在这里插入图片描述

假设small及后面的节点的长度都介于250-253字节,big长度大于254字节,现在把samll删除了,导致e1的previous_entry__length需要扩展,后面依此类推,这样就会发生"连锁更新"。

因为连锁更新在最坏的情况下需要对压缩列表执行N次空间重分配,而每次空间重分配的最坏复杂度为O(N),所以连锁更新的最坏复杂度为O(N^2).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值