Redis设计与实现之String.docx

  1. 1、本文档共16页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 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)那么在执行这个操作之前,程序需要先通过内存重新分配来扩展底层数组的空间大小,如果忘记了就会导致缓冲区溢出。 如果程序执行的是缩短字符串操作,

文档评论(0)

科技之佳文库 + 关注
官方认证
内容提供者

科技赋能未来,创新改变生活!

版权声明书
用户编号:8131073104000017
认证主体重庆有云时代科技有限公司
IP属地上海
统一社会信用代码/组织机构代码
9150010832176858X3

1亿VIP精品文档

相关文档