Redis1:简单动态字符串SDS

1、SDS的定义

在这里插入图片描述

len:buf数组中使用字节的数量
free:buff数组中未使用字节的数量

2、SDS与C字符串的区别

2.1 获取字符串长度的复杂度

C字符串不记录自身的长度信息,为了获取C字符串的长度,程序必须遍历整个字符串。
SDS在len属性中记录了SDS本身的长度。
Redis将获取字符串长度所需的时间复杂度降低到了O(1),确保了获取字符串长度的工作不会成为Redis的性能瓶颈

2.2 杜绝缓冲区的溢出

  C字符串不记录自身长度带来的一个问题是容易造成缓冲区溢出。比如strcat函数可以将src字符串中的内容拼接到dest字符串的末尾,假设用户在执行这个函数时已经为dest分配了足够的内存。可以容纳src字符串的所有内容,一旦这个假设不成立就会产生缓冲区溢出。
  当SDS的API需要对SDS进行修改时,API会先检查SDS的空间是否满足修改所需的要求。如果不满足API会自动将SDS的空间扩展至所需的大小,然后才执行实际的修改操作。使用SDS既不需要手动修改SDS的空间大小,也不回出现缓冲区溢出问题。

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

一个包含了N个字符的C字符串底层是一个N+1个字符长的数组,所以每次增长或者缩短C字符串,都要对这个C字符串的数组进行一次内存重分配操作。内存重分配设计复杂的算法,可能需要执行系统调用,通常是一个比较耗时的操作:

  • Redis作为数据库,经常被用于速度要求严苛、数据被频繁访问的场合,导致修改频繁、内存重分配次数多、性能下降。
  • 通过未使用空间,SDS实现了空间预分配和惰性空间释放两种优化策略。

2.4 二进制安全

C字符串的字符必须符合某种编码,除了字符串末尾之外不可以出现空字符,因此只能保存文本数据,而不能保存图片、音频、视频、压缩文件这样的二进制数据。

为了确保Redis可以适用各种不同的场景,SDS的API都是二进制安全的,以处理二进制的方式来处理SDS存放在buf数组里的数据。程序不会对其中的数据做任何限制、过滤、假设。数据写入时是什么样的,读出时就是什么样的。

2.5 兼容部分C字符串函数

3 总结

C字符串 SDS
获取字符串长度的时间复杂度 O(N) O(1)
API安全 不安全,造成缓冲区溢出 是安全的,不会造成缓冲区溢出
修改字符串长度N次执行内存重分配的次数 需要执行N次 最多需要N次
文本数据 只能保存文本数据 可以保存文本数据或二进制数据
<string.h>库中的函数 可以使用 可以使用一部分
  • Redis使用C字符串作为字面量,大多数情况下使用SDS作为字符串表示。

猜你喜欢

转载自blog.csdn.net/qq_37935909/article/details/108895704