当前位置: 首页 > news >正文

Redis字符串编码

在Redis的底层实现中,字符串类型并非采用单一的存储方式,而是根据数据的特性动态选择int、embstr和raw三种编码方式。这种灵活的编码设计是Redis实现高性能和内存高效利用的关键手段之一。本文将从编码触发条件、内存结构、核心优势及适用场景等方面,全面拆解Redis字符串的三种编码机制,带你理解其背后的优化逻辑。

一、为什么需要多编码方式?

Redis作为高性能的内存数据库,对内存利用率和操作效率有着极致的追求。如果采用统一的编码方式存储所有字符串数据,会导致严重的资源浪费或性能瓶颈:

  • 若用复杂结构存储简单整数,会产生大量内存冗余;
  • 若用灵活但开销较高的结构存储短字符串,会增加内存分配成本和CPU缓存开销;
  • 若用固定结构存储长字符串,会限制数据的修改灵活性。

因此,Redis针对不同数据场景设计了三种编码方式,实现“按需分配”的存储优化,在内存占用和操作性能之间找到最佳平衡。

二、三种编码方式的详细解析

(一)int编码:整数数据的高效存储

1. 触发条件

当字符串值是一个64位有符号整数时(取值范围:-9223372036854775808 ~ 9223372036854775807),Redis会自动采用int编码。例如存储"123""-456"这类纯整数字符串时,会被解析为整数并以int编码存储。

2. 内存结构

int编码的核心是“数据嵌入”,直接利用RedisObject的ptr字段存储整数值,无需额外分配内存空间。RedisObject的结构定义如下:

typedef struct redisObject {unsigned type:4;        // 数据类型(此处为 OBJ_STRING)unsigned encoding:4;    // 编码类型(此处为 OBJ_ENCODING_INT)unsigned lru:24;        // LRU 时间或 LFU 计数(用于内存淘汰)int refcount;           // 引用计数(内存回收机制)void *ptr;              // 指向数据的指针(int编码时直接存储整数值)
} robj;

由于ptr字段是指针类型(在64位系统中占8字节),恰好能容纳64位有符号整数,因此无需额外的SDS结构,实现了零额外内存开销。

3. 核心优势
  • 内存利用率极高:无需分配SDS结构体和数据缓冲区,直接复用RedisObject的ptr字段;
  • 操作效率高:对整数的增减、比较等操作无需进行字符串与整数的类型转换,减少性能损耗。
4. 限制

仅支持64位有符号整数,若存储的数值超出该范围或非整数(如浮点数"3.14"),会自动转换为其他编码。

(二)embstr编码:短字符串的性能优化方案

1. 触发条件

当字符串长度≤44字节(Redis 5.0及以上版本,不同版本阈值可能略有差异)且无法用int编码存储时,Redis会使用embstr编码。例如存储"hello world""user:1001"这类短文本字符串。

2. 内存结构

embstr编码的核心特点是“连续内存分配”,RedisObject和SDS结构体被分配在同一块连续的内存空间中。这种结构避免了内存碎片,同时提升了CPU缓存命中率——CPU在读取数据时,能一次性将RedisObject和SDS数据加载到缓存中。

3. 核心优势
  • 内存分配高效:仅需一次内存分配操作(对比raw编码的两次分配),减少系统调用开销;
  • 缓存友好:连续的内存布局降低了CPU缓存缺失的概率,提升数据访问速度;
  • 内存碎片少:避免了RedisObject和SDS分散存储导致的内存碎片问题。
4. 限制

embstr编码的字符串不可修改。一旦执行修改操作(如APPENDSETRANGE),Redis会自动将其转换为raw编码,之后的操作都基于raw编码进行。

(三)raw编码:长字符串的通用存储方案

1. 触发条件

满足以下任一条件时,Redis会采用raw编码:

  • 字符串长度>44字节;
  • 字符串无法用int编码存储(如浮点数、包含特殊字符的字符串等)。
    例如存储长文本内容、JSON字符串、二进制数据等场景,都会使用raw编码。
2. 内存结构

raw编码采用“分离存储”模式,RedisObject和SDS结构体分别分配在不同的内存块中。RedisObject的ptr字段指向SDS结构体,SDS再存储实际的字符串数据。这种结构允许字符串进行动态修改,无需重新分配RedisObject的内存。

3. 核心优势
  • 支持动态修改:可自由执行追加、截断、替换等操作,无需转换编码;
  • 兼容性强:适用于所有非int编码的字符串场景,包括长文本和二进制数据;
  • 稳定性高:修改操作不会导致RedisObject的内存重分配,避免了关联数据的地址变更。
4. 不足
  • 内存分配开销较高:需要两次内存分配(分别分配RedisObject和SDS);
  • 内存连续性差:RedisObject和SDS分散存储,可能降低CPU缓存效率,且容易产生内存碎片。

三、三种编码的核心对比

为了更清晰地展示三种编码的差异,整理了以下对比表格:

编码类型

内存分配次数

内存连续性

适用场景

修改代价

int

1次(仅RedisObject)

连续(数据嵌入)

64位有符号整数

不可修改,修改需转为raw编码

embstr

1次(RedisObject+SDS)

连续

短字符串(≤44字节)

不可修改,修改需转为raw编码

raw

2次(分别分配RedisObject和SDS)

非连续

长字符串、二进制数据、浮点数等

支持动态修改,无编码转换代价

四、编码转换机制

Redis的编码转换是自动触发的,核心转换规则如下:

  1. int → raw:当对int编码的字符串执行修改操作(如APPEND "123" "4"),或存储的数值超出64位有符号整数范围时,会转为raw编码;
  2. embstr → raw:对embstr编码的字符串执行任何修改操作(如SETRANGE "hello" 1 "i"),会立即转为raw编码;
  3. raw → 其他编码:一旦转为raw编码,不会再自动转回int或embstr编码,即使后续数据被修改为符合int或embstr的条件(需手动重新设置值才能触发编码转换)。

五、总结

Redis字符串的多编码设计,充分体现了“因地制宜”的优化思想——针对整数、短字符串、长字符串的不同特性,设计了差异化的存储方案,在内存利用率和操作性能之间实现了精准平衡。

例如在存储用户ID、商品库存等整数字段时,可直接以整数形式存储以触发int编码;在存储短key(如"order:10086")时,利用embstr编码提升访问性能;在存储长文本或二进制数据时,接受raw编码的开销以换取修改灵活性。通过对编码机制的合理运用,能让Redis发挥出更优的性能。

http://www.dtcms.com/a/504366.html

相关文章:

  • React中的事件绑定
  • [嵌入式系统-152]:CAN总线最大数据只有8个字节,CAN FD最大才64个字节,这么小的数据量,如何进行稍大一点的数据传输?
  • 个人网站做论坛还是博客好广州网站备案公司
  • 仓颉 Markdown 解析库在 HarmonyOS 应用中的实践
  • 肇庆 网站建设ci设计
  • 小九源码-springboot089-在线学习平台
  • 申请域名就可以做网站了吗网站如何做的有气质
  • 乐陵市住房和城乡建设局网站济南建立网站
  • 旅游网页设计模板网站保定网站制作网页
  • C++类和对象(中):构造函数与析构函数的核心逻辑
  • 数据结构--顺序表的测试
  • Intel HD Graphics 2000可以在window 11 中使用openGL
  • 昆明网站建设网站一建论坛建工教育网
  • 建站宝盒设置wordpress 跳转到首页
  • PySide6 文本编辑(QTextEdit)查找功能进阶 读取并记录上一次状态
  • Vivado 增量综合检查点错误的排查与解决
  • 学院的网站怎么做自己怎么制作网页游戏
  • 哪家企业的网站做的好榆林微网站建设
  • 【嵌入式】环形缓冲区缓和读写速度差的原因分析
  • 聊城开发区建设局网站郑州聚商网络科技有限公司
  • 上海网站设计制作报价门头沟高端网站建设
  • 随州网站推广哪家权威织梦导航网站模板
  • Docker安装Elasticsearch、kibana、IK分词器
  • 银河麒麟V10 Docker安装
  • 聊城开发区建设局网站国家建设部官方网站赵宏彦
  • 十堰英文网站建设网站的空间域名
  • 【SpringCloud(6)】Gateway路由网关;zuul路由;gateway实现原理和架构概念;gateway工作流程;静态转发配置
  • 什么网站做简历模板网站开发用哪些技术
  • 电商网站主题html国庆节网页制作代码
  • 聊城网站制作公司wordpress通过标签获取文章