Redis压缩列表的详细介绍(示例讲解)

本篇文章给大家带来的内容是关于Redis压缩列表的详细介绍(示例讲解),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

此篇文章是主要介绍Redis在数据存储方面的其中一种方式,压缩列表。

本文会介绍

1、压缩列表(ziplist)的使用场景 

2.如何达到节约内存的效果?

3.压缩列表的存储格式 

4. 连锁更新的问题  

5. conf文件配置。

在实践上的操作主要是对conf配置文件进行配置,具体上没有确切的一个值,更多是经验值。也有的项目会直接使用原本的默认值。此篇对于更好地理解一个数据库底层的存储逻辑会有一点帮助。修学储能,既要博,也要渊。希望这篇文章对同样也是在学习Redis的各位同伴有点用。(推荐教程:Redis教程)

一、压缩列表(ziplist)的使用场景:

Redis为了优化数据存储,节约内存,在列表、字典(哈希键)和有序集合的底层实现了使用压缩列表这一优化方案。

例如,假如一个哈希键里面存储的字符串比较短,那么Redis就会将它用压缩列表的格式去存储,即转换为字节数组存储。而一个哈希键内部存储的整数值比较小,同样也会把它存储为压缩列表的一个节点。同理,列表键的对小数据的存储跟哈希键的操作类似。

如此说来,压缩列表并不是开发者可以直接调用的Redis中的一种存储数据结构,而是Redis中为优化数据存储而在底层做的一项努力。理解好这点还是比较重要的。

二、如何达到节约内存的效果?

压缩列表是一种序列化的数据结构,这种数据结构的功能是将一系列数据与其编码信息存储在一块连续的内存区域,这块内存物理上是连续的。但逻辑上被分为多个组成部分,即节点。目的是为了在一定可控的时间复杂度条件下尽可能的减少不必要的内存开销,从而达到节省内存的效果。需要理解是怎么达到节约内存作用的,还需要去了解压缩列表的存储格式。

三、压缩列表的存储格式:

压缩列表(ziplist)是Redis列表键、哈希键和有序集合键的底层实现之一,其实质是一种序列化的数据存储结构。有别于普通情况下,Redis用双端链表表示列表,使用散列表表示哈希键,用散列表+跳跃表表示有序集合。当一个列表或者哈希字典/有序集合只包含很少内容,并且每一个列表项或者哈希项/有序集合项如果是小整数,或者比较短的字符串。那么Redis就会用压缩列表来做底层的实现。

压缩列表由一系列经Redis特殊编码的连续内存块组成,每一个内存块称为一个节点(entry),而一个压缩列表可以包含很多个节点。每个节点存储的数据格式可以是字节数组(中文字符串等都会转换为字节数组)或者整数值。

字节数组的长度可以是以下的其中一种:

1. 长度小于等于63字节(2的6次方)

2. 长度小于等于16383字节(2的14次方)

3. 长度小于等于4294967295字节(2的32次方)

整数值可能是以下六种中的其中一种:

1. 4位长,介于0-12之间的无符号整数

2. 1字节长的有符号整数

3. 3字节长的有符号整数

4. int16_t类型整数

5. int32_类型整数

6. int64_t类型整数

普通存储格式下和压缩列表存储格式下的不同点:

列表存储结构典型的为双端链表,每一个值都是用一个节点来表示,每个节点都会有指向前一个节点和后一个节点的指针,以及指向节点包含的字符串值的指针。而字符串值又分为3个部分存储,第一部分存储字符串长度,第二部分存储字符串值中剩余可用的字节量,第三部分存储的则是字符串数据本身。所以一个节点往往都需要存储3个指针、2个记录字符串信息的整数、字符串本省和一个额外的字节。总体上额外的开销是很大的(21字节)。

压缩列表节点的格式:

Redis压缩列表的详细介绍(示例讲解)

每一个节点都有previous_entry_length,encoding,content三个部分组成,在遍历压缩列表的时候是从后往前遍历的。

1. previous_entry_length记录了前一个节点的长度,只要用当前指针减去这个值就可以达到前一个节点的起始地址。

2. encoding记录了节点content属性所保存数据的类型和长度

Redis压缩列表的详细介绍(示例讲解)

3. content记录了一个节点的值

显然压缩列表这种方式节约了不少存储空间。但同时也会引发下面的问题。

四、连锁更新的问题:

一般而言如果前一个节点的整体长度小于254字节,previous_entry_length属性只需要1个字节的空间来保存这个长度值。而当前一个节点大于254字节的时候,previous_entry_length属性要用5个字节长的空间来记录长度值。

当长度为254字节左右的节点前插入一个新的节点的时候,需要增加previous_entry_length来记录这个节点到新节点的偏移量。这个时候,这个节点的长度肯定就大于254字节了。所以这个节点的后一个节点就不能只用一个字节的previous_entry_length来记录这个节点的信息了,而是需要5个字节来记录。如果连续多个节点的长度都为254字节左右,在其中的某一个节点前/后发生节点的插入和删除(删除的推理与插入相反,原本用5字节记录前一节点的可能变为1字节),都可能引发连锁的更新,显然,这样对系统地运行效率是很不利的。不过,在实际应用中这种情况还是比较少发生的。

而双端链表在节点的更新、增加和删除上显得就会“轻松”很多了。 因为每一个节点存储的信息都是相对独立的。  

实践意义:

爱图表 爱图表

AI驱动的智能化图表创作平台

爱图表 99 查看详情 爱图表

要预估一个节点大概占据多少字节的存储空间,适当地调整字段的存储格式而不要使存储的字段值占据存储空间落在254字节(除去encoding属性和previous_entry_length属性)左右。

Redis中查看字符串和哈希键值的长度相关命令:

1. 查询字符串键对应的值长度

命令:

Strlen

例如:

127.0.0.1:6379> strlen m_name

(integer) 8

2. 查询哈希键某一个域长度

命令:

Hstrlen

例如:

127.0.0.1:6379> hstrlen good_list good_list1

(integer) 226

五、Conf文件配置:

通过修改配置文件,可以控制是否使用压缩列表存储相关键的最大元素个数和最大元素的大小

Conf文件中的配置:
1.

[] -max-ziplist-entries : 表示对于键的最大元素个数,即一个键中在该指定值下的数量的节点个数都会用压缩列表来储存

[] -max-ziplist-value :表示压缩列表中每个节点的最大体积是多少字节

实际使用中,一个列表键/哈希键的某一个元素往往存储着比较大的信息量,会大于64字节,所以配置时很有可能会比64大,同时考虑到实际存储数据的容量大小以及上面谈到的previous_entry_length的大小问题,对[] -max-ziplist-value进行合理的配置。

配置文件内容:

############## ADVANCED CONFIG ##########################哈希键# Hashes are encoded using a memory efficient data structure when they have a# small number of entries, and the biggest entry does not exceed a given# threshold. These thresholds can be configured using the following directives.hash-max-ziplist-entries 512hash-max-ziplist-value 64有序集合键# Similarly to hashes and lists, sorted sets are also specially encoded in# order to save a lot of space. This encoding is only used when the length and# elements of a sorted set are below the following limits:zset-max-ziplist-entries 128zset-max-ziplist-value 64列表键,比较特殊,直接使用制定大小kb字节数表示(有些conf文件的列表键与hash键的表达式没太大区别)# Lists are also encoded in a special way to save a lot of space.# The number of entries allowed per internal list node can be specified# as a fixed maximum size or a maximum number of elements.# For a fixed maximum size, use -5 through -1, meaning:# -5: max size: 64 Kb  <-- not recommended for normal workloads# -4: max size: 32 Kb  <-- not recommended# -3: max size: 16 Kb  <-- probably not recommended# -2: max size: 8 Kb   <-- good# -1: max size: 4 Kb   <-- good# Positive numbers mean store up to _exactly_ that number of elements# per list node.# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),# but if your use case is unique, adjust the settings as necessary.list-max-ziplist-size -2

案例:

修改配置前使用默认配置:

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

127.0.0.1:6379> hstrlen good_list good_list1

(integer) 226

127.0.0.1:6379> object encoding good_list

“hashtable”

修改配置:

hash-max-ziplist-entries 512

hash-max-ziplist-value 254

注意:修改配置后需要重启服务器

127.0.0.1:6379> hstrlen good_list good_list1

(integer) 226

127.0.0.1:6379> object encoding good_list

“ziplist”

可以看到存储方式已将变为ziplist

较官方的压力测试和指导建议:

当一个压缩列表的元素数量上升到几千(实际使用可能远小于这个值)的时候,压缩列表的性能可能会下降,因为Redis在操作这种结构的时候,编解码会出现一定的压力。

压缩列表的长度限制在500-2000之内,每个元素体积限制在128字节或以下,压缩列表的的性能都会处于合理范围之内。

以上就是Redis压缩列表的详细介绍(示例讲解)的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/376789.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
钉钉消息重复怎么办 钉钉消息刷新与去重方法
上一篇 2025年11月6日 09:58:24
6.5k Star开源让每个人都简单方便的使用前沿人工智能技术
下一篇 2025年11月6日 09:58:28

相关推荐

  • 如何用Golang构建无状态微服务 分享Session管理最佳实践

    如何用Golang构建无状态微服务 分享Session管理最佳实践如何用Golang构建无状态微服务 分享Session管理最佳实践如何用Golang构建无状态微服务 分享Session管理最佳实践如何用Golang构建无状态微服务 分享Session管理最佳实践

    构建无状态微服务时,session管理可通过jwt、redis和统一认证中心实现。①使用jwt作为token,客户端存储,服务端无状态;②结合redis记录session元数据,支持主动失效;③设立统一认证中心,中间件校验token;④确保https传输安全并设计token刷新机制。 用 Golan…

    2026年5月10日 用户投稿
    000
  • 怎样用Golang实现一个简单的键值存储 基于文件持久化方案

    怎样用Golang实现一个简单的键值存储 基于文件持久化方案怎样用Golang实现一个简单的键值存储 基于文件持久化方案怎样用Golang实现一个简单的键值存储 基于文件持久化方案怎样用Golang实现一个简单的键值存储 基于文件持久化方案

    要实现一个简单的键值存储系统,需结合golang与文件持久化方案。1. 使用map[string]string作为内存数据结构,选择json或gob进行序列化;2. 围绕map实现crud操作,写入后立即或定时刷新到磁盘,并在启动时加载数据;3. 文件策略可选每次写入刷盘、定时异步刷盘或日志记录变更…

    2026年5月10日 用户投稿
    000
  • C#的System.IO.Pipelines是什么?如何实现高性能的流处理?

    System.IO.Pipelines通过PipeReader和PipeWriter减少内存分配与拷贝,高效处理流数据,适用于高吞吐、低延迟场景如网络通信和协议解析。 System.IO.Pipelines 是 C# 中用于高效处理流数据的一个库,特别适合高吞吐、低延迟的场景,比如网络通信、文件解析…

    2026年5月10日
    100
  • WebSocket消息队列处理性能优化

    优化WebSocket性能需解耦通信与业务逻辑,通过消息队列异步处理、二进制序列化、数据压缩、批量发送及动态心跳机制,提升吞吐量并降低延迟。 处理WebSocket消息时,性能瓶颈常出现在消息的接收、处理和分发环节。优化核心在于解耦通信与业务逻辑,并高效管理消息流。 引入消息队列进行异步解耦 直接在…

    2026年5月10日
    000
  • Laravel Session::put 正确用法详解与常见误区规避

    本文详细探讨了 laravel 中 `session::put` 方法的正确用法,特别指出在仅提供键名而未指定值时可能导致会话数据未被正确设置的问题。通过示例代码,阐述了如何为会话数据赋予明确的值,并演示了如何正确地检查和获取会话数据,以确保会话管理功能按预期工作,有效避免常见的会话操作错误。 La…

    2026年5月10日
    000
  • PHP大型配置管理:结构化数据与外部文件实践

    本文旨在探讨在php项目中高效管理大量配置项的最佳实践。我们将摒弃直接创建数百个独立php变量或在配置文件中混合代码的低效方式,转而介绍如何利用php数组以及ini、json、yaml等外部结构化数据格式来组织和加载配置,并结合业务逻辑进行处理,从而提升代码的可维护性、可扩展性和专业性。 在PHP应…

    2026年5月10日
    100
  • php调用视频处理功能_php调用FFmpeg处理视频文件

    答案:PHP通过exec()等函数调用系统FFmpeg命令实现视频处理。需先安装FFmpeg,再使用exec()执行转码、截图、裁剪等操作,如截图示例:ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 cover.jpg;常见操作包括格式转换、分辨率调整、音频提…

    2026年5月10日
    000
  • 深度剖析 Go 语言在分布式缓存开发中的常见技术问题

    在使用 go 语言开发分布式缓存时,我们会遇到并发访问、数据一致性和性能优化等技术问题。1) 并发访问可通过 sync.mutex、sync.rwmutex 或 sync.map 解决,但高并发下可能需使用分片锁优化。2) 数据一致性可通过先更新数据库再更新缓存的方式实现,但在高并发下需引入分布式锁…

    2026年5月10日
    000
  • php调用数据同步方案_php调用多数据库数据同步

    首先明确同步需求与模式,如单向、双向、定时或实时同步;接着使用PHP通过PDO连接多数据库,基于时间戳或增量ID同步变更数据,并记录同步状态;为提高可靠性,可引入消息队列、binlog解析、中间同步层及加锁机制;最后注意网络超时、分页处理、错误重试、日志记录与测试验证,确保数据一致性与系统稳定性。 …

    2026年5月10日
    000
  • HTML表单如何实现白名单功能?怎样只允许授权用户?

    要实现%ignore_a_1%的白名单功能并确保只有授权用户操作,核心答案是必须依赖后端服务器进行严格的身份认证、会话管理、授权检查和数据验证,前端仅能提供用户体验层面的初步提示而不能保障安全;具体而言,首先通过用户身份认证(如用户名/密码或oauth)确认用户身份,服务器创建会话并返回标识符,后续…

    2026年5月10日
    800
  • 如何使用Go语言编写高性能键值对存储器?

    Go语言高性能键值存储方案探讨 本文探讨如何使用Go语言构建一个高性能的键值对内存存储,类似于Redis。许多开发者首先想到的是使用map,但Go的map并非线程安全。虽然sync.Map解决了这个问题,但其性能是否最佳仍存在争议。因此,我们需权衡sync.Map、第三方concurrentMap以…

    2026年5月10日
    100
  • PHP代码怎么压缩文件_ PHP文件压缩库调用与解压方法

    答案:PHP处理文件压缩解压主要使用ZipArchive类,可创建或提取ZIP文件,结合PharData和zlib扩展支持TAR、GZ等格式;需注意内存、执行时间、权限及文件名编码问题。 PHP代码要压缩或解压文件,核心是利用PHP内置的 ZipArchive 类。这个类提供了相当全面的功能,无论是…

    2026年5月10日
    000
  • 优化字符串查找:内存映射 vs. 数据库查询

    在Go服务器应用开发中,经常会遇到需要对接收到的字符串进行验证的场景,例如验证字符串是否存在于数据库中。针对高并发的HTTP请求,如何高效地进行字符串查找是一个关键问题。通常有两种策略:一是每次请求都执行SQL查询;二是将所有字符串预先加载到内存中的Map,然后通过Map进行快速查找。选择哪种策略取…

    2026年5月10日
    000
  • Golang微服务健康检查与自动恢复技巧

    Golang微服务通过/healthz端点实现健康检查,返回200或500状态码;2. 检查内容包括服务状态、依赖连接和资源使用;3. 与Consul或Kubernetes联动,利用liveness/readiness探针触发恢复;4. 内置自愈逻辑如协程重启、连接重连,配合退避策略;5. 健康检查…

    2026年5月10日
    000
  • PHP源码缓存机制实现_PHP源码缓存机制实现教程

    Opcode缓存是PHP性能优化的核心机制,通过将PHP脚本编译后的Opcode存储在共享内存中,避免每次请求重复解析和编译,显著降低CPU和I/O开销。首次请求时Zend引擎将PHP代码编译为Opcode并由OPcache等扩展存入共享内存;后续请求直接从内存加载Opcode执行,跳过文件读取与编…

    2026年5月10日
    100
  • Golang缓存机制提升访问效率实践

    使用sync.Map实现内存缓存,结合TTL过期与LRU淘汰策略,可有效提升高并发下Golang服务性能,减少数据库压力。 在高并发服务场景中,频繁访问数据库或远程接口会显著影响响应速度和系统负载。Golang 作为高性能语言,天然适合构建高效缓存机制来减少重复计算和外部依赖调用。通过合理使用内存缓…

    2026年5月10日
    000
  • 如何在Golang中实现购物车功能

    答案:通过定义用户、商品和购物项结构体,使用map管理购物车条目,实现添加、删除、计算总价功能,并结合HTTP接口与读写锁支持并发操作,适合扩展优惠券与库存校验。 在Golang中实现购物车功能,关键在于管理用户、商品和购物项之间的关系。通常使用结构体来表示数据模型,结合内存存储或数据库完成增删改查…

    2026年5月10日
    100
  • Golang性能优化的基本原则是什么 解析高效Go代码的核心准则

    go程序中常见的内存优化策略包括预分配切片容量、使用strings.builder或bytes.buffer进行字符串拼接、利用sync.pool复用对象以减少gc压力、避免大对象的值传递而改用指针传递、复用缓冲区以减少临时对象分配,以及警惕切片或字符串切片操作导致的底层数组隐式引用内存泄漏,这些策…

    2026年5月10日
    000
  • Laravel 会话机制详解:如何识别用户会话

    本文旨在深入解析 Laravel 框架中的会话管理机制,揭示 Laravel 如何利用 cookie 在服务器端存储会话数据,并准确地识别和恢复每个用户的会话。通过本文,你将了解 Laravel 会话的工作原理,以及如何利用它来构建安全可靠的 Web 应用程序。 Laravel 的会话管理系统建立在…

    2026年5月10日
    000
  • Golang微服务如何实现动态扩缩容

    Go微服务通过容器化与Kubernetes实现动态扩缩容,需具备无状态设计、健康检查与优雅关闭;利用HPA基于CPU或Prometheus业务指标自动调整Pod副本数,结合Service与Ingress实现负载均衡,由平台完成弹性调度。 Go语言编写的微服务实现动态扩缩容,核心依赖于容器化部署与编排…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信