- 1、本文档共13页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
SDS 与 C 字符串的区别
根据传统, C 语⾔使⽤长度为 N+1 的字符数组来表⽰长度为 N 的字符串, 并且字符
数组的最后⼀个元素总是 字符 \0 。
⽐如说, 图 2-3 就展⽰了⼀个值为 Redis 的 C 字符串:
C 语⾔使⽤的这种简单的字符串表⽰⽅式, 并不能满⾜ Redis 对字符串在安全性、效
率、以及功能⽅⾯的要求, 本节接下来的内容将详细对⽐ C 字符串和 SDS 之间的区
别, 并说明 SDS ⽐ C 字符串更适⽤于 Redis 的原因。
常数复杂度获取字符串长度
因为 C 字符串并不记录⾃⾝的长度信息, 所以为了获取⼀个 C 字符串的长度, 程序
必须遍历整个字符串, 对遇到的每个字符进⾏计数, 直到遇到代表字符串结尾的
字符为⽌, 这个操作的复杂度为 。
举个例⼦, 图 2-4 展⽰了程序计算⼀个 C 字符串长度的过程。
和 C 字符串不同, 因为 SDS 在 len 属性中记录了 SDS 本⾝的长度, 所以获取⼀个
SDS 长度的复杂度仅为 。
举个例⼦, 对于图 2-5 所⽰的 SDS 来说, 程序只要访问 SDS 的 len 属性, 就可以
⽴即知道 SDS 的长度为 5 字节:
又⽐如说, 对于图 2-6 展⽰的 SDS 来说, 程序只要访问 SDS 的 len 属性, 就可以
⽴即知道 SDS 的长度为 11 字节。
设置和更新 SDS 长度的⼯作是由 SDS 的 API 在执⾏时⾃动完成的, 使⽤ SDS ⽆须
进⾏任何⼿动修改长度的⼯作。
通过使⽤ SDS ⽽不是 C 字符串, Redis 将获取字符串长度所需的复杂度从 ,
这确保了获取字符串长度的⼯作不会成为 Redis 的性能瓶颈。
⽐如说, 因为字符串键在底层使⽤ SDS 来实现, 所以即使我们对⼀个⾮常长的字符
串键反复执⾏ STRLEN 命令, 也不会对系统性能造成任何影响, 因为 STRLEN 命令
的复杂度仅为 。
杜绝缓冲区溢出
除了获取字符串长度的复杂度⾼之外, C 字符串不记录⾃⾝长度带来的另⼀个问题是
容易造成缓冲区溢出 (buffer overflow )。
举个例⼦, string.h/strcat 函数可以将 src 字符串中的内容拼接到 dest 字
符串的末尾:
char *strcat(char *dest, const char *src)
因为 C 字符串不记录⾃⾝的长度, 所以 strcat 假定⽤户在执⾏这个函数时, 已经
为 dest 分配了⾜够多的内存, 可以容纳 src 字符串中的所有内容, ⽽⼀旦这个假
定不成⽴时, 就会产⽣缓冲区溢出。
举个例⼦, 假设程序⾥有两个在内存中紧邻着的 C 字符串 s1 和 s2 , 其中 s1 保存
了字符串 Redis , ⽽ s2 则保存了字符串 MongoDB, 如图 2-7 所⽰。
如果⼀个程序员决定通过执⾏:
strcat(s1, Cluster)
将 s1 的内容修改为 Redis Cluster , 但粗⼼的他却忘了在执⾏ strcat 之前
为 s1 分配⾜够的 间, 那么在 strcat 函数执⾏之后, s1 的数据将溢出到 s2 所
在的 间中, 导致 s2 保存的内容被意外地修改, 如图 2- 所⽰。
与 C 字符串不同, SDS 的 间分配策略完全杜绝了发⽣缓冲区溢出的可能性: 当
SDS API 需要对 SDS 进⾏修改时, API 会先检查 SDS 的 间是否满⾜修改所需的要
求, 如果不满⾜的话, API 会⾃动将 SDS 的 间扩展⾄执⾏修改所需的⼤⼩, 然后
才执⾏实际的修改操作, 所以使⽤ SDS 既不需要⼿动修改 SDS 的 间⼤⼩, 也不会
出现前⾯所说的缓冲区溢出问题。
举个例⼦, SDS 的 API ⾥⾯也有⼀个⽤于执⾏拼接操作的 sdscat 函数, 它可以将
⼀个 C 字符串拼接到给定 SDS 所保存的字符串的后⾯, 但是在执⾏拼接操作之
前, sdscat 会先检查给定 SDS 的 间是否⾜够, 如果不够的话, sdscat 就会先
扩展 SDS 的 间, 然后才执⾏拼接操作。
⽐如说, 如果我们执⾏:
sdscat(s, Cluster)
其中 SDS
文档评论(0)