一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
关于Redis内部编码的转换,都符合以下规律:
编码转换在Redis写入数据时完成,且转换过程不可逆,只能从小内存编码向大内存编码转换。(不包括重新set)
1、字符串
核心
- Redis所有的键都是字符串类型
- 字符串之外的其他几种复杂类型的元素也是字符串。
- 字符串长度不能超过512MB。
内部编码
字符串类型的内部编码应用场景:
1、int:8个字节的长整型。字符串值是整型时,这个值使用long整型表示。
2、embstr:<=39字节的字符串。
3、raw:大于39个字节的字符串
embstr和raw有什么区别?
相同点:
- embstr与raw都使用redisObject和sds保存数据, 不同点:
- embstr 申请一次内存空间, 因为 RedisObject 和 SDS 是连续的
- embstr 删除释放一次空间内存空间
- embstr RedisObject 和 SDS 连在一起, 查找方便
- embstr 扩容只读
- raw 申请两次内存空间, 分别为 RedisObject 和 SDS 申请内存空间
- raw 删除释放两次内存空间
- raw RedisObject 和 SDS 不在一起, 查找不方便
- raw 可单独为 RedisObject 和 SDS 扩容
结论:
-
embstr的好处在于创建时少分配一次空间,删除时少释放一次空间,以及对象的所有数据连在一起,寻找方便
-
embstr的坏处也很明显,如果字符串的长度增加需要重新分配内存时,整个redisObject和sds都需要重新分配空间,因此redis中的embstr实现为只读。
-
embstr和raw进行区分的长度,是39;是因为redisObject的长度是16字节,sds的长度是9+字符串长度;因此当字符串长度是39时,embstr的长度正好是16+9+39=64,jemalloc正好可以分配64字节的内存单元。
(3) int 和 embstr 转化为 raw 之间编码转换
-
当 int 数据不再是整数, 或大小超过了 long 的范围 (2^63 - 1) 时, 自动转化为 raw
-
由于 embstr 是只读的, 因此在对 embstr 对象进行修改时, 都会先转化为 raw 再进行修改, 无论是否达到了 44 个字节