2.2 Redis中SDS(简单动态字符串) 与C字符串的区别
创始人
2024-03-04 02:21:49
0

引言:

根据传统,C语言使用长度N+1的字符数组来表示长度为N的字符串,并且字符数组的最后一个元素总是空字符’\0’。
例如,图2-3 就展示了一个值为"Redis"的C字符串。
C语言使用这种简单的字符串表示方式,并不能满足Redis对字符串在安全性、效率以及功能方面的要求,接下来的内容将详细对比C字符串和SDS之间的区别,并说明SDS比C字符串更适合用于Redis的原因。

在这里插入图片描述

2.2.1 Redis 可以,以常数复杂度 获取 字符串的长度

在传统的C字符串中,其本身,并不记录字符串的长度信息,如果想获取该字符串的长度,那么就需要对字符串进行遍历,对遇到的每个字符进行计数,知道遇到 0元素或者 字符’\0’,这个操作的复杂度为O(N)。

和C字符串不同的是,Redis 中 SDS 在len 属性中记录了SDS本身的长度,所以获取一个SDS长度的复杂度仅为O(1)。

设置和更新SDS长度的工作,是由SDS的API 在执行时自动完成的,所以使用SDS无需进行任何手动修改长度工作。

通过使用SDS这种字符串结构,Redis 把 获取一个字符串的效率,从O(N) 时间复杂度降低到O(1),即使我们对一个非常长的字符串键,进行反复的执行STRLEN 命令,也不会对系统性能造成任何影响,因为STRLEN命令的时间复杂度仅为O(1)。

2.2.2 杜绝了缓冲区溢出

传统C字符串,除了获取字符串长度以外,还会造成缓冲区溢出的问题。

例如如果 对一个已经分配好内存空间的C语言字符串 char *dest,如果这个时候要对该字符串进行追加的话,那么如果在没有追加之前没有为dest额外分配额外的空间(这往往是粗心的程序猿所做的,但是C语言中确实是这样的。每一次对字符串进行新增或者修改,都要进行一次内存分配),一旦没有提前进行分配,那么就会产生缓冲溢出。

举个例子,加入程序中,有2个在内存中紧邻的C字符串s1和s2,其中s1保存了"redis",
s2保存了 “mysql5.7”,如图2-7所示。

在这里插入图片描述

如果一个程序员,决定通过执行:

strcat(s1," Java");

那么s1的内容将会被修改为"redis JAVA"(10个字符),但是粗心的他却忘了在执行此函数之前,为s1分配足够的内存空间,那么在strcat函数执行之后,s1的数据将会溢出到s2所在的空间中,会导致s2保存的内容以外地被修改,如果2-8所示。

在这里插入图片描述

与C字符串不同的是,SDS 的空间分配策略完全杜绝了发生缓冲区溢出的可能性:当SDS的API需要对SDS进行修改时,API 会先检查SDS 的空间是否满足修改所需的要求,如果不满足的话,API 会自动将SDS 的空间扩展至执行修改所需的大小,然后才执行实际的修改操作问题,所以使用SDS既然不需要手动修改SDS的空间大小,也不会出现前面所说的缓冲区溢出问题。

举个例子,SDS的API里面也有一个用于执行拼接操作的sdscat函数,可以将一个C字符串拼接到给定SDS所保存的字符串的后面,但是在执行拼接操作之前,sdscat会先检查给定SDS的空间是否足够,如果不够的话,sdscat就会先扩展SDS的空间,然后才执行拼接操作。

例如,如果我们执行:

sdscat(s," Cluster");

在这里插入图片描述

其中SDS值s 如图2-9 所示,那么sdscat将在执行拼接操作之前检查s的长度是否足够,在发现s目前的空间不足以拼接" Cluster"之后,sdscat就会扩展s的空间,然后才执行拼接
" Cluster"的操作,拼接操作完成之后的SDS如图2-10所示。
在这里插入图片描述
注意:图2-10所示的SDS,sdscat不仅对这个SDS进行了拼接操作,它还为SDS分配了13字节的未使用空间,并且拼接之后的字符串也正好是13字节长,这种现象既不是bug也不是巧合,它和SDS的空间分配策略有关。

链接: 2.2.3 Redis中的SDS减少修改字符串时带来的内存重分配次数

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...