「Redis数据结构」动态字符串(SDS)

news2025/7/22 10:20:28

「Redis数据结构」动态字符串(SDS)

文章目录

  • 「Redis数据结构」动态字符串(SDS)
    • @[toc]
    • 一、前言
    • 二、概述
    • 三、C字符串与SDS的区别
      • 获取字符串长度复杂度
      • 杜绝缓冲区溢出
      • 减少修改字符串时的内存分配次数
      • 二进制安全
      • 兼容部分C字符串函数
    • 参考

一、前言

我们都知道Redis中保存的Key是字符串,value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。

Redis采用C语言来实现,但并没有使用C语言传统字符串的表示,而是自己构建了一种名为简单动态字符串(simple dynamic string,SDS)的数据结构,并将SDS作为Redis的默认字符串表示。在Redis里C字符串只会作为字面量用在一些无需对字符串修改的地方,入打印日志。


二、概述

Redis构建了一种新的字符串结构,称为简单动态字符串(Simple Dynamic String),简称SDS
例如,我们执行命令:

image-20221114230819741.

那么Redis将在底层创建两个SDS,其中一个是包含“name”的SDS,另一个是包含“frozenpenguin”的SDS。

Redis是C语言实现的,其中SDS是一个结构体,源码如下:

image-20221114230857879

例如,一个包含字符串“name”的sds结构如下:

1653984648404

SDS之所以叫做动态字符串,是因为它具备动态扩容的能力,例如一个内容为“hi”的SDS:

1653984787383

假如我们要给SDS追加一段字符串“,Amy”,这里首先会申请新内存空间:

如果新字符串小于1M,则新空间为扩展后字符串长度的两倍+1;

如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配。

1653984822363

1653984838306

三、C字符串与SDS的区别

Redis没有直接使用C语言中的字符串,因为C语言字符串存在很多问题。

image-20221114232509292

获取字符串长度复杂度

C语言使用N+1的字符串数组来表示长度为N的字符串,并且数组的最后一个元素总是空字符串’/0’,C字符串并不记录自身的长度信息,每次获取长度需要重新遍历字符串直到遇到’/0’为止,这个复杂度为O(N)

SDS在len属性中保存了字符串的长度,所以获取字符串长度的复杂度为O(1),设置和更新SDS长度的工作是由SDS的API在执行时自动完成的,不需要进行手动的修改。

杜绝缓冲区溢出

C字符串如果在修改字符串之前没有分配足够的内存空间会造成缓冲区溢出

SDS在修改时会先检查SDS的空间是否足够,如果空间不足,会自动扩展空间至修改所需要的大小,再去执行修改操作。

减少修改字符串时的内存分配次数

C字符串的底层实现总是一个N+1个字符长度的数组,因为C字符串和底层数组之间的长度存在这种关联性,所以每次修改字符串时会重新分配数组的内存空间(如果增长字符串而不进行重新分配内存会产生缓冲区溢出,减少的话会产生内存泄露)。

为了避免C字符串的这种缺陷,SDS通过未使用空间解除了字符串长度和底层数组之间的关联,在SDS中buff长度不一定是字符数量+1,数组里面可以包含未使用的字节,而这些字节数量由SDS的free属性记录。

通过未使用空间,SDS实现了空间预分配和惰性空间释放两种优化策略。

空间预分配:

当对一个SDS进行修改并需要扩展SDS的空间时,程序不仅会分配修改所需要的空间,还会为SDS额外分配未使用的空间。(SDS小于1M会额外分配等于SDS的空间,大于等于1M则额外分配1M)

通过空间预分配策略,Redis可以减少连续执行字符串增长操作所需的内存从新分配次数。(如果要增长的长度小于未使用的空间就不会重新分配内存)

惰性空间释放:

惰性空间释放用于优化SDS的字符串缩短操作,当SDS需要缩短保存的字符串时,程序并不立即使用内存分配来回收缩短后多出来的字节,而是使用free属性将这些字节数量记录起来,并等待将来使用。

二进制安全

C字符串中的字符必须符合某种编码格式,并且除了字符串的末尾处,不允许有空字符串,否则会被认为是字符串结尾,这些限制使C字符串只能保存文本数据,不能保存二进制数据

SDS会以处理二进制的方式来处理SDS存放在buf数组中的数据,程序不会对数据做任何限制,数据写入时是什么样,读取时就是什么样。(SDS的buf属性不是保存字符,而是保存的一系列二进制数据

兼容部分C字符串函数

虽然SDS的API都是二进制安全的,但他们一样遵守C字符串以空字符串结尾的惯例,为了SDS可以重用一部分string.h库定义的函数,从而避免代码重复。

image-20221114233407460


参考

《Redis设计与实现》

redis数据结构—动态字符串(SDS)

黑马程序员

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

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

相关文章

【PyTorch】Transforms基本使用

文章目录二、Transforms基本使用1、Transforms的结构及用法1.1 如何使用1.2 TensorBoard查看2、常用的Transforms2.1 ToTensor2.2 Normalize2.3 Resize2.4 Compose2.5 RandomCrop二、Transforms基本使用 Transforms主要是对特定格式的图片进行一些变化。 1、Transforms的结构及…

展锐UIS8310 CAT4物联网模块简介

1.简介 UIS8310是一个高度集成的应用处理器,支持TDD-LTE、FDD-LTE和WCDMA、GSM/GPRS/EDGE制式,并且支持LPDDR2。它的AP处理器是单核ARM CortexTM A7 1GHz,旨在为物联网提供经济高效、低功耗和高性能的解决方案。 UIS8310经过特别优化的架构可…

Servlet之RequestReponse 学习笔记

1 Request 1.1 Request继承关系 ServletRequest Java提供的请求对象根接口 HttpServletRequest Java提供的对Http协议封装的请求对象接口 RequestFacade Tomcat定义的实现类WebServlet("/demo2") public class Servlet2Demo extends HttpServlet {Overridep…

Vue 路由router的介绍以及使用方法

路由:简单来说类似于路由器,中转站。 1.理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。 2.前端路由:key是路径&…

同源策略、跨域与JSONP

跨域与JSONP一、了解同源策略和跨域1.1 同源策略1.2 跨域二、JSONP2.1 什么是JSONP2.2 JSONP的实现原理2.3 自己实现一个简单的JSONP2.4 JSONP的缺点2.5 jQuery中的JSONP2.6 自定义参数及回调函数名称2.7 jQuery中JSONP的实现过程三、案例-淘宝搜索一、了解同源策略和跨域 1.1…

软考考完了,如何评职称?

很多考生以为软考初级、中级、高级资格考试通过了就是相应的职称了,然而并不是这样的,通过了软考考试只是相当于有了评职称的资格,并不是有了相应职称。 有了软考证书是可以申请评职称的,因为有了软考证书就有了评职称的资格哦&a…

【前端】flet:一款(即将)支持多语言开发的UI库

文章目录介绍开发生态支持语言运行体验组件API热更新开发计划 Roadmap2022 7月-8月安全手机端桌面端Controls(控件)核心功能用户指引(User education)2022 9月到12月手机端控件(Controls)编程语言支持核心功能介绍 Flet enables …

【云原生 | Kubernetes 系列】--Gitops持续交付 CD Push Pipeline实现

1. Tekton Trigger基础 Tekton Triggers简介 - 监控特定的事件,并在满足条件时自动触发Tekton PipelineTekton Triggers 为用户提供了一种声明式API 它允许用户按需定义监视的事件,并将其与特定的Pipeline连接,从而实例化出PipelineRun还允许将事件中的某些属性值信息注入到P…

使用springboot每日推送早安问候语到用户微信

本文主要实现给不同的用户推动不同的问候模板 准备工作 申请微信公众平台的测试号 申请微信测试公众号 创建成功后,可以看到appid和appsecret,这个后面认证时需要 申请模板 可自行修改 今天是:{{now.DATA}} 不管那一天,每一天…

【科学文献计量】科学文献知识网络分析基础

科学文献知识网络分析基础 1 知识网络分析基础2 知识网络图构成2.1 简单网络图绘制2.2 完整网络图绘制3 知识网络图中的术语3.1 术语和统计量概念3.2 获取术语信息实例3.3 最大子群和网络图孤立点的识别3.4 网络图节点度信息的统计1 知识网络分析基础 从分析的角度来看,社会网…

安保公司的商业计划书

安保公司的商业计划书年轻人,来做保安吧,少走二十年弯路安保公司的商业计划书安保品牌公司的商业模式真正的路反潮流,不上大学去创业,其实反而是领先的。 工厂肯定不能创业的,因为打工的技能和创业的技能不同。 如果…

【附源码】计算机毕业设计JAVA茶园文化交流平台演示录像2020

【附源码】计算机毕业设计JAVA茶园文化交流平台演示录像2020 目运行 环境项配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术&#xff1…

SpringBoot框架Mockito的使用

SpringBoot框架Mockito的使用 一、简介 mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。 在具体的测试过程中,我们经常会碰到需要模拟数据或者接口的情况,因为环…

线性模型(穷举法实现)

参考视频:2.线性模型_哔哩哔哩_bilibili 参考视频中实现ywxywxywx 的代码,在加上偏置b后实现 ywxbywxbywxb 的线性模型 假设我们有这样一个线性模型:ywxbywxbywxb X和Y对应的数据如下 XY1.05.02.08.03.011.04.0? 预测值&#x…

开源知识付费APP代码分析

如今,传统的学校已经不能满足大众多元化的需求,各种教育培训机构落地生根。随着时间的推移,互联网与传统教育的结合也开拓了一种新的教育方式,这就是广为人知的知识付费。在线教育的突然崛起多半是因为疫情的“催化”,…

OceanBase 4.0 - 从分布式到单机,从单机到分布式

近些年国产化数据库如雨后春笋般冒出并遍地开花。据某技术平台不完全统计,国产化数据库(见图 )已达 200余个,对于这些数据库的名字,即使作为多年数据库从业者的我,也有很多是第一次听说。在这竞争激烈的数据…

FFplay文档解读-49-多媒体过滤器三

32.14 sendcmd, asendcmd 将命令发送到filtergraph中的过滤器。 这些过滤器读取要发送到filtergraph中其他过滤器的命令。 必须在两个视频滤镜之间插入sendcmd,必须在两个音频滤镜之间插入asendcmd,但除此之外,它们的行为方式相同。 可以…

[附源码]java毕业设计基于的高校学生考勤管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

vue中tinymce的使用

1.下载 npm i tinymce5.10.3 tinymce/tinymce-vue3.2.8 -S2.在node_modules中找到 (我这里是vue2,vue3不是写在public下,具体的可以搜搜 看看) 3.在public中新建 tinymce 文件夹 把三个文件复制进去 4.在components文件夹中新建…

Unity架构之详解域重新加载和场景重新加载

一、unity进入运行模式包括以下主要阶段 备份当前场景:这仅在场景被修改后发生。这样当退出运行模式时,Unity 将场景恢复为运行模式开始前的状态。Domain Reload:通过重新加载脚本域来重置脚本状态。Scene Reload:通过重新加载场…