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

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 高性能和高可靠性的重要基础之一。

相关文章:

  • MySQL80 配置主从复制方案(双主双从)
  • JavaScript 前端面试 5()
  • 最长递增子序列(贪心算法)思路+源码
  • 鸿蒙开发中 数组 find 的理解
  • 【代码随想录】第九章-动态规划(上)
  • 2.1 第一个程序:从 Hello World 开始
  • 安装Redis并把Redis设置成windows下的服务然后进行Redis实例演示
  • LabVIEW中CFURL.llb 工具库说明
  • vue3: directive自定义指令防止重复点击
  • 【java】成员变量和局部变量
  • 【python】提取word\pdf格式内容到txt文件
  • Mac中的oss上传
  • 2.3 变量
  • 【复习】Redis
  • 2.2 STM32F103C8T6最小系统板的四种有关固件的开发方式
  • Python Django系列—入门实例
  • 云原生降本之路:技术创新与应用解析
  • clickhouse--表引擎的使用
  • 防漏电保护,塔能物联运维为城市照明安全“上锁”
  • 数据库索引:原理、设计与优化
  • 做搜索网站挣钱/网页seo搜索引擎优化
  • 东营网站建设制作/竞价排名点击器
  • 做同城网站赚钱吗/网络营销常见的工具
  • 农业网站建设/线上销售渠道有哪些
  • 网站的想法/aso安卓优化公司
  • 怎么做自己的一个网站/如何弄一个自己的网站