Redis (String 底层数据结构)

Redis是查询数据很快的no Sql数据库。其原因不只是因为它存储在内存中,还因为它存储各种类型的数据结构。比如这期说到的String类型。String类型在Redis中应用很广泛。Redis中存储数据是以键值对的方式。这个键都是String类型。所以下面我们看下String类型的底层数据结构吧。

1. 简单字符串(SDS)

1.1Redis是由C语言开发的。为啥字符串没有使用C字符串呢?

  1. 这是因为C字符串是以\0为结尾。所以保存的字符串长度总是比原字符串长1。而且存储的特殊字符也可能由于\0得特性导致数据丢失。如果Redis想要存储文件数据则就不能使用C字符串。否则会导致数据丢失。
  2. C字符串是以char[]数组来实现的,在创建出来之后就不能改变其长度了,所以如果执行字符串拼接或者字符串截取就需要创建新的char[]数组。这样就就会徒增性能的消耗。

1.2 Redis 字符串实现

Redis使用SDS来实现。

1.2.1 SDS结构
c 复制代码
struct sdshdr {
    //记录buf数组中已使用字节的数量
    //等于SDS所保存字符串的长度
    int len;
    //记录buf数组中未使用字节的数量
    int free;
    //字节数组,用于保存字符串
    char buf[];
};

Redis虽然还是以\0为结尾但是不会再遇到\0就认为字符串到头了。这样做的好处还可以使用C语言中一些操作字符串的方法。

1.2.2 获取字符串长度

C字符串需要判断\0的位置,所以计算长度是O(n)。而SDS有len字段可以直接判断字符串长度。所以是O(n)。

1.2.3 杜绝缓冲区溢出
  1. C语言字符串如果需要把一个字符串后面拼接另一个字符串。因为C语言字符串没有记录字符串的长度。假定没有分配足够的内存给后面一个字符串的长度。则会导致产生缓存区溢出。
  2. SDS在进行拼接时会判断可用长度free是否可以容纳拼接字符串的长度。如果不能够容纳则会进行扩容。扩容后达到足够容纳拼接字符串的可用空间后才会继续进行拼接操作。这样就不会造成缓存区的溢出了。
1.2.4 减少修改字符串时带来的内存重分配次数
  1. 正如上面所说拼接字符串。C语言需要每次都对目标字符串进行内存重新分配。所以只要每次操作都需要进行重新分配。
  2. 为了解决上面的问题SDS实现了空间预分配和惰性空间释放两种策略。
    a. 空间预分配
    ⅰ. 对SDS进行修改后如果长度小于1MB。那么SDS就会分配和len一样长度的大小的额外空间。比如分配后的长度为13。最终的len = 13 + 13 + 1 = 27。额外的一字节用于保存空字符。
    ⅱ. 如果分配后长度大于1MB。那么SDS就会分配多1MB的额外的空间。比如分配后的长度为30MB。最终的len = 30MB + 1MB + 1字节。
    b. 惰性空间释放
    ⅰ. 如果把字符串缩短。也不会把空余出来的空间给立马释放掉。会等待字符串变长时使用。SDS也提供了响应的API。让我们可以完全释放掉free的空间。
1.2.5 二进制安全

C字符串中的字符必须符合某种编码(比如ASCII),并且除了字符串的末尾之外,字符串里面不能包含空字符,否则最先被程序读入的空字符将被误认为是字符串结尾,这些限制使得C字符串只能保存文本数据,而不能保存像图片、音频、视频、压缩文件这样的二进制数据。

SDS的API都是二进制安全的(binary-safe),所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据,程序不会对其中的数据做任何限制、过滤、或者假设,数据在写入时是什么样的,它被读取时就是什么样。

总结

所以根据上面的几个方面我们可以看出Redis使用SDS对字符串进行了优化。保证了字符串的安全性,提高了字符串操作的性能。

参考:《Redis开发与实现》

相关推荐
埃泽漫笔5 分钟前
Redis的List数据结构底层实现
redis·list
小白.cpp7 分钟前
list链表容器
数据结构·链表·list
viperrrrrrrrrr77 分钟前
milvus向量数据库
数据库·大模型·llm·milvus
仰泳的熊猫11 分钟前
LeetCode:207. 课程表
数据结构·c++·算法·leetcode
liu****18 分钟前
19.map和set的封装
开发语言·数据结构·c++·算法
白衣鸽子22 分钟前
MySql数据库同步技术:构建高可用架构的基石
数据库·后端
不良人天码星43 分钟前
redis的事务,以及watch的原理
数据库·redis·缓存
懂得节能嘛.1 小时前
【动态配置中心】Java+Redis构建动态配置中心
java·开发语言·redis
韩立学长1 小时前
基于微信小程序的公益捐赠安全平台9hp4t247 包含完整开发套件(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·微信小程序·小程序
智能化咨询1 小时前
SQL之参数类型讲解——从基础类型到动态查询的核心逻辑
数据库·oracle