当前位置: 首页 > article >正文

redis---字符串SDS(简单动态字符串)底层结构

文章目录

  • 什么是SDS(简单动态字符串)
  • SDS结构
  • SDS的优点
    • O(1) 时间复杂度获取字符串长度
    • 避免缓冲区溢出
    • 减少内存重分配次数
    • 二进制安全
    • 兼容C语言字符串函数
  • SDS的操作
  • 总结


什么是SDS(简单动态字符串)

redis是由C语言编写的,但是redis在实现字符串中并没有采用传统C语言中的字符串表示(传统的C语言字符串是一个以空字符‘\0’结尾的字符数组char*),而是自己定义了一种叫做简单动态字符串(simple dynamic string, 简称SDS)的抽象类型,并用SDS用作redis默认的字符串表示。

SDS结构

Redis 5.0 及之后的版本

struct __attribute__ ((__packed__)) sdshdr {
    uint8_t len;        // 字符串的实际长度
    uint8_t alloc;      // 分配的总空间(不包括头部和结尾的 \0)
    unsigned char flags; // 标志位,用于标识 SDS 的类型
    char buf[];         // 存储字符串内容的柔性数组
};
  • len:记录字符串的实际长度(不包括结尾的 \0)。

  • alloc:记录分配的总空间(不包括头部和结尾的 \0)。

  • flags:标志位,用于标识 SDS 的类型(如 SDS_TYPE_8SDS_TYPE_16 等)。

  • buf:存储字符串内容的动态数组,末尾会自动添加 \0,以兼容 C 语言的字符串函数。

新版SDS根据字符串的长度动态选择不同的类型:

  • SDS_TYPE_5:长度小于 32。

  • SDS_TYPE_8:长度小于 256。

  • SDS_TYPE_16:长度小于 65536。

  • SDS_TYPE_32:长度小于 2^32。

  • SDS_TYPE_64:长度小于 2^64。

这种设计可以根据字符串的实际长度动态调整头部的大小,进一步节省内存。

SDS的优点

O(1) 时间复杂度获取字符串长度

C 语言的原生字符串需要通过遍历(strlen)来获取长度,时间复杂度为 O(n)。

SDS 直接通过 len 字段获取长度,时间复杂度为 O(1)。

避免缓冲区溢出

C 语言的原生字符串操作(如 strcat)容易导致缓冲区溢出。

// 将 src 字符串拼接到 dest 字符串后面
char *strcat(char *dest, const char* src);

C 语言的字符串是不会记录自身缓冲区大小的,所以 strcat 函数假定程序员在执行这个函数时,已经为 dest 分配了足够多的内存,可以容纳 src 字符串中的所有内容,而一旦这个假定不成立,就会发生缓冲区溢出可能会造成程序运行终止

SDS 在修改字符串时会检查剩余空间(free),如果不足则自动扩展,避免溢出。

减少内存重分配次数

SDS 采用预分配空间的策略:

  • 当字符串长度增加时,SDS 会额外分配一些未使用的空间(free),减少后续修改时的内存重分配次数。
  • 例如,SDS 的扩容策略通常是:新长度小于 1MB 时,分配双倍空间;大于 1MB 时,额外分配 1MB。

二进制安全

C 语言的原生字符串以 \0 作为结束符,不能存储包含 \0 的二进制数据。因此其只能保存文本数据,不能保存图片,音频,视频和压缩文件等二进制数据,否则可能出现字符串不完整的问题,所以其是二进制不安全。

SDS 通过 len 字段记录长度,可以存储任意二进制数据,包括 \0

兼容C语言字符串函数

SDSbuf 字段末尾会自动添加 \0,因此可以直接使用 C 语言的字符串函数(如 printf)。

SDS的操作

Redis 提供了一系列函数来操作 SDS,例如:

  • 创建 SDSsdsnewsdsempty
  • 追加字符串sdscat
  • 复制字符串sdscpy
  • 释放 SDSsdsfree
  • 获取长度sdslen
  • 获取剩余空间sdsavail

总结

SDS 是 Redis 中用于表示字符串的底层数据结构,具有高效、安全、灵活的特点。它通过预分配空间、记录长度等方式,避免了 C 语言原生字符串的缺陷,同时兼容 C 语言的字符串函数。SDS 的设计是 Redis 高性能和高可靠性的重要基础之一。


http://www.kler.cn/a/561041.html

相关文章:

  • 【无人集群系列---无人机集群编队算法】
  • 免填邀请码工具:赋能六大核心场景,重构App增长新模型
  • 故障诊断 | DCS差异创意搜索算法优化CatBoost故障诊断(MatlabPython)
  • 微软量子芯片引领人工智能革命,开启计算新纪元
  • 算法日记27:完全背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
  • 当G1机器人跳出“丝滑舞步“:算力+AI 催生具身智能
  • 鸿蒙系统-同应用跨设备数据同步(分布式功能)
  • 【SQLI】sqlmap Tamper 脚本分类总结
  • LangChain教程 - RAG - PDF摘要
  • Elasticsearch中的CURL请求详解
  • Java——单例类设计模式
  • 【栈与队列】N叉树的层序遍历 二叉树的锯齿形层序遍历
  • DeepSeek在MATLAB上的部署与应用
  • 地铁站内导航系统:基于蓝牙Beacon与AR技术的动态路径规划技术深度剖析
  • C#语音识别与播报开发指南
  • LabVIEW C编译支持工具库CCompileSupp.llb
  • 本地开发用ASP.NET Core Web API项目创建及测试
  • 【学习笔记】Cadence电子设计全流程(三)Capture CIS 原理图绘制(中)
  • 【SQLI】CTF SQL注入解题步骤总结
  • hbase线上region不一致问题相关数据修复