- 1、本文档共16页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
?
?
Redis设计与实现之String
?
?
Redis设计与实现之String
文章目录
Redis设计与实现之String
Redis简介
SDS
SDS的定义
SDS的优势
常数复杂度获取字符串长度
杜绝缓冲区溢出
减少修改字符串时的内存分配次数
空间预分配
惰性空间释放
字符串对象编码
embstr和raw的区别
扩展
Redis简介
Redis(Remote Dictionary Server ),即远程字典服务,是一个完全开源(遵守BSD协议)免费的使用C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
Redis 与其他 key - value 缓存产品有以下三个特点:
Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
Redis支持数据的备份,即master-slave模式的数据备份。
SDS
SDS全称是简单动态字符串(simple dynamic string)。
Redis只有在无需对字符串值进行修改的地方才会使用C语言原生的字符串,比如日志打印。
对于需要对字符串的值可能会修改的地方,则使用SDS。所以Redis将SDS作为默认的字符串表示。比如存储字符串的时候就是使用SDS表示。
键值对的健是一个字符串对象,对象的底层实现是一个保存着字符串“msg”的SDS。
键值对的值也是一个字符串对象,对象的底层实现是一个保存着字符串“hello world”的SDS。
键值对的健是一个字符串对象,对象的底层实现是一个保存着字符串“fruits”的SDS。
键值对的值是一个列表对象,列表对象包含了三个字符串对象,这三个字符串对象分别是由三个SDS对象实现:
第一个SDS保存字符串“apple”,
第二个SDS保存字符串“banana”,
第三个SDS保存字符串“cherry”
SDS的定义
struct sdshdr {
// 记录buf数组中已使用的字节数量
// 等于SDS所保存字符串的长度
int len;
// 记录buf数组中未使用的字节数量
int free;
// 字节数组,用于保存字符串
char buf[];
}
free属性的值为0,表示这个SDS没有分配任何未使用空间。
len属性的值为5,表示这个SDS保存了一个5字节长度的字符串。
buf属性是一个char类型的数组,数组的前五个字节分别保存了‘R’、‘e’、‘d’、‘i’、‘s’五个字符。
最后一个字节则保存了空字符串’\0’(这是遵循C字符串以空字符结尾的惯例,这个空字符不计算在SDS的len属性中。)。
SDS的优势
常数复杂度获取字符串长度
C字符串本身不记录字符串长度,每次获取字符串长度需要遍历一次数组。这个操作的复杂度为O(N)。
SDS的len属性记录了本身的长度,所以获取一个SDS长度的复杂度为O(1)。
杜绝缓冲区溢出
C字符串本身不记录字符串长度,导致的另外一个问题是容易造成缓冲区溢出。
假设程序里有2个内存中紧邻的C字符串s1和s2,其中s1保存了字符串“Redis”,而s2则保存了字符串“MongoDB”。
如果有人直接执行:strcat(s1, “ Cluster”);将s1的内容修改为“Redis Cluster”。由于没有提前给s1分配足够的空间,那么在strcat函数执行后,s1数据将溢出到s2所在的空间,导致s2保存的内容被意外修改。
与C字符串不同,SDS空间分配策略完全可以杜绝缓冲区溢出的问题:当SDS API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改所需要的要求,如果不满足的话,API会自动将SDS空间扩展至执行修改所需要的大小,然后才执行实际的修改操作,所以使用SDS即不需要手动修改SDS空间大小,有不会前面所说的缓冲区溢出问题。
如上图执行strcat(s1, “ Cluster”)操作,那么空间不够拼接,会先扩展空间然后执行拼接“ Cluster”操作,拼接的结果如下图所示。
减少修改字符串时的内存分配次数
正如前面所说,由于C字符串并不记录自身的长度,所以对于一个包含了N个字符的C字符串来说,底层实现总数一个N+1个字符长度的数组。所以每次增长或者缩短一个C字符串,程序总要保存这个C字符串的数组进行一次内存重新分配操作:
如果程序执行的是增长字符串操作,比如拼接操作(append)那么在执行这个操作之前,程序需要先通过内存重新分配来扩展底层数组的空间大小,如果忘记了就会导致缓冲区溢出。
如果程序执行的是缩短字符串操作,
您可能关注的文档
- Python语言程序设计-文件和数据格式化.docx
- Python语言程序设计基础.docx
- Python课程设计爬虫篇.docx
- QT学习1:设计可视化窗口的框架-Ui-Class.docx
- RBAC权限系统分析、设计与实现.docx
- Redis+Nginx+JVM+设计模式+Spring全家桶+Dubbo.docx
- Redis+Nginx+设计模式+Spring全家桶+Dubbo精选.docx
- Redis+Nginx+设计模式+Spring全家桶+Dubbo精选概述.docx
- redis-list类型的设计与实现.docx
- redis-string类型的设计与实现.docx
- 中国行业标准 GM/T 0126-2023HTML密码应用置标语法.pdf
- 《JJF 2121-2024恒转速源校准规范》.pdf
- 餐饮服务中20条处理要点.docx
- 《GM/T 0011-2023可信计算 可信密码支撑平台功能与接口规范》.pdf
- 《JJF 2134-2024旋转流变仪校准规范》.pdf
- JJF 2121-2024恒转速源校准规范.pdf
- 计量规程规范 JJF 2121-2024恒转速源校准规范.pdf
- 《JJF 2118-2024压力式六氟化硫气体密度控制器校验仪校准规范》.pdf
- JJF 2134-2024旋转流变仪校准规范.pdf
- 计量规程规范 JJF 2134-2024旋转流变仪校准规范.pdf
文档评论(0)