理解Redis SDS(简单动态字符串)

2024-01-19 22:38

本文主要是介绍理解Redis SDS(简单动态字符串),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简述

Redis中并没有直接使用C语言的字符串表示(在内存中以“\0”作为字符串的结尾),而是自己新建了一个字符串的结构,该结构就是SDS(Simple Dynamic String,简单动态字符串)。

SDS在Redis中的使用

Redis中设计可变字符串都是用的SDS结构,如Redis底层为键值对结构,所有的键都是字符串类型的,就是SDS结构的对象。当然Redis打印日志时,字符串不需要变化,则是使用的C语言的字符串。

SDS结构

struct sdshdr{//buf数组中未使用的字节数量int free;//buf数组中已经使用的字节数量,不包括“\0”int len;//字节数组,用来保存字符串char buf[];
}

假如用SDS来存储字符串“Redis”,那么其结构如下:
在这里插入图片描述
len为5,实际buf数组的长度为6,有一个字节用来存储了“\0”。SDS不需要“\0”来判断字符串是否到结尾,那么为什么还要在buf数组最后用“\0”作为结尾呢?其实主要是Redis还要用到C语言中对字符串的处理函数,以“\0”作为结尾,Redis就可以使用这些函数而不用自己去实现。

SDS与C语言字符串的区别

获取字符串长度时时间复杂度O(1)

在C语言的字符串中,以"\0"作为结尾,在需要求字符串长度的时候,需要遍历数组到“\0”处,时间复杂度为O(N)。而在SDS的结构中,可以直接从len中读取长度,时间复杂度为O(1)。

缓冲区溢出问题

传统C语言字符串在执行诸如字符串相加的函数时,是假设使用者已经进行了内存的分配,有足够的内存可以供操作,假如使用者在执行函数之前没有进行内存处理,就可能出现缓冲区溢出的情况。
如:现在有两个字符串S1,S2,结构如下:
在这里插入图片描述
此时,如果直接给S1加上“ Cluster”,就会发生溢出,结构变为:
在这里插入图片描述
可以看到S2的字符串变为“Cluster”。而SDS结构中free字段,明确规定了buf数组空闲字节的数量,执行操作之前可以计算free是否足够放下新的字符串,如果不够就进行内存分配,这样就可以防止缓冲区溢出。

减少内存分配的次数

传统的C语言字符串,在进行字符串相加操作之前,每一次操作都需要进行内存分配,防止缓冲区溢出。而SDS,如果free空闲字节数量足够,完全可以直接进行操作,不需要进行空间申请。那么SDS是怎么判断应该预留多少free的呢?

空间预分配

假如free中空闲的字节数不足以放下新的字符串,那么SDS也会申请进行内存分配,保证buf足够的空间放下新的字符串。当存储的字符串大小小于1MB时,free会和len一样大,也就是假设新的字符串大小len为13,那么free也为13,buf数组的长度为13 + 13 + 1(\0占一位)。如果新的字符串超过1MB,那么free就为1MB。

惰性释放内存空间

buf存储的字符串进行缩减操作时,内存空间并不会立刻释放,释放出来的字节数目会加到free中。

二进制安全

传统的C语音字符串是无法保存媒体数据的,因为如果数据中有“\0”就会被判断为结尾。使用SDS就可以存储媒体数据。

注:"\0"是 ASCII 码为 0 的字符,对应的字符是(Null),C语言中用来判断字符串的结尾

这篇关于理解Redis SDS(简单动态字符串)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/623924

相关文章

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

GO语言实现串口简单通讯

《GO语言实现串口简单通讯》本文分享了使用Go语言进行串口通讯的实践过程,详细介绍了串口配置、数据发送与接收的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录背景串口通讯代码代码块分解解析完整代码运行结果背景最近再学习 go 语言,在某宝用5块钱买了个

MyBatis-Plus使用动态表名分表查询的实现

《MyBatis-Plus使用动态表名分表查询的实现》本文主要介绍了MyBatis-Plus使用动态表名分表查询,主要是动态修改表名的几种常见场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录1. 引入依赖2. myBATis-plus配置3. TenantContext 类:租户上下文

SpringBoot整合Apache Spark实现一个简单的数据分析功能

《SpringBoot整合ApacheSpark实现一个简单的数据分析功能》ApacheSpark是一个开源的大数据处理框架,它提供了丰富的功能和API,用于分布式数据处理、数据分析和机器学习等任务... 目录第一步、添加android依赖第二步、编写配置类第三步、编写控制类启动项目并测试总结ApacheS

Redis 命令详解与实战案例

《Redis命令详解与实战案例》本文详细介绍了Redis的基础知识、核心数据结构与命令、高级功能与命令、最佳实践与性能优化,以及实战应用场景,通过实战案例,展示了如何使用Redis构建高性能应用系统... 目录Redis 命令详解与实战案例一、Redis 基础介绍二、Redis 核心数据结构与命令1. 字符

SpringBoot18 redis的配置方法

《SpringBoot18redis的配置方法》本文介绍在SpringBoot项目中集成和使用Redis的方法,包括添加依赖、配置文件、自定义序列化方式、使用方式、实际使用示例、常见操作总结以及注意... 目录一、Spring Boot 中使用 Redis1. 添加依赖2. 配置文件3. Redis 配置类

Java中的随机数生成案例从范围字符串到动态区间应用

《Java中的随机数生成案例从范围字符串到动态区间应用》本文介绍了在Java中生成随机数的多种方法,并通过两个案例解析如何根据业务需求生成特定范围的随机数,本文通过两个实际案例详细介绍如何在java中... 目录Java中的随机数生成:从范围字符串到动态区间应用引言目录1. Java中的随机数生成基础基本随

C++简单日志系统实现代码示例

《C++简单日志系统实现代码示例》日志系统是成熟软件中的一个重要组成部分,其记录软件的使用和运行行为,方便事后进行故障分析、数据统计等,:本文主要介绍C++简单日志系统实现的相关资料,文中通过代码... 目录前言Util.hppLevel.hppLogMsg.hppFormat.hppSink.hppBuf

Redis中群集三种模式的实现

《Redis中群集三种模式的实现》Redis群集有三种模式,分别是主从同步/复制、哨兵模式、Cluster,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1. Redis三种模式概述2、Redis 主从复制2.1 主从复制的作用2.2 主从复制流程2