String 的三种编码是什么
Redis 的 String 在内部有三种编码:纯整数字符串用 int(还能共享小整数对象,最省内存)、长度不超过 44 字节的短字符串用 embstr(对象头与数据一次分配)、更长的字符串用 raw(两次分配)。编码由 Redis 自动选择,用 OBJECT ENCODING 可以查看。关键点是切换通常单向:embstr 一旦被 APPEND 修改就会变成 raw 且不会再变回去。
基本信息
| 适用版本 | Redis 2.6+ 已有 embstr,Redis 7.x 阈值与实现细节略有差异 |
|---|---|
| int | 长整数字符串,可复用共享对象 |
| embstr | 长度 ≤ 44 字节,只读小字符串,一次内存分配 |
| raw | 长度 > 44 字节或已被修改过的字符串 |
| 查看命令 | OBJECT ENCODING key、MEMORY USAGE key |
| 权限 | 普通客户端即可执行 |
典型使用场景
- 内存优化排查:确认大量短字符串是否仍是 embstr 而不是被改成 raw
- 缓存设计评审:评估键值长度是否跨越编码阈值导致内存上升
- 对比不同集群的内存占用差异:编码差异常常是主因之一
- 排查热点键:结合 OBJECT 命令与采样分析单键开销
- 验证序列化方案:评估 JSON 与紧凑格式在内存上的差异
观察编码变化
观察编码变化
SET n 12345
OBJECT ENCODING n # int
SET s "hello"
OBJECT ENCODING s # embstr
APPEND s "-world-0123456789012345678901234567890123456789"
OBJECT ENCODING s # raw(追加后变长,且不会再变回 embstr)
SET big "$(python3 -c 'print("a"*100)')"
OBJECT ENCODING big # raw
MEMORY USAGE s # 对比不同编码下的实际占用编码对照
| 编码 | 产生条件 | 内存特点 |
|---|---|---|
| int | 值可解析为 64 位长整数 | 最省,且可复用共享对象 |
| embstr | 字符串长度 ≤ 44 字节 | 一次分配,读写紧凑 |
| raw | 长度 > 44 字节,或经 APPEND / SETRANGE 修改 | 两次分配,额外内存开销 |
| 阈值边界 | 44 字节是历史实现值,随版本略有差异 | 跨版本迁移后编码可能不同 |
编码是自动选择的,业务无法直接指定;能做的优化是控制值的长度与修改方式:短字符串尽量整体 SET 而不是 APPEND,需要频繁拼接的数据考虑 Hash 或分段存储。
大量键的内存占用差异往往来自编码而非键数量:同样的业务数据,用 JSON 存与用紧凑格式存可能相差一倍以上,容量评审时以 MEMORY USAGE 实测为准,不要只按字符数估算。