Redis支持5种对象类型,而每种都至少有两种编码,这样做的好处在于:
一方面接口与实现分离,当需要增加或改变内部编码时,用户使用不受影响;另一方面可以根据不同的应用场景切换内部编码,提高效率。
Redis各种对象类型支持的内部编码如下图所示(部分)
关于Redis内部编码的转换,都符合以下规律:编码转换在Redis写入数据时完成,且转换过程不可逆,只能从小内存编码向大内存编码转换。
字符串
1.1 概况
字符串是最基础的类型,因为所有的键都是字符串类型,且字符串之外的其他几种复杂类型的元素也是字符串。
字符串长度不能超过512MB。
1.2 内部编码
字符串类型的内部编码有3种,它们的应用场景如下:
- int:8个字节的长整型。 字符串值是整型时,这个值使用long整型表示。
- embstr:<=44字节的字符串。 embstr与raw都使用redisObject和sds保存数据,区别在于,embstr的使用只分配一次内存空间(因此redisObject和sds是连续的),而raw需要分配两次内存空间(分别为redisObject和sds分配空间)。因此与raw相比,embstr的好处在于创建时少分配一次空间,删除时少释放一次空间,以及对象的所有数据连在一起,寻找方便。而embstr的坏处也很明显,如果字符串的长度增加需要重新分配内存时,整个redisObject和sds都需要重新分配空间,因此redis中的embstr实现为只读。
- raw:大于44个字节的字符串
127.0.0.1:6379> set key1 123
OK
127.0.0.1:6379> object encoding key1
"int"
127.0.0.1:6379> set key2 helloworld
OK
127.0.0.1:6379> object encoding key2
"embstr"
127.0.0.1:6379> set key2 helloworldhelloworldhelloworldhelloworld
OK
127.0.0.1:6379> strlen key2
(integer) 40
127.0.0.1:6379> object encoding key2
"embstr"
127.0.0.1:6379> set key3 helloworldhelloworldhelloworldhelloworldhell
OK
127.0.0.1:6379> strlen key3
(integer) 44
127.0.0.1:6379> object encoding key3
"embstr"
127.0.0.1:6379> set key4 helloworldhelloworldhelloworldhelloworldhello
OK
127.0.0.1:6379> strlen key4
(integer) 45
127.0.0.1:6379> object encoding key4
"raw"
1.3 编码转换
当int数据不再是整数,或大小超过了long的范围时,自动转化为raw。
而对于embstr,由于其实现是只读的,因此在对embstr对象进行修改时,都会先转化为raw再进行修改
因此,只要是修改embstr对象,修改后的对象一定是raw的,无论是否达到了44个字节。
127.0.0.1:6379> set key1 hello
OK
127.0.0.1:6379> object encoding key1
"embstr"
127.0.0.1:6379> append key1 .world
(integer) 11
127.0.0.1:6379> get key1
"hello.world"
127.0.0.1:6379> object encoding key1
"raw"
参考链接: