Redis对象编码(encoding)之字符串对象详解
上篇文章讲述了Redis对象的属性https://www.cnblogs.com/Joe-Go/p/16420643.html,这篇文章就是对上篇文章中Redis对象属性encoding(编码)之字符串对象进行详细的解释
字符串对象
字符串的编码可以是int、embstr、raw;
- 如果一个字符串对象保存的是整数,并且这个整数可以用long类型来表示,那么这个字符串对象会将这个整数值保存在对象结构的ptr属性里面,并将字符串的编码设置为REDIS_ENCODING_INT
举例,如果我们在redis客户端中执行以下命令:
redis > SET msg 10086
OK
redis > OBJECT ENCODING msg
"int"
则会得到一个如下图所示的字符串对象:
- 如果字符串对象保存的是一个字符串值,并且这个字符串的长度大于32字节,那么字符串对象将会使用简单动态字符串(SDS)来保存这个字符串值,并将这个字符串值的编码设置为REDIS_ENCODING_RAW
举例,如果我们在Redis客户端执行以下命令:
redis > SET msg "are you ok? I'm ok, thanks you . and you ? .... okokok"
OK
redis > STRLEN msg
(integer) 40
redis > OBJECT ENCODING msg
raw
就会得到一个如下图所示的SDS字符串对象:
- 如果一个字符串对象的值是一个字符串,并且该字符串的长度小于等于32字节,那么这个字符串对象就会以REDIS_ENCODING_EMBSTR(embstr)编码的方式来保存这个字符串值
embstr编码是专门用于保存短字符串的一种优化编码方式,这种编码和raw编码一样,都是采用redisObject和sdshdr这两种结构来保存字符串,但raw编码会调用两次内存分配函数来分别创建redisObject结构和sdshdr结构;而embstr编码则通过一次调用内存分配函数来分配一块连续的空间,空间中依次包含redisObject和sdshdr两个结构,如下图所示
embstr编码的字符串对象在执行命令时和raw编码的字符串对象的表现是一样的,但是使用embstr编码的字符串对象来保存短字符串值有以下三个好处:
(1)embstr编码将创建字符串对象的两次调用内存分配函数降低为一次
(2)embstr编码的字符串对象在释放内存时也只需要调用一次函数,而raw编码的字符串对象则需要调用两次释放函数
(3)embstr编码的字符串对象是存放在一块连续的内存空间,这就会导致embstr编码的字符串对象比raw编码的字符串对象能更好的利用缓存优势
举例,用以下命令创建一个embstr编码的字符串对象:
redis > SET msg hello
OK
redis > OBJECT ENCODING msg
embstr
值对象的数据结构如下:
**注意:long double 类型的表示的浮点数在Redis中也是作为字符串值保存的
执行以下命令:
redis > set pi 3.1415
OK
redis > OBJECT ENCODING pi
embstr
在执行加减乘除等操作时,Redis会将保存的浮点数的字符串转换为浮点数,执行后,再将得到的浮点数转换回字符串进行保存
int、embstr编码的转换
(1)对于int编码的字符串对象来说,如果向对象执行了一些命令,使得这个对象保存的不再是整数值,而是一个字符串值,那么这个字符串的编码将从int变为raw
例如下面的操作:
redis > SET num 10086
OK
redis > OBJECT ENCODING num
int
redis > APPEND num " good!"
(integer)11
redis > OBJECT ENCODING num
raw
因为Redis没有为embstr编码的字符串做任何相应的修改程序,所以embstr编码的字符串实际上是只读的,当要对embstr编码的字符串进行修改时,Redis会把embstr编码的字符串转换为raw,然后再执行修改命令。因此,embstr编码的字符串执行修改后,总会变为一个raw编码的字符串。
下述代码是将一个embstr编码的字符串执行APPEND命令后,对象编码从embstr变为raw的例子:
redis > SET msg hello
OK
redis > OBJECT ENCODING msg
embstr
redis > APPEND " hello"
(integer) 11
redis > OBJECT ENCODING msg
raw