Featured image of post Redis数据结构之String(SDS)

Redis数据结构之String(SDS)

Redis数据结构之String个人学习笔记

redis版本7.x

原生C语言字符串的问题

  1. C语言使用char * 字符数组来实现字符串,在创建时就需要手动检查和分配空间。由于没有 length属性 记录长度,想要获取字符串的长度就需要从头遍历,直到遇到\0。

  2. 无法做到“安全的二进制格式数据存储”,图片等二进制格式数据无法保存。无法存储\0这种特殊字符,\0在C语言中代表字符串结尾。

  3. 字符串的扩容和缩容。char数组的长度在创建字符串的时候就确定下来,如果要追加数据,则要重新申请一块空间,把追加后的字符串内容拷贝进去,再释放旧的空间,十分消耗资源。

Redis中SDS设计

SDS也遵循C语言的以空字符串 \0 结尾的惯例,但是空字符串不计入SDS内部的len字段中。

SDS主要字段如下:

  1. len:数组已使用长度

  2. alloc:数组总长度

  3. flags:SDS类型

  4. char buf[]:存储的实际内容

O(1)时间复杂度获取字符串长度

SDS中的len字段保存了字符串的长度,实现了O(1)时间复杂度获取字符串长度。

SDS结构有一个flags字段,表示的是SDS类型。实际上SDS一共设计了5种类型,分别是sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64,区别在于数组的len长度和分配空间长度alloc不同。

节省内存

之所以这么设计,是因为SDS使用不同的类型保存不同大小的字符串可以节省内存。

redis内部限制最大的字符串长度为512MB

编码格式

SDS内部采用了三种编码格式来存储,分别是int、embstr和raw。

  • int编码:8字节的长整型,值是数字类型且数字的长度小于20。

  • embstr编码:长度小于或等于44字节的字符串。

  • raw编码:长度大于44字节的字符串。

作用:代替字节对齐的方式来节省内存。

二进制格式的数据安全

因为SDS并不是通过 \0 来判断字符串结束的,而是采用len标志结束,所以可以直接存储二进制格式数据。

空间预分配

在需要对SDS的空间进行扩容时,不仅仅分配所需的空间,还会分配额外的未使用空间,通过预分配策略,减少了执行字符串增长所需的内存重新分配次数。

惰性空间释放

当对SDS进行缩短操作时,程序并不会回收多余的内存空间,如果后面需要append追加操作,则直接使用buf数组alloc-len中未使用的空间。通过惰性空间释放策略,避免了减小字符串所需的内存重新分配操作。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计