首页 > 数据库 >Redis数据结构4:REDIS_ZIPLIST

Redis数据结构4:REDIS_ZIPLIST

时间:2023-12-13 19:31:32浏览次数:46  
标签:字节 encoding REDIS ZIPLIST Redis entry 长度 节点 254

REDIS_ZIPLIST

zipList(压缩列表)是一种紧凑型的数据结构,占用一片连续的内存,本质上是一个字节数组。能提高CPU缓存的利用效率,并且针对不同数据结构进行不同编码,节省内存开销。

编码结构

zipList的字节数组主要由5个部分组成:zlbyteszltailzllenzltailentry

6.png

  • zlbytes 记录了整个zipList占用的内存大小。
  • zltail 记录了整个zipList尾结点距离起始地址的字节数,也可认为是列表尾的offset(偏移量)。
  • zllen 记录了压缩列表的entry数量
  • zlend 记录了zipList的结束点,固定值为0xFF(十进制下的255)。

entry

entry是zipList的有效存储模块,其中entry又分为三部分:prevlenencodingdata

7.png

  • prevlen 记录了前一个entry的长度,目的是为了实现从后向前遍历
  • encoding 记录了当前节点实际数据的类型和长度,类型主要有两种:字符串和整数。
  • data 记录了当前节点的实际数据,类型和长度都由 encoding 决定。

对于entry来说:

如果前一个entry的长度小于254字节,那么prelen就会采用1个字节。

如果前一个entry的长度大于254,prelen就采用5个字节:第一个字节会被设置为0xFE(十进制的254),之后的四个字节则用于保存前一个节点的长度。

对于encoding来说:

encoding的空间大小跟数据是字符串还是整数,以及字符串的长度有关。

8.png

  • 如果当前节点的数据是整数,则 encoding 会使用 1 字节的空间进行编码,也就是 encoding 长度为 1 字节。通过 encoding 确认了整数类型,就可以确认整数数据的实际大小了,比如如果 encoding 编码确认了数据是 int16 整数,那么 data 的长度就是 int16 的大小。
  • 如果当前节点的数据是字符串,根据字符串的长度大小,encoding 会使用 1 字节/2字节/5字节的空间进行编码,encoding 编码的前两个 bit 表示数据的类型,后续的其他 bit 标识字符串数据的实际长度,即 data 的长度。

连锁更新问题

连锁更新问题是指:在极端情况下,在修改 entry 的 data 时,data长度过高,zipList需要重新分配内存空间。

当新插入的元素较大时,可能会导致后续元素的 prevlen 占用空间都发生变化,从而引起连锁更新问题,导致每个元素的空间都要重新分配,造成访问压缩列表性能的下降。

该问题主要是因为 prevlen 会根据前一个节点的长度进行不同的空间大小分配

如果前一个节点的长度小于 254 字节,那么 prevlen 属性需要用 1 字节的空间来保存这个长度值;如果前一个节点的长度大于等于 254 字节,那么 prevlen 属性需要用 5 字节的空间来保存这个长度值。

现在设一个zipList中有多个连续且长度在 250~253 之间的节点,这些节点的长度都小于254prelen 使用1个字节的空间保存长度值。我们设这第一个元素为E1。

这时,如果将一个长度大于等于 254 字节的新节点加入到压缩列表的表头节点。因为原E1的prelen只有一个字节,无法保存新插入的结点,那么此时prelen需要从1扩大到5字节。

而此时E1的长度也大于了254,那么后续节点都需要逐步扩大prelen,扩大prelen又导致了新的后节点变化。像多米诺骨牌一样产生的连续多次空间扩展

反之,在删除节点时也可能导致连锁更新。

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

但因为大规模连锁更新的情况过于极端,且小规模连锁更新并不影响性能,所以不必过于担心。

Redis也并未对此种情况提出相应解决方案。

标签:字节,encoding,REDIS,ZIPLIST,Redis,entry,长度,节点,254
From: https://blog.51cto.com/ErickRen/8805638

相关文章

  • Redis实战篇
    Redis实战篇开篇导读短信登录这一块我们会使用redis共享session来实现商户查询缓存通过本章节,我们会理解缓存击穿,缓存穿透,缓存雪崩等问题,让小伙伴的对于这些概念的理解不仅仅是停留在概念上,更是能在代码中看到对应的内容优惠卷秒杀通过本章节,我们可以学会Redis的计数......
  • 2023最新中级难度Redis面试题,包含答案。刷题必备!记录一下。
    好记性不如烂笔头内容来自面试宝典-中级难度Redis面试题合集问:请解释Redis中的持久化机制RDB和AOF的区别,并谈谈你在实际应用中的选择。Redis的两种持久化机制分别为RDB和AOF:RDB(RedisDatabase)是Redis默认的持久化方式,会在指定的时间间隔内将内存中的数据集快照写入磁盘......
  • 2023最新初级难度Redis面试题,包含答案。刷题必备!记录一下。
    好记性不如烂笔头内容来自面试宝典-初级难度Redis面试题合集问:请简单介绍一下Redis,以及它主要用于解决什么问题?Redis是一款键值存储系统,也被称为“内存数据库”,其主要特点是在内存中高速存储数据。它的优点在于其极高的读写速度和较低的延迟,因此常被用来作为缓存、队列......
  • Redis
    入门Redis是一种基于Key-Value键值对的在内存数据库。版本号第二位是奇数则是非稳定版本,偶数则为稳定版本。常用命令命令作用redis-server/myredis/redis7.conf启动Redisredis-cli-a159123zxc-p6379连接Redisquit退出Redis界面,此时Redis仍在运行shu......
  • Redis内存分析工具-RDBtools安装&使用
    目录是什么安装安装Python(已安装忽略,低版本需要卸载重安)安装GCC(已安装忽略)安装rdbtools和python-lzf安装成功页面基础命令常用示例查找大key与处理导出CVS文件直连Redis服务查询单个key详情生成HTML图表更多用法见Help是什么Rdbtools提供了一组工具,可以帮助用户分析、导入和转换......
  • Springboot项目通过redis实现接口的幂等性
    在SpringBoot项目中,通过Redis实现接口的幂等性通常是通过在Redis中存储唯一标识符(token、UUID等)的方式来实现。当接口第一次被调用时,生成并存储一个唯一标识符到Redis,然后将该标识符返回给客户端。客户端在后续的请求中携带该标识符,服务端在处理请求之前检查Redis中是否存在该标识......
  • 【Centos】Centos 7.6 安装 Redis 7.2.3
    1  前言我们继续安装Redis。2 安装步骤2.1 下载压缩包https://redis.io/download/2.2 解压tar-xvfredis-7.2.3.tar.gz2.3 安装make2.4 启动./src/redis-server./redis.conf2.5 修改配置修改配置文件:redis.conf#绑定开放bind127.0.0.......
  • Redis进阶命令
    1.设置过期时间expire[keyName][seconds]eg:expirefoo60再次使用expire命令会重置键的过期时间。2.查看剩余过期时间ttl[keyName]eg:ttlfoottl表示timetolive3.使用事务连续执行一系列命令multi[command1][command2]...exec 4.排序可以对l......
  • Redis_基础
    Redis_基础SQL与NoSQL对比数据结构:结构化---非结构化数据关联:关联的---无关联查询方式:SQL查询---非SQL事务特性:ACID---BASE存储方式:磁盘---内存扩展性:垂直---水平使用场景:数据结构固定,相关业务对数据安全性、一致性要求较高---数据结构不固定,对一致性、安全性要求不高,对......
  • 【flink番外篇】3、fflink的source(内置、mysql、kafka、redis、clickhouse)介绍及示例(2
    Flink系列文章一、Flink专栏Flink专栏系统介绍某一知识点,并辅以具体的示例进行说明。1、Flink部署系列本部分介绍Flink的部署、配置相关基础内容。2、Flink基础系列本部分介绍Flink的基础部分,比如术语、架构、编程模型、编程指南、基本的datastreamapi用法、四大基......