Redis底层数据结构之SDS

news2024/12/23 7:36:40

目录

    • 一、概述
    • 二、SDS结构
    • 三、为什么使用SDS

下一篇 redis底层数据结构之ziplist

一、概述

Redis 中的 SDS(Simple Dynamic String,简单动态字符串)是 Redis 用于存储字符串值的底层实现,是对 C 语言传统字符串(以 null 结尾的字符数组)的改良,内部结构类似于 C 语言的字符数组,但额外存储了字符串长度和分配空间大小,避免了 C 字符串的缺陷。SDS 用于解决 C 字符串的一些限制和安全性问题, 具有动态扩容的特点. 其实现位于src/sds.hsrc/sds.c中。SDS 除了保存数据库中的字符串值以外,SDS 还可以作为缓冲区(buffer):包括 AOF 模块中的AOF缓冲区以及客户端状态中的输入缓冲区。

二、SDS结构

在这里插入图片描述
在这里插入图片描述

三、为什么使用SDS

  1. 长度灵活
    SDS 在内存中的表示包含了字符串的长度信息,因此它可以包含任意长度的数据,包括空字符(‘\0’)。这解决了 C 字符串无法存储空字符的问题。

  2. 快速获取长度
    由于 len 属性的存在,我们获取 SDS 字符串的长度只需要读取 len 属性,时间复杂度为 O(1)。而对于 C 语言,获取字符串的长度通常是经过遍历计数来实现的,时间复杂度为 O(n)。通过 strlen key 命令可以获取 key 的字符串长度。

  3. 防止缓冲区溢出
    在 C 语言中使用 strcat 函数来进行两个字符串的拼接,一旦没有分配足够长度的内存空间,就会造成缓冲区溢出。而对于 SDS 数据类型,在进行字符修改的时候,会首先根据记录的 len 属性检查内存空间是否满足需求, 如果不满足,会进行相应的空间扩展,然后在进行修改操作,所以不会出现缓冲区溢出。

  4. 减少修改字符串时的内存重新分配次数
    C语言由于不记录字符串的长度,所以如果要修改字符串,必须要重新分配内存(先释放再申请),因为如果没有重新分配,字符串长度增大时会造成内存缓冲区溢出,字符串长度减小时会造成内存泄露。而对于SDS,由于len属性和alloc属性的存在,对于修改字符串SDS实现了空间预分配和惰性空间释放两种策略:

    • 空间预分配:对字符串进行空间扩展的时候,扩展的内存比实际需要的多,这样可以减少连续执行字符串增长操作所需的内存重分配次数。
      • 如果对 SDS 进行修改之后, SDS 的长度(也即是 len 属性的值)将小于 1 MB , 那么程序分配和 len 属性同样大小的未使用空间, 这时 SDS len 属性的值将和 free 属性的值相同。 举个例子, 如果进行修改之后, SDS 的 len 将变成 13 字节, 那么程序也会分配 13 字节的未使用空间, SDS 的 buf 数组的实际长度将变成 13 + 13 + 1 = 27 字节(额外的一字节用于保存空字符)。
      • 如果对 SDS 进行修改之后, SDS 的长度将大于等于 1 MB , 那么程序会分配 1 MB 的未使用空间。 举个例子, 如果进行修改之后, SDS 的 len 将变成 30 MB , 那么程序会分配 1 MB 的未使用空间, SDS 的 buf 数组的实际长度将为 30 MB + 1 MB + 1 byte 。
    • 惰性空间释放:对字符串进行缩短操作时,程序不立即使用内存重新分配来回收缩短后多余的字节,而是使用 alloc 属性将这些字节的数量记录下来,等待后续使用。(当然SDS也提供了相应的API,当我们有需要时,也可以手动释放这些未使用的空间。)
  5. 二进制安全
    SDS 可以存储任何二进制数据,包括图片、音频等非文本数据。这是因为 SDS 不依赖 null 字符来标识字符串的结束,而是以 len 属性表示的长度来判断字符串是否结束,因此数据中可以包含任意的二进制序列。

  6. 兼容部分 C 字符串函数
    尽管 SDS 是对 C 字符串的扩展,但它的存储布局确保了在以 \0 结尾处的内存地址上的内容可以被视为一个正常的 C 字符串,这意味着可以在不需要复制字符串的前提下,利用 C 的一些标准库函数来操作 SDS。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1613510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用 Node.js 发送电子邮件全解和相关工具推荐

大多数Web应用程序都需要发送电子邮件。它可能用于注册、密码重置、状态报告,甚至是完整的市场营销活动,如新闻和促销。本教程解释了如何在Node.js中发送电子邮件,但其概念和挑战适用于您正在使用的任何系统。 你会在 npm 上找到大量与电子邮…

深度图转点云

一、理论分析 二、其他分析 1、相机内参 相机内参主要是四个参数fx,fy,u0,v0。要明白相机内参就是相机内部参数,是参考像素坐标系而言,有了这个前提,这四个参数也就很好理解了。 (1)首先,。其中F是相机的…

内存管理下及模板初阶

嗨喽,今天阿鑫给大家带来内存管理下以及模板初阶的博客,下面让我们开始今天的学习吧! 内存管理下及模板初阶 new和delete的实现原理定位new表达式(placement-new)常见面试题泛型编程函数模板类模板 1. new和delete的实现原理 1.1 内置类型…

上位机工作感想-从C#到Qt的转变-1

0.前言 接触Qt开发也有一年多的时间了,还记得去年初从杭州回合肥时,刚来公司面临的几个问题: 1.C#转上位机的迷茫2.新公司管理模式的差异3.试用期的各种紧急任务。 当时也是加班加点学习C和Qt的基础知识,做了两个考核项目后&am…

Hadoop——Yarn 生产环境核心参数

1. ResourceManager 相关参数: yarn.resourcemanager.hostname:ResourceManager 的主机名。yarn.resourcemanager.webapp.address:ResourceManager 的 Web 应用程序地址。yarn.resourcemanager.scheduler.address:ResourceManage…

MB21屏幕增强

MB21 增强 一、屏幕抬头增强 需要在屏幕的抬头添加两个字段,并将字段保存至自建表 二、增强步骤 首先屏幕中的收货字段找到对应的屏幕为0521。 在对应的屏幕添加增强的字段:命名需要和对应的表名一样 根据需求,增强只针对预留中的异动…

华为机考入门python3--(16)牛客16-购物单最大满意度

分类:动态规划,组合,最大值,装箱问题 知识点: 生成递减数 100, 90, 80, ..., 0 range(100, -1, -10) 访问列表的下标key for key, value in enumerate(my_list): 动态规划-捆绑装箱问题 a. 把有捆绑约束的物…

SpringMvc的核心组件和执行流程

一、 springmvc的核心组件及作用 1.DispatcherServlet:前置控制器,是整个流程控制的核心,用来控制其他组件的执行,降低了其他组件的耦合性 2.Handler:控制器,完成具体的业务逻辑,当DispatcherServlet接收到请求后&am…

力扣70:爬楼梯(经典动态规划)

题目 解题思路 考虑动态规划&#xff0c;dp[i]表示爬到第i层的方法种数&#xff0c;对于第i层&#xff0c;可以从第i-2层爬两个台阶到达&#xff0c;也可以从i-1层爬一个台阶到达&#xff0c;故dp[i]dp[i-1]dp[i-2]&#xff0c;输出dp[n]即为答案 代码 #include<iostream…

CSS——高级选择器

层次的选择器&#xff1a; <1> 后代选择器&#xff1a; 格式&#xff1a; 标签1 标签2{} 解释&#xff1a; 标签1 不生效&#xff0c;被标签1 嵌套中的 标签2才生效 举例&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charse…

利用fft算法理解频率和像素变化率的关系

算法我就不贴了。算法就是算法导论的内容。 我直接写推导过程。 假设变化率为f(n1)-f(n) 首先计算二进制数&#xff0c;这里我假设为3位二进制。 例如:f(5)-f(4)&#xff0c; 5和4的二进制为101,100。所以逆序数为101&#xff0c;001 101对应的频率为5, 001对应的频率为1…

go | defer、panic、recover

刷一道题&#xff0c; 将当函数触发panic 之后&#xff0c;函数是怎么执行的 然后我去找相关博客&#xff0c;发现这篇讲的蛮好的 接下来我直接上demo &#xff0c;然后通过demo 来逐个分析 package mainimport ("fmt" )func f() {defer func() {if r : recover();…

【 AIGC 研究最新方向(上)】面向平面、视觉、时尚设计的高可用 AIGC 研究方向总结

目前面向平面、视觉、时尚等设计领域的高可用 AIGC 方向有以下 4 种&#xff1a; 透明图层生成可控生成图像定制化SVG 生成 本篇&#xff08;上篇&#xff09;介绍 1、2&#xff0c;而下篇将介绍 3、4。 透明图层生成 LayerDiffuse 代表性论文&#xff1a;Transparent Imag…

23种设计模式之抽象工厂

简单工厂和工厂方法 关注 产品等级 抽象工厂 关注 产品族 对于比较稳定的产品&#xff0c;抽象工厂更有效率&#xff08;一个工厂生产很多产品族&#xff09; 抽象工厂代码例子加深理解

数组的删除与插入优化思路

数据结构&#xff1a;线性表、非线性表 线性表&#xff1a; 数组&#xff0c;链表、队列、栈等。 线性表就是数据排成像一条线一样的结构&#xff0c;每个线性表上的数据最多只有前和后两个方向。 非线性表&#xff1a; 二叉树、堆、图等。 在非线性表中&#xff0c;数据之间并…

09 JavaScript学习:对象

对象的概念 在计算机科学中&#xff0c;对象是一种数据结构&#xff0c;用于存储数据和方法&#xff08;也称为函数&#xff09;。对象可以包含属性&#xff08;也称为成员变量&#xff09;和方法&#xff08;也称为成员函数&#xff09;&#xff0c;通过这些属性和方法可以描述…

SpringMVC--RESTful

1. RESTful 1.1. RESTful简介 REST&#xff1a;Representational State Transfer&#xff0c;表现层资源状态转移。 RESTful是一种网络架构风格&#xff0c;它定义了如何通过网络进行数据的交互。这种风格基于HTTP协议&#xff0c;使得网络应用之间的通信变得更加简洁和高效。…

每天五分钟机器学习:神经网络模型参数的选择

本文重点 在深度学习和人工智能的浪潮中,神经网络作为其中的核心力量,发挥着举足轻重的作用。然而,神经网络的性能并非一蹴而就,而是需要经过精心的参数选择和调优。 神经网络由大量的神经元组成,每个神经元之间通过权重进行连接。这些权重,以及神经元的偏置、激活函数…

CSS基础:position定位的5个类型详解!

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

《R语言与农业数据统计分析及建模》学习——数据框的统计处理

1、数据框的透视 aggregate()函数用于对数据框进行聚合操作&#xff0c;可以按照指定的条件对数据进行分组&#xff0c;并计算每组的汇总统计量。函数如下&#xff1a; aggregate(formula,data,FUN,...) formula&#xff1a;定义聚合的公式&#xff0c;指定需要聚合的变量和分…