Redis 数据类型--> 字符串解析

Posted offerNotFound

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 数据类型--> 字符串解析相关的知识,希望对你有一定的参考价值。

闲来无事,去看了下《Redis 设计与实现》这本广受好评的书(确实好,连我这种小白都读得顺畅)。

Redis 中的字符串

Redis 中的字符串并没有直接使用 C 语言中的字符串,而是自己构建了一种简单动态字符串,并将 SDS 用作 Redis 的默认字符串表示。

举个列子,客户端执行命令:resdis> SET msg "hello word",其中:

  • 键值对的键是一个字符串对象,对象的底层实现是一个保存着字符串 “msg” 的 SDS。
  • 键值对的值也是一个字符串对象,对象的底层实现是一个保存着字符串 “hello word” 的 SDS。

SDS 的定义

比如一个 “Redis” 字符串,其 SDS 结构如图(图片来自书中):


SDS 与 C 字符串的区别:


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

众所周知,C 或 Java 要或者字符串的长度,都要跑去把字符串遍历一遍了才知道,而 SDS 结构的 len 属性就存了字符串的长度,可以直接获取。

二、杜绝缓冲区溢出

举个列子,比如你要向 “Redis” 这个字符串中拼接一个字符串,在 C 语言中,如果你忘了提前为 “Redis” 分配足够的空间,那么在拼接后会导致新拼接的内容被意外的修改。而 SDS 的空间分配策略完全杜绝了这种情况,当 SDS API 需要对 SDS 进行修改时, API 会检查 SDS 空间是否够用,不够的话会自动去扩容。

三、减少修改字符串时带来的内存重分配次数

在 C 中,无论你对字符串进行拼接或删减都会要重新分配内存,很繁琐,而 SDS 使用了两种优化策略:空间预分配和惰性空间释放。

1、空间预分配

当 SDS 的 API 对一个 SDS 进行修改,并且需要对 SDS 进行空间扩展的时候,程序不仅会为 SDS 分配所够用的空间,还会为 SDS 分配额外的未使用空间。

举个例子,字符串 “Redis” 的 SDS 结构:

在给它拼接一个字符串 “Cluster” 时,会重新进行一次内存分配,将 len 修改成13字节,并将未使用空间 free 同样修改为13字节:

这时候我们如果还想再拼接一个字符串 “Tutorial” 时,由于未使用空间 free 里的13字节足够使用了,就不需要再重新分配内存。

2、惰性空间释放

对字符串 “XYXaYYbcXYYY” 执行sdstrim(s,"XY)" // 移除 字符串中所有的 “X” 和 “Y”

在移除后,会多出来8个字节,而这8个字节会作为未使用空间 free 保留在 SDS 里,如果后面还要对此字符串进行拼接操作的话,这个 free 就又派上用场了。

四、二进制安全

五、兼容部分 C 字符串函数


总结:

以上是关于Redis 数据类型--> 字符串解析的主要内容,如果未能解决你的问题,请参考以下文章

Redis 学习 —— 数据类型及操作

Redis源码解析-SDS简单动态字符串

Redis 数据类型--> 字符串解析

Redis 数据类型--> 字符串解析

Redis 数据类型--> 字符串解析

Redis 数据结构解析和命令指南