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

news2024/11/25 12:35:52

定义

众所周知,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.coloradmin.cn/o/876446.html

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

相关文章

vue + less 实现动态主题换肤功能

文章目录 前言一、前提条件1. 初始化vue项目2. 安装插件 二、新建文件夹主题theme1.style.less文件2.model.js文件3.theme.js文件theme文件夹最终效果 三、修改vue.config.js文件四、页面上的具体使用1. index.vue 页面2. index.vue 页面注意点说明3. index.vue 效果 五、在js中…

学会这一招,轻松玩转小程序自动化

jmeter 可以做性能测试,这个很多人都知道,那你知道,jmeter 可以在启动运行时,指定线程数和运行时间,自定义性能场景吗? jmeter 性能测试,动态设定性能场景 平时,我们使用 jmeter 进…

《图解HTTP》——HTTP协议详解

一、HTTP协议概述 HTTP是一个属于应用层的面向对象协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP…

TiDB Bot:用 Generative AI 构建企业专属的用户助手机器人

本文介绍了 PingCAP 是如何用 Generative AI 构建一个使用企业专属知识库的用户助手机器人。除了使用业界常用的基于知识库的回答方法外,还尝试使用模型在 few shot 方法下判断毒性。 最终,该机器人在用户使用后,点踩的比例低于 5%&#xff0…

安科瑞电力监控系统在某区块页岩气地面集输工程中的应用

摘要:Acrel-2000Z电力监控系统适用于35kV及以下电压等级的各类变电站,可以帮助用户掌握配电系统实时运行状态, 获取预警、告警等各类事件,实现区域的无人值守,提高监管水平。本文介绍了安科瑞电力监控系统Acrel-2000在…

elasticsearch-head 插件

1、elastic 插件说明 **Head** 是第三方提供的一款很优秀的插件,集监控、查询、配置一体的web功能系统,可以在系统中进行创建、删除索引 、文档。以及查询、配置索引等功能,深受广大开发者的喜爱 **Kopf** 是另一个第三方提供的一款很优秀…

【Java】2022 RoboCom 机器人开发者大赛-高职组(省赛)题解

7-15 您好呀 本届比赛的主题是“智能照护”,那么就请你首先为智能照护机器人写一个最简单的问候程序 —— 无论遇见谁,首先说一句“您好呀~”。 输入格式: 本题没有输入 输出格式: 在一行中输出问候语的汉语拼音 Nin Hao Ya ~…

《局外人》阅读笔记

《局外人》阅读笔记 2023年8月14日在杭州小屋读完。我看的是张雨彤编译的这本,这本书包含了两部分,第一部分是《局外人》是原版的小说故事,第二部分是《堕落》包括了六天内的自然自语,完全没看懂,写作风格突变&#xf…

Python爬虫IP代理池的建立和使用

写在前面 建立Python爬虫IP代理池可以提高爬虫的稳定性和效率,可以有效避免IP被封锁或限制访问等问题。 下面是建立Python爬虫IP代理池的详细步骤和代码实现: 1. 获取代理IP 我们可以从一些代理IP网站上获取免费或付费的代理IP,或者自己租…

【人工智能前沿弄潮】—— SAM系列:SAM自动生成物体mask

SAM自动生成物体mask 由于SAM可以高效处理提示,可以通过在图像上抽样大量的提示来生成整个图像的mask。这种方法被用来生成数据集SA-1B。 类SamAutomaticMaskGenerator实现了这个功能。它通过在图像上的网格中对单点输入提示进行抽样,从每个提示中SAM可…

报名小程序PowerActivity配置

https://github.com/zhihuliukanshan/PowerActivity/assets/100545532/9b3e2a3b-f810-4c1f-90d5-9596d99abbd3 导入代码后,需要配置的位置有: 1、miniprogram\setting\setting.js中的CLOUD_ID: module.exports {//### 环境相关 CLOUD_ID: …

【论文阅读】基于深度学习的时序预测——LTSF-Linear

系列文章链接 论文一:2020 Informer:长时序数据预测 论文二:2021 Autoformer:长序列数据预测 论文三:2022 FEDformer:长序列数据预测 论文四:2022 Non-Stationary Transformers:非平…

手把手教你如何零成本搭建网站实现内网穿透从而创建自己的数据隧道

手把手教你如何零成本搭建网站实现内网穿透从而创建自己的数据隧道 文章目录 手把手教你如何零成本搭建网站实现内网穿透从而创建自己的数据隧道前言1. 安装网站运行和发布必备软件2. 安装PHPStudy3. 安装wordpress4. 进入wordpress安装程序,进行网页编辑和设置5. 安…

使用FTP文件传输协议的潜在风险

数据(事实,数字,价值)是当今业务运行的核心要素。但是,如果数据没有得到有效的存储和传输,它们就会成为阻碍业务发展的障碍。如果企业不能及时地把数据送到合适的地方,就会造成严重的经济损失。…

Freemarker+thymeleaf应用实现打印银行小票

背景&#xff1a;最近项目里有个需求&#xff0c;需要动态配置一个模板&#xff0c;来打印各种不同银行或者其他行业的小票&#xff0c;下面小小记录一下实现过程。 关键词&#xff1a;Springboot, thymeleaf, Freemarker,html2image 一&#xff0c;引入依赖 <dependency…

汉诺塔:传说中的智慧游戏

文章目录 前言规则概述数学原理核心Java代码实现结语 前言 汉诺塔&#xff08;Hanoi Tower&#xff09;&#xff0c;又称汉诺塔游戏&#xff0c;是源自印度古老传说的经典智力游戏。这个谜题的起源被认为与印度的寺庙有关&#xff0c;是由僧侣们传承的智慧游戏。汉诺塔塔座包含…

【Java】Web应用的文件上传下载

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Web应用的文件上传下载&#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x1faf0;&#x1…

日撸java三百行day84-87

文章目录 说明1. 网络结构与参数1.1 单层1.2 多层管理 2. CNN网络构建2.1 构建CNN网络建构2.2 初始化卷积神经网络FullCnn对象2.3 获取数据集2.4 训练数据2.4.1 前向传播函数forward2.4.1.1 CONVOLUTION卷积层2.4.1.2 SAMPLING 池化层2.4.1.3 OUTPUT 输出层 2.4.2 反向传播函数…

【华为Datacom 综合拓扑案例—分享篇】

拓扑图 题目要求 实验要求&#xff1a; 1、PC1\PC2\PC3\PC4采用DHCP自动获取IP地址&#xff0c;SW5作为服务器&#xff0c;SW3和SW4作为中继 创建地址池ip pool huawei1和ip pool huawei2&#xff0c;租期都为2天 2、SW3与SW4做链路聚合&#xff0c;采用LACP模式。SW3作为主…

tauri-react:快速开发跨平台软件的架子,支持自定义头部和窗口阴影效果

tauri-react 一个使用 taurireacttsantd 开发跨平台软件的模板&#xff0c;支持窗口头部自定义和窗口阴影&#xff0c;不用再自己做适配了&#xff0c;拿来即用&#xff0c;非常 nice。 开原地址&#xff1a;GitHub - Sjj1024/tauri-react: 一个最基础的使用tauri和react开发…