- 字符串对象编码可以是int, raw 或者 embstr
- 如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型表示
- 那么字符串对象会将整数值保存在字符串对象结构的ptr属性里面(将void*转换成long),并将字符串对象的编码设置为int
- 如果字符串对象保存的是一个字符串值,并且这个字符串值的长度大于44字节
- 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值,并将对象的编码设置为raw
- 如果字符串对象保存的是一个字符串值,并且这个字符串值的长度小于等于44字节,那么字符串对象将使用embstr编码的方式来保存这个字符串值
- raw 和 embstr的区别
- embstr编码是专门用于保存短字符串的一种优化编码,这种编码和raw编码一样,都使用redisObject结构和sdshdr结构来表示字符串
- raw编码会调用两次内存分配函数来分别创建redisObject结构和sdshdr结构, 而embstr编码则通过调用一次内存分配函数来分配一块连续的空间
- embstr的好处
- embstr编码的字符串对象在执行命令时,产生效果和raw编码的字符串对象执行命令时产生的效果是相同的
- 但使用embstr编码的字符串对象来保存短字符串值有以下好处
- embstr编码将创建字符串对象所需的内存分配次数从raw编码的两次降低为一次
- 释放embstr编码的字符串对象只需要调用一次内存释放函数,而释放raw编码的字符串对象需要调用两次内存释放函数
- 因为embstr编码的字符串对象的所有数据都保存在一块连续的内存里面,所以这种编码的字符串对象比起raw编码的字符串对象能够更好地利用缓存带来的优势
- int 编码的字符串对象和embstr编码的字符串对象在条件满足的情况下,会被转换为raw编码的字符串对象
- 对于int编码的字符串对象来说,如果我们向对象执行了一些命令,使得这个对象保存的不再是整数值,而是一个字符串值,那么字符串对象的编码将int变为raw
- 例如
- 通过APPEND命令,向一个保存整数对象追加了一个字符串值,就会变成raw
- 例如
- Redis没有为embstr编码的字符串对象编写任何相应的修改程序(只有int编码的字符串对象和raw编码的字符串对象有这些程序),所以embstr编码的字符串对象实际上只只读的
- 当我们对embstr编码的字符串对象执行任何修改命令时,程序会先将对象的编码从embstr转换raw
| 命令 | int编码的实现方式 | embstr编码的实现方式 | raw编码的实现方式 |
|---|---|---|---|
| SET | 使用int编码保存值 | 使用embstr保存值 | 使用raw编码保存值 |
| GET | 拷贝对象所保存的整数值,将这个拷贝值转换称字符串值,然后客户端返回这个字符串值 | 直接问客户端返回字符串值 | 直接向客户端返回字符值 |
| APPEND | 将对象转换成raw编码,然后按raw编码的方式执行此操作 | 将对象转换成raw编码,然后按raw编码的方式执行此操作 | 调用sdscatlen函数,将给定字符串追加到现有字符串的末尾 |
| INCRBYFLOAT | 取出整数值并将其转换成long double类型浮点数,对这个浮点数进行加法计算,然后将得出的浮点数结果保存起来 | 取出字符串并尝试将其转换成long double类型的浮点数,对这个浮点数进行加法计算,然后将得出的浮点数结果保存起来,如果字符串值不能被转换成浮点数,那么向客户端返回一个错误 | 取出字符串并尝试将其转换成long double类型的浮点数,对这个浮点数进行加法计算,然后将得出的浮点数结果保存起来,如果字符串值不能被转换成浮点数,那么向客户端返回一个错误 |
| INCRBT | 对整数值进行加法计算,得到的计算结果作为整数被保存起来 | embstr编码不能执行此命令,向客户端返回一个错误 | raw编码不能执行此命令,向客户端返回一个错误 |
| DECRBT | 对整数值进行减法计算,得到的计算结果作为整数被保存起来 | embstr编码不能执行此命令,向客户端返回一个错误 | raw编码不能执行此命令,向客户端返回一个错误 |
| STRLEN | 拷贝对象所保存的整数值,将这个拷贝值转换称字符串值,计算并返回这个字符串值的长度 | 调用sdslen函数,返回字符串的长度 | 调用sdslen函数,返回字符串的长度 |
| SETRANGE | 将对象转换成raw编码,然后按raw编码的方式执行此操作 | 将对象转换成raw编码,然后按raw编码的方式执行此操作 | 将字符串特定索引上的值设定为给定的字符 |
| GETRANGE | 拷贝对象所保存的整数值,将这个拷贝值转换称字符串值,然后取出并返回字符串指定索引上的字符 | 直接取出并返回字符串指定索引上的字符 | 直接取出并返回字符串指定索引上的字符 |