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 数据类型--> 字符串解析的主要内容,如果未能解决你的问题,请参考以下文章