参考:<<Redis设计与实现>>
- 注:这本书是基于Redis3.0版本写的,和后面的版本有点差异
字符串对象的编码可以是 int、embstr 或 raw。
- 如果一个字符串对象保存的是整数值,并且可以用long类型来表示,那么就会将整数值赋值给字符串对象结构里的ptr属性,以及将字符串对象的编码设置为int。
- 如果保存的是字符串,并且这个字符串值的长度大于39字节,那么字符串对象将使用SDS(简单动态字符串)保存,并将编码设置为raw。
- 如果保存的是字符串,并且这个字符串的长度小于等于39字节,那么字符串对象使用embstr编码方式来保存字符串值。
注:3.2版本开始,改为了以44字节作为临界值,原因是sdshdr结构改了,占用了更少的字节,可以参考下面博客的解释:
- https://blog.csdn.net/XiyouLinux_Kangyijie/article/details/78045385
- https://www.cnblogs.com/jianyungsun/p/10247607.html
字符串对象保存各类型值的编码方式如下表所示:
值 | 编码 |
---|---|
可以用 long 类型保存的整数 | int |
可以用 long double 类型保存的浮点数 | embstr 或 raw |
字符串值,或超过long类型范围的整数,或超过long double类型范围的浮点数 | embstr 或 raw |
一、字符串对象的编码
1.1 int编码的字符串对象
int编码的字符串对象,前提是整数,并且整数值在long类型范围内,否则仍然当作字符串来保存,int编码如下图所示:
示例:
使用object endocing key查看对象使用的编码
:
redis> set num 10086
redis> object encoding num
"int"
1.2 raw编码保存的字符串对象
使用redisObject结构和sdshdr结构来表示字符串对象。
示例:
保存一个长度大于39字节的字符串,使用object encoding key
命令查看使用的编码,可以看出使用了raw编码,
redis> set str "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
OK
redis> strlen str
(integer) 52
reeis> object encoding str
"raw"
raw编码的字符串对象如下图所示:
1.3 embstr编码保存的字符串对象
embstr编码是专门用于保存短字符串的一种优化编码方式,同样使用redisObject结构和sdshdr结构来表示字符串对象。
使用embstr编码的字符串对象保存短字符串的优点:
- embstr编码将创建字符串对象只需要调用一次内存分配函数创建连续的redisObject和sdshdr结构,而raw编码会调用两次内存分配函数分别创建redisObject和sdshdr结构
- 释放embstr编码的字符串只需要调用一次内存释放函数,释放raw编码需要调用两次
- embstr编码的字符串对象所有数据保存在一块连续的内存里,这种编码方式比起raw编码能更好地利用缓存带来的优势
embstr创建的内存块结构如下图所示:
1.4 浮点数使用的编码
可以用 long double 类型表示的浮点数在Redis中作为字符串值来保存的。
注:若超过double类型范围,则根据长度使用embstr或raw编码保存。
保存一个浮点数时,程序会先把浮点数转化为字符串,然后再保存转换后的字符串值。
在执行某些操作时,程序会将字符串值转换为浮点数,进行相关操作,再将操作所得的浮点数转换为字符串值进行保存。
示例:
redis> set pi 3.14
OK
redis> object encoding pi
"embstr"
redis> incrbyfloat pi 2.0
"5.14"
redis> object encoding pi
"embstr"
二、编码的转换
int编码和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象。
2.1 int -> raw
int编码的字符串对象执行了某些操作,如 APPEND命令,拼接一个字符串值,那么字符串对象的编码就会从 int 变为 raw。
示例:
redis> set num 10086
OK
redis> object encoding num
"int"
redis> append num " is a number"
(integer) 17
redis> get num
"10086 is a number"
redis> object encoding num
"raw"
2.2 embstr -> raw
Redis没有为embstr编码的字符串对象提供修改程序,所以当执行修改操作时,先要转换为 raw 编码,再执行修改操作。所以执行修改命令后,会变成 raw编码 的字符串对象。
注:
- 只有int和raw编码的字符串对象才有相应的修改程序
- embstr编码的字符串对象实际上是只读的
示例:
redis> set str "hello world"
OK
redis> object encoding str
"embstr"
redis> append str " !"
(integer) 13
redis> object encoding str
"raw"