Redis 数据结构实现(一)字符串
Redis采用SDS(simple dynamic string)来表示字符串,表示一个可以修改的字符串值。用在Redis的key和value中。
注意:Redis所有的key都是这个类型,value有不同的其他类型,SDS还可以用在缓冲区中。
其具体的定义如下:
为什么不用C原生字符串?
- 是因为Redis中有STRLEN命令,该命令可以求一个key对应的value的长度(必须为string 类型),如果用C字符串每次求长度都必须扫描整个字符串,效率较低。而Redis中的SDS提供了len长度属性,可以在O(1)的时间内求得长度。
- C中存在字符串拼接时缓冲区溢出的问题,Redis中也有sdscat命令,这个命令用于字符串拼接,拼接前会先检查是否有足够的free,没有则先分配空间再拼接。
- Redis需要保存二进制数据,而C中的字符串以’\0’判断是否到达末尾,没办法存储二进制数据。
注意:虽然Redis用自己的SDS,但是为了复用C语言中提供的字符串操作函数,还是遵循了以’\0’结尾的传统~(len、free中不算这个‘\0’但是实际分配时buff数组是分配了的。
SDS内存重分配策略?
刚才讲到,如果没有足够的free会先分配内存,众所周知,字符串的拼接、裁剪是非常频繁的操作,内存的分配与回收不当则会降低效率甚至带来内存泄漏,那是如何优化分配的呢?
- 空间预分配
- 如果修改后的len小于1M的话,会一起预先分配与len长度相等的free空间
- 如果修改后的len大于等于1M的话,会预先分配1M的空间
- 惰性空间释放
当对字符串进行裁剪时(字符串长度缩小),并不会立即释放空间,而是保留下次使用。Redis也提供了释放SDS未使用内存的命令(sdsRemoveFreeSpace命令)
惰性删除的代码如下: