Redis 简单动态字符串SDS

103 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情 ​

Redis中的字符串是和C语言中的字符串是有区别的,C语言字符串使用 长度为n+1的字符数组来表示长度为n的字符串,并且字符数组的最后一个元素总是空字符'\0',因为这种字符串表示方式不能满足Redis对字符串在安全性、效率以及功能方面的要求,所以Redis自己构建了SDS。

说是字符串但它的内部结构更像是一个 ArrayList,内部维护着一个字节数组, 并且在其内部预分配了一定的空间,以减少内存的频繁分配。其底层实现是简单动态字符串sds(simple dynamic string),是可以修改的字符串。sds ,Simple的意思是简单,Dynamic即动态,意味着其具有动态增加空间的能力,扩容不需要使用者关心。

Redis的内存分配机制是这样:

当字符串的长度小于 1MB时,每次扩容都是加倍现有的空间。

如果字符串长度超过 1MB时,每次扩容时只会扩展 1MB 的空间。

使用SDS的好处:

1.二进制安全的数据结构

2、兼容C语言的函数库,\0结尾

3、相比C语言字符串,使获取字符串长度时间复杂度降为O(1),C语言字符串不记录自身长 度,如果想获取自身长度必须遍历整个字符串,对每个字符进行计数,这个操作时间复杂度是O(n)。相比较而言,Redis程序只要访问SDS的len属性就可以直接获取到字符串长度,时间复杂度为O(1),确保获取字符串长度不会成为Redis性能瓶颈。

如何优化?

在Redis3.X版本中不同长度的字符串占用的头部是相同的,如果某一字符串很短但是头部 却占用了更多空间,这十分浪费。所以我们将SDS分为三种级别的字符串:

——短字符串(长度小于32),len和free的长度用1字节即可。

——长字符串,用2字节或4字节。

——超长字符串,用8字节。 共有五种类型的SDS(长度小于1字节、1字节、2字节、4字节、8字节)

我们可以在SDS中新增一个type字段来标识类型,但是没必要使用一个4字节的int类型去 做。可以使用1字节的char类型通过位运算(3位即可标识2^3种类型)来获取类型 image.png

低三位存储类型,高5位存储长度,最多能标识的长度为32,所以短字符串的长度必定小于 32。无需free字段了,32-len即为free