当前位置: 首页 >  互联网技术 >  Redis数据结构二之SDS和双向链表

Redis数据结构二之SDS和双向链表

导读:本文首发于公众号:Hunter后端.原文链接:Redis数据结构二之SDS和双向链表.这一篇笔记介绍一下 SDS(simple dynamic string)和双向链表。.以下是本篇笔记目录:.SDS.常数复杂度获取字符串长度.杜绝缓冲区溢出.减少修改字符串带来的内存重分配次数.

本文首发于公众号:Hunter后端
原文链接:Redis数据结构二之SDS和双向链表

这一篇笔记介绍一下 SDS(simple dynamic string)和双向链表。

以下是本篇笔记目录:

  1. SDS
    1. 常数复杂度获取字符串长度
    2. 杜绝缓冲区溢出
    3. 减少修改字符串带来的内存重分配次数
    4. 二进制安全
    5. 兼容C字符串函数
  2. 双向链表

1、 SDS

SDS,simple dynamic string,即简单动态字符串

SDS 在 Redis 2.9 版本中数据结构如下:

struct sdshdr {
    int len;
    int free;
    char buf[];
};

在这个结构中,len 表示 buf 数组中已使用字节的数量,free 表示 buf 数组中未使用字节的数量,buf 则表示是一个 char 类型的数组。

Redis 没有复用 C字符串,有以下几个方面的考虑和优点。

1. 常数复杂度获取字符串长度

C字符串并不记录自身的长度信息,如果要获取C字符串的长度,必须遍历整个字符串然后计数。

SDS 结构中有 len 属性记录 SDS 本身的长度,可以直接获取。

2. 杜绝缓冲区溢出

因为 C字符串并不记录自身的长度信息,在执行某些操作,比如拼接字符串的时候,并不会自动查询是否拥有足够内存,那么这个操作可能就会造成缓冲区溢出的问题

而 SDS 执行相应的字符串修改时,其 API 会先检查 SDS 的空间是否需求,不满足则会进行扩展,这个空间分配策略也就是下面要讲的

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

C字符串每次进行字符串修改时,程序都需要手动进行内存重分配的操作,而 SDS 通过空间预分配和惰性空间释放两种策略对此进行了优化

空间预分配

当 SDS API 对一个 SDS 进行修改并需要对 SDS 进行空间扩展时,程序不仅会为 SDS 分配修改所需要的空间,还会为其分配额外的未使用空间

如果修改之后,SDS 的长度,也就是结构中的 len 属性小于 1MB,那么程序会额外分配同样大小的未使用空间,这个时候,len 属性和 free 属性将相同

如果修改之后,SDS 的长度,也就是结构中的 len 属性大于等于 1MB,那么程序会额外分配 1MB 的未使用空间

惰性空间释放

当需要对SDS保存的字符串进行缩短时,程序并不会重新分配内存来回收多出来的字节,而是会使用 free 属性将这些字节记录下来,以备后面使用

4. 二进制安全

C字符串保存的字符结尾都是以空字符结尾,所以字符串中间不能包含空字符,否则程序读入空字符的时候就会被认为是字符串结尾,因此C字符串只能保存文本数据,不能保存图片、音频等这样的二进制数据

而 SDS 的 API 都是以处理二进制的方式来处理 SDS 中存放在 buf 里的数据,程序不会对数据做任何限制、过滤,所以 SDS 的 API 都是二进制安全的

SDS 使用 len 属性值而不是空字符串来判断字符串是否结束

5. 兼容C字符串函数

虽然SDS的API都是二进制安全的,但是仍然遵循C字符串以空字符结尾的惯例,而且在为 buf 数组分配空间的时候总是会多分配一个字节来容纳这个空字符,所以保存文本数据的 SDS 可以重用一部分C中的函数

以下是 SDS 与 C字符串区别的总结:

C字符串 SDS
获取字符串长度复杂度为 O(N) 获取字符串长度复杂度为O(1)
API是不安全的,可能会造成缓冲区溢出 API是安全的,不会造成缓冲区溢出
修改字符串长度N次必须执行N次内存重分配 修改长度N次最多需要执行N次内存重分配
只能保存文本数据 可以保存文本或者二进制数据
可以使用库中函数 可以使用部分

在之后的的 Redis 版本对 SDS 的结构有过更新,将 free 属性换成了 alloc,这个属性表示的意思是分配的空间长度。和之前的 free 属性比较,其关系是 alloc = free + len

2、 双向链表

C 语言没有链表这个结构,所以 Redis 自己设计了一个链表数据结构。

在 Redis 中,链表节点的结构拥有指向前置节点和后置节点的属性。

链表结构则包含链表表头节点、表尾节点、节点长度等属性,便于快速获取链表相关信息。

双向链表是列表对象的底层实现之一,什么情况下使用双向链表作为列表对象的底层实现我们之后再介绍。

以下是链表节点的结构:

typedef struct listNode{
    // 前置节点
    struct listNode *prev;

    // 后置节点 
    struct listNode *next;

    // 节点值
    struct *value;

}listNode;

在链表节点中,拥有前置节点和后置节点的指针构成双向的链表。

以下是链表的结构:

typedef struct list{
    // 表头节点
    listNode *head;

    // 表尾节点
    listNode *tail;

    // 链表包含的节点数量
    unsigned long len;

    ...
}list;

在链表结构中,有表头节点和表尾节点可快速定位到链表的头部和尾部,以及用有 len 属性表示链表包含的节点数量。

如果想获取更多后端相关文章,可扫码关注阅读:

内容
  • Unity 中的存档系统(本地存档)
    Unity 中的存档系统(本地存
    2023-12-09
    思想.在游戏过程中,玩家的背包、登录、人物系统都与数据息息相关,无论是一开始就设定好的默认数据,还是可以动态存取的数据,
  • Unity3D高级编程主程手记 学习笔记二:C#技术要点
    Unity3D高级编程主程手记
    2023-12-06
    1.Untiy3D中C#的底层原理.Unity底层在运行C#程序时有两种机制:一种是Mono,另一种是IL2CPP。Mo
  • Mybatis的工作原理
    Mybatis的工作原理
    2023-12-05
    mybatis的工作原理.mybatis基本工作原理.封装sql ->调用JDBC操作数据库 -> 返回数据封装.JDB
  • 数据分析师如何用SQL解决业务问题?
    数据分析师如何用SQL解决业务问
    2023-12-03
    本文来自问答。.提问:数据分析人员需要掌握sql到什么程度?.请问做一名数据分析人员,在sql方面需要掌握到什么程度呢?
  • 缓存面试解析:穿透、击穿、雪崩,一致性、分布式锁、Redis过期,海量数据查找
    缓存面试解析:穿透、击穿、雪崩,
    2023-12-03
    为什么使用缓存.在程序内部使用缓存,比如使用map等数据结构作为内部缓存,可以快速获取对象。通过将经常使用的数据存储在缓
  • Unity学习笔记--数据持久化Json
    Unity学习笔记--数据持久化
    2023-12-02
    JSON相关.json是国际通用语言,可以跨平台(游戏,软件,网页,不同OS)使用,.json语法较为简单,使用更广泛。
  • 软件定制开发服务
    软件定制开发服务
    2024-01-05
    软件定制开发服务.产品功能.我们的软件定制开发服务为客户提供了一站式的解决方案,包括需求分析、设计开发、**部署和维护支
  • ***安全解决方案
    ***安全解决方案
    2024-01-10
    ***安全解决方案.产品功能.我们的服务器安全解决方案是一款专为企业服务器量身定制的安全软件,旨在保护企业服务器免受恶意
  • 电子元件芯片
    电子元件芯片
    2024-01-20
    电子元件芯片.产品功能.电子元件芯片是一种微型电子元件,其具有高性能、高可*性和低功耗的特点。它广泛应用于手机、电脑、家
  • ***远程监控系*
    ***远程监控系*
    2023-12-16
    ***远程监控系*.产品功能.我们的服务器远程监控系*是一款针对企业服务器管理的智能监控系*。它具有实时监控、远程操作、
  • 电子元件模块
    电子元件模块
    2023-12-21
    电子元件模块.我们的电子元件模块是一款专为电子爱好者和工程师设计的多功能模块。它集成了多种常用的电子元件和功能模块,可以
  • 电子元件连接器
    电子元件连接器
    2023-12-31
    电子元件连接器.产品功能.电子元件连接器是一种用于连接不同电子元件的重要组件。它可以提供可*的电气连接,从而实现各种电子
  • 人工智能应用软件
    人工智能应用软件
    2024-01-15
    人工智能应用软件产品介绍.产品功能.我们的人工智能应用软件集成了多种先进的人工智能技术,包括机器学习、自然语言处理、计算
  • ***数据备份方案
    ***数据备份方案
    2024-01-15
    ***数据备份方案.产品功能.自动化备份:定期自动备份***上的数据,无需人工干预,确保数据的及时、准确备份。.数据恢复
  • ***软件
    ***软件
    2023-12-06
    ***软件产品介绍.产品描述.我们的服务器软件是一款高性能、稳定可靠的服务器管理软件,具有强大的功能和灵活的配置,适用于
  • 移动应用开发
    移动应用开发
    2023-12-01
    移动应用开发.产品描述.移动应用开发是一种专注于为移动设备(如智能手机、平板电脑)开发应用程序的技术和流程。这些应用程序