Redis 简单动态字符串(SDS)

SDS 遵循 C 字符串以空字符结尾的惯例,保存空字符的 1 字节空间不计算在 SDS 的 len 属性里面(额外分配)。

添加空字符到字符串结尾的操作由 SDS 函数自动完成,对于使用者来说完全透明。

设置和更新 SDS 长度的工作由 SDS 的 API 在执行时自动完成,所以无需手动进行任何手动修改长度的工作。

一、SDS 的空间分配策略

当 API 需要对 SDS 进行修改时,API 会先检查 SDS 的空间是否满足需求,如果不够,API 会自动将 SDS 的空间扩展,然后执行修改操作。(检查和扩容避免了缓冲区溢出,缓冲区即上次分配空间后的使用剩余空间)

1.空间预分配

用于字符串增长操作:

  • 如果 SDS 修改之后长度 len 小于 1MB,将分配和 len 属性同样大小的未使用空间,此时 len 和 free 属性值相同。
  • 如果 SDS 修改后长度 len 大于等于 1MB,将分配 1MB 的未使用空间。比如,如果修改后 SDS 的长度变为 30MB,那么将分配 1MB 的未使用空间,则 SDS 的 buf 数组长度变为 30MB + 1MB + 1byte。

通过预分配策略,减少了连续执行字符串增长操作所需的内存重分配次数。

2.惰性空间释放

用于字符串缩短操作:当 SDS 的 API 需要缩短 SDS 保存的字符串,并不会立即使用内存重分配来回收缩短后多出来的字节,而是使用 free 属性将字节数量保存,等待将来使用。

通过惰性空间释放策略,SDS 避免了缩短字符串时所需的内存重分配操作,并未将来可能的增长操作提供了优化。

SDS 也提供了相应的 API 用于在有需要时真正释放 SDS 的未使用空间,所以不用担心惰性空间释放策略造成内存浪费。

二、二进制安全

C 字符串除了末尾之外,不能包含空字符,因为 C 字符串通过空字符判断字符串的结尾,这些限制使得 C 字符串只能保存文本数据,而不能保存图片、音频、视频、压缩文件等二进制数据。

SDS 的 API 都是二进制安全的,都会以处理二进制的方式处理 SDS 存放在 buf 数组中的数据。

SDS 通过 len 属性的值而不是空字符来判断字符串是否结束。

二进制安全的 SDS 使得 Redis 不仅可以保存文本数据,还可以保存任意格式的二进制数据。

参考:《Redis 设计与实现》

 

 

你可能感兴趣的:(redis,数据库)