目录
String类型的内部编码
存储字符串采用两种编码方式的优缺点
选择SDS的原因
存储整数型采用OBJ_ENCODING_INT的原因
String 类型的底层的数据结构实现主要是 long 和 SDS(简单动态字符串)
数据结构:SDShttps://blog.csdn.net/weixin_44415582/article/details/131709666?spm=1001.2014.3001.5501
String类型的内部编码
类型的内部编码(encoding)有 3 种 :int、raw和 embstr
存储数据为字符串时
- 其基本编码方式是RAW,基于简单动态字符串(SDS)实现,存储上限为512mb。但RAW会通过调用两次内存分配函数来分别分配两块空间来保存
redisObject
和SDS
。- 在redis 5.0之后,如果存储的SDS长度小于44字节,则会采用EMBSTR编码会通过一次内存分配函数来分配一块连续的内存空间来保存
redisObject
和SDS
存储的字符串是整数值时
- 其大小在LONG_MAX范围内,则会采用INT编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节针对64位系统),不再需要SDS了。
存储字符串采用两种编码方式的优缺点
优点:
embstr
编码将创建字符串对象所需的内存分配次数从raw
编码的两次降低为一次;- 释放
embstr
编码的字符串对象同样只需要调用一次内存释放函数;- 因为
embstr
编码的字符串对象的所有数据都保存在一块连续的内存里面可以更好的利用 CPU 缓存提升性能。embstr 也有缺点
- 如果字符串的长度增加时,需要重新分配内存,整个redisObject和sds都需要重新分配空间,所以embstr编码的字符串对象实际上是只读的,redis没有为embstr编码的字符串对象编写任何相应的修改程序。当我们对embstr编码的字符串对象执行任何修改命令(例如append)时,程序会先将对象的编码从embstr转换成raw,然后再执行修改命令。
选择SDS的原因
- SDS 不仅可以保存文本数据,还可以保存二进制数据
- SDS 获取字符串长度的时间复杂度是 O(1)
- Redis 的 SDS API 是安全的,拼接字符串不会造成缓冲区溢出
存储整数型采用OBJ_ENCODING_INT的原因
- 在对string进行加、减等操作的时候,如果它内部是OBJ_ENCODING_INT编码,那么可以直接进行加减操作
- 如果它内部是OBJ_ENCODING_RAW或OBJ_ENCODING_EMBSTR编码,那么Redis会先试图把sds存储的字符串转成long型,如果能转成功,再进行加减操作。
原因:对⼀个内部表示成long型的string执行append, setbit, getrange这些命令,针对的仍然是string的值(即十进制表示的字符串),而不是针对内部表⽰的long型进行操作。
若不进行转换,情景如下:字符串”32”,如果按照字符数组来解释,它包含两个字符,它们的ASCII码分别是0x33和0x32。当我们执行命令【setbit key 7 0】的时候,相当于把字符0x33变成了0x32,这样字符串的值就变成了”22”。⽽如果将字符串”32”按照内部的64位long型来解释,那么它是0x0000000000000020,在这个基础上执行setbit位操作,结果就完全不对了。因此,在这些命令的实现中,会把long型先转成字符串再进行相应的操作。