Redis存储string里面embstr和raw格式区别
文章目录
- Redis 字符串存储揭秘:embstr 与 raw 格式深度解析
- 核心区别:内存分配与效率
- 编码转换的临界点
- 如何查看字符串的编码?
- 总结
Redis 字符串存储揭秘:embstr 与 raw 格式深度解析
在 Redis 中,String(字符串)是最基础也是最常用的数据类型。然而,为了极致地优化内存使用和执行效率,Redis 在内部并不会用同一种方式来存储所有的字符串。其中,embstr
和 raw
是两种主要的编码格式,它们的选择取决于字符串的长度,并直接影响着内存分配和操作效率。
简而言之,embstr
是一种专门用于存储短字符串的优化格式,而 raw
则是用于存储长字符串的通用格式。
核心区别:内存分配与效率
embstr
和 raw
格式最根本的区别在于它们的内存分配策略。
-
raw
格式:两次内存分配
当一个字符串使用raw
格式存储时,Redis 会进行两次内存分配。一次是为 Redis 的对象头(redisObject
)分配内存,另一次是为字符串的实际内容(sdshdr
,即简单动态字符串)分配内存。redisObject
中的指针会指向存储实际字符串内容的sdshdr
。(对sdshdr有疑问的可以参考末尾文章链接!) -
embstr
格式:一次内存分配
为了优化短字符串的存储,embstr
格式应运而生。它通过一次内存分配,将redisObject
和sdshdr
存储在一块连续的内存空间中。这种方式不仅减少了内存分配的开销,更重要的是,由于数据在内存中的连续性,能够更好地利用 CPU 缓存,从而提升了访问效率。
特性 | embstr | raw |
---|---|---|
内存分配 | 一次(redisObject 和 sdshdr 连续存储) | 两次(redisObject 和 sdshdr 分开存储) |
内存碎片 | 更少 | 可能产生更多碎片 |
访问效率 | 更高(更好的 CPU 缓存局部性) | 相对较低 |
适用场景 | 短字符串 | 长字符串 |
修改操作 | 只读,任何修改都会先转换为 raw 格式 | 可直接修改 |
编码转换的临界点
Redis 会根据字符串的长度自动选择使用 embstr
还是 raw
编码。这个长度阈值在不同的 Redis 版本中有所变化:
- Redis 3.2 及以后版本: 当字符串长度小于等于 44 字节时,使用
embstr
编码。 - Redis 3.2 以前版本: 这个阈值是 39 字节。
需要特别注意的是,embstr
编码是只读的。一旦你对一个使用 embstr
编码的字符串进行任何修改操作(例如 APPEND
),Redis 会先将其转换为 raw
编码,然后再执行修改。即使修改后的字符串长度仍然小于44字节,它也会保持为 raw
编码。
如何查看字符串的编码?
你可以通过 OBJECT ENCODING
命令来查看一个键所对应的字符串的内部编码。
示例:
redis> SET short_str "hello world"
OK
redis> OBJECT ENCODING short_str
"embstr"redis> SET long_str "This is a longer string that will exceed the embstr length limit."
OK
redis> OBJECT ENCODING long_str
"raw"redis> APPEND short_str " again"
(integer) 17
redis> OBJECT ENCODING short_str
"raw"
总结
embstr
和 raw
格式是 Redis 在字符串存储上进行精细化优化的体现。通过为短字符串设计专门的 embstr
格式,Redis 有效地减少了内存分配开销和内存碎片,并提升了数据访问的效率。了解这两种内部编码的区别,有助于我们更深入地理解 Redis 的高性能原理,并在实践中更高效地利用内存。对于开发者而言,虽然这种转换是自动且透明的,但理解其背后的机制,对于进行性能分析和故障排查大有裨益。
下一篇:
Redis中什么是SDSHDR