Redis数据结构——Redis简单动态字符串SDS

定义

众所周知,Redis是由C语言写的。
对于字符串类型的数据存储,Redis并没有直接使用C语言中的字符串。
而是自己构建了一个结构体,叫做“简单动态字符串”,简称SDS,比C语言中的字符串更加灵活。

SDS的结构体是这样的:

struct{int len; // 数组中已使用的字节的数量,即真实的内容长度 int free; // 数组中未使用的字节的数量,即还可以继续存储的内容的长度 char buff[]; // 字节数组,用来保存字符串 
};

在C语言中,总是使用长度是N+1的字符数组来保存长度为N的字符串,并且字符数组的最后一个是’\0’结束符,在SDS中,一次申请的字符串的长度比真实的长,所以才会有free这个属性

SDS与C语言字符串相比,优点是:

  • O(1)复杂度获取字符串长度
  • 防止了内存溢出
  • 减少内存分配的次数
  • 二进制安全

获取字符串长度

对于C字符串来说,获取一个字符串的真实长度,需要遍历字符串,这就是O(N)的时间复杂度。
而在SDS中,用一个len属性保存字符串的真实长度,每次对字符串的修改,都会维护这个len属性
因此对于SDS来说,获取字符串的真实长度的时间复杂度是O(1),这确保了获取字符串长度的操作不会成为Redis字符串的性能瓶颈

内存溢出问题

在C字符串中,如果要对字符串进行修改操作,如果忘记了给字符串重新分配足够的空间,就会导致内存溢出问题。在C语言中,并没有内存溢出相关的检查机制,因此可能会导致不可预测的问题产生。

通过SDS的API来操作字符串时,会先检查SDS的空间是否满足修改的要求,如果不满足的话,会自动将SDS的空间扩展至要求的大小,然后执行字符串操作,所以使用SDS来操作字符串,不用担心内存溢出问题。

减少内存分配的次数

对于C语言字符串,因为总是有一个长度为N+1的字符数组来保存一个长度为N的字符串。
所以,如果对C字符串进行操作:

  • 如果进行字符串的长度增长的操作,比如追加字符append,那么在执行这个操作前,需要先为字符串分配新的内存空间,然后才能执行操作。如果忘记了重新分配内存,会导致内存溢出问题。
  • 如果进行字符串长度的减少操作,比如删除某个字符,那么在执行这个操作之后,需要释放掉不再使用的内存空间。如果忘记了释放内存,会导致内存泄漏问题。

而对于SDS来说,不存在这些问题,通过两个机制来解决以上问题

  • 空间预分配
  • 惰性空间释放

1. 空间预分配

空间预分配机制,用来优化SDS字符串的增长操作。
我们认为初始化赋值和拼接操作都是对于SDS的扩容操作。
当SDS来扩容一个字符串时,系统不仅会为SDS分配所需的内存空间大小,还会分配额外的未使用空间,即系统分配给SDS的空间大小比真实的字符串长度要大。
至于,额外的空间有多大,有以下规则:

  • 当扩容后的SDS的长度小于1MB,那么程序分配的额外空间就是len的大小,即与真实的字符串的空间大小相同。例如,扩容后,SDS的len的长度是20,那么额外的空间也是20,总共的SDS的空间是40字节。
  • 如果扩容后的SDS的长度大于等于1MB,那么程序会分配1MB的额外空间。

通过空间预分配策略,可以减少字符串增长操作的内存分配次数。
当进行字符串增长操作时,会先检查free的空间大小是否够增加的长度,如果够,那么直接在真实的数组上操作,无需再进行内存分配操作,并维护free和len的值。
如果不够,那么就会进行扩容操作,扩容机制上面说过了。

2. 惰性空间释放

惰性空间释放用来优化字符串的缩短操作。
当SDS缩短一个字符串时,还是直接在原始的数组上操作,并维护len和free的值。
缩短完成后,程序并不会立即回收释放后的内存,而是使用free属性记录下来,方便下次的字符串长度增加时使用。

二进制安全

C字符串中的字符必须符号某种编码,例如,当编码格式是ASCII时,除了末尾的空字符’\0’外,字符串内容中不可以出现空字符,否则程序在读取字符串时,会误以为这是字符串的结尾。
这样的限制使得,C字符串只能保存文本数据,而不能保存图片、音频等二进制数据。
而SDS会以二进制的方式来处理存放到buff数组中的数据,程序不会对其中的数据进行限制、过滤等额外操作
这就是我们称SDS是字节数组的原因——Redis不是用buff数组来保存字符,而是保存一系列的二进制数据

SDS不是使用空字符’\0’来判断字符串的结尾,而是使用len属性来判断字符串是否结尾
如"Redis\0String",C字符串的函数会把’\0’当做结束符来处理,而忽略到后面的"String"。而SDS的buf字节数组不是在保存字符,而是一系列二进制数组,SDS API都会以二进制的方式来处理buf数组里的数据,使用len属性的值而不是空字符来判断字符串是否结束。

参考文章

Redis数据结构——简单动态字符串SDS - 随心所于 - 博客园
《Redis设计与实现》

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

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

相关文章

Python-OpenCV中的图像处理-视频分析

Python-OpenCV中的图像处理-视频分析 视频分析Meanshift算法Camshift算法光流 视频分析 学习使用 Meanshift 和 Camshift 算法在视频中找到并跟踪目标对象: Meanshift算法 Meanshift 算法的基本原理是和很简单的。假设我们有一堆点(比如直方 图反向投影得到的点&…

ASR 语音识别接口封装和分析

这个文档主要是介绍一下我自己封装了 6 家厂商的短语音识别和实时流语音识别接口的一个包,以及对这些接口的一个对比。分别是,阿里,快商通,百度,腾讯,科大,字节。 zxmfke/asrfactory (github.c…

ubuntu 安装 cuda

ubuntu 安装 cuda 初环境与设备在官网找安装方式 本篇文章将介绍ubuntu 安装 CUDA Toolkit CUDA Toolkit 是由 NVIDIA(英伟达)公司开发的一个软件工具包,用于支持并优化 GPU(图形处理器)上的并行计算和高性能计算。它…

解析TCP/IP协议的分层模型

了解ISO模型:构建通信的蓝图 为了促进网络应用的普及,国际标准化组织(ISO)引入了开放式系统互联(Open System Interconnect,OSI)模型。这个模型包括了七个层次,从底层的物理连接到顶…

一、Dubbo 简介与架构

一、Dubbo 简介与架构 1.1 应用架构演进过程 单体应用:JEE、MVC分布式应用:SOA、微服务化 1.2 Dubbo 简介一种分布式 RPC 框架,对专业知识(序列化/反序列化、网络、多线程、设计模式、性能优化等)进行了更高层的抽象和…

ArcGIS Maps SDK for JavaScript系列之三:在Vue3中使用ArcGIS API加载三维地球

目录 SceneView类的常用属性SceneView类的常用方法vue3中使用SceneView类创建三维地球项目准备引入ArcGIS API创建Vue组件在OnMounted中调用初始化函数initArcGisMap创建Camera对象Camera的常用属性Camera的常用方法 要在Vue 3中使用ArcGIS API for JavaScript加载和展示三维地…

Java旋转数组中的最小数字(图文详解版)

目录 1.题目描述 2.题解 分析 具体实现 方法一(遍历): 方法二(排序): 方法三(二分查找): 1.题目描述 有一个长度为 n 的非降序数组,比如[1,2,3,4,5]&a…

npm install 中 --save 和 --save-dev 是什么?

npm,全名 Node Package Manager,套件管理工具,package.json 会记下你在项目中安装的所有套件。 假设在项目中安装 lodash npm i --save lodash这样在 dependencies 中会出现: 如果修改了导入方式: npm i --save-dev …

Labview解决“重置VI:xxx.vi”报错问题

文章目录 前言一、程序框图二、前面板三、问题描述四、解决办法 前言 在程序关闭前面板的时候小概率型出现了 重置VI:xxx.vi 这个报错,并且发现此时只能通过任务管理器杀掉 LabVIEW 进程才能退出,这里介绍一下解决方法。 一、程序框图 程序…

pve7.2虚拟机 lvm磁盘扩容,增加硬盘操作

之前安装pve时候只有256的ssd,最近安装的虚拟机较多,给加块闲置硬盘,顺便学习一下,像pve这种虚拟机系统,硬盘应该可以像nas你这样随时增加,而不影响上层应用,我自己也是摸索着做。 一、安装好硬盘后打开pv…

vue3+ts-tsconfig.json报错Option ‘importsNotUsedAsValues’

vue3ts-tsconfig.json报错Option ‘importsNotUsedAsValues’ is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption ‘“ignoreDeprecations”: “5.0”’ to silence this error. Use ‘verbatimModuleSyntax’ instead 自我记录 翻译 选项…

echart 3d立体颜色渐变柱状图

如果可以实现记得点赞分享,谢谢老铁~ 1.需求描述 根据业务需求将不同的法律法规,展示不同的3d立体渐变柱状图。 2.先看下效果图 3. 确定三面的颜色,这里我是自定义的颜色 // 右面生成颜色const rightColorArr ref(["#79D…

ComponentOne Studio ASP.NET MVC Crack

ComponentOne Studio ASP.NET MVC Crack FlexReport增强功能 添加了对在Microsoft Windows上部署Microsoft Azure的支持。 添加了对显示嵌入字体的支持。 .NET标准版的经典C1PDF(Beta版) GrapeCity的经典C1Pdf库现在提供了基于Microsoft.NET标准的版本。在任何.NET应用程序(包括…

江南大学计算机考研分析

24计算机考研|上岸指南 江南大学 江南大学计算机考研招生学院是人工智能与计算机学院。目前均已出拟录取名单。 江南大学人工智能与计算机学院成立于2020年3月,办学历史可追溯到1994年设立的计算机应用专业。学院秉持江南大学“彰显轻工特色,服务国计民…

【数据结构】栈和队列

【数据结构】栈和队列 一: 栈1.栈的概念及和结构2. 栈的实用3. 栈接口实现 二: 队列1. 队列的概念和结构2. 队列的实用3. 队列接口实现 三:扩展 一: 栈 1.栈的概念及和结构 栈:一种特殊的线性表,其只允许…

SAP安全库存-安全库存共享、安全库存简介

SAP系统中的安全库存用于管理计划外和计划内的库存需求,在某些行业中,由于不同的情况,如意外损耗、损坏、环境问题、制造工艺问题、需求增加等,通常会出现意外的库存需求。 SAP提供了维护安全库存的处理方式来处理这样的问题,安全库存的字段信息在主数据视图中,在物料需…

题解 | #1002.Shortest path# 2023杭电暑期多校9

1002.Shortest path 签到题 记忆化搜索 题目大意 给定一个正整数 n n n ,可以对其进行以下操作: 如果 n n n 能被 3 3 3 整除,则可以使 n n / 3 nn/3 nn/3 ;如果 n n n 能被 2 2 2 整除,则可以使 n n / 2 nn/2 nn/2 …

【C++】deque容器

0.前言 1.deque构造函数 #include <iostream> using namespace std; #include <deque>//deque构造函数 void printDeque(const deque<int>& d) {for (deque<int>::const_iterator it d.begin(); it ! d.end(); it){//*it 100; //加了const就不能…

go的gin和gorm框架实现切换身份的接口

使用go的gin和gorm框架实现切换身份的接口&#xff0c;接收前端发送的JSON对象&#xff0c;查询数据库并更新&#xff0c;返回前端信息 接收前端发来的JSON对象&#xff0c;包含由openid和登陆状态组成的一个string和要切换的身份码int型 后端接收后判断要切换的身份是否低于该…

windows下dll文件的创建详细教程

1、前言 dll文件是啥&#xff0c;就不作过多赘述了。现在直接教大家如何创建与使用dll文件。 本文基于windows系统&#xff0c;使用的编译相关工具为visual studio 2019。 2、创建dll 2.1 创建dll工程 首先打开visual studio&#xff0c;然后选择创建新项目&#xff0c;在搜…