一 前言
本篇文章是初步认识redis的字符串数据结构SDS(Simple Dynamic String), 其意指简单的动态字符串,字面上的含义就是smiple 代指简单,操作简单,使用者能够快点理解上手,无需关心redis内部实现;Dynamic 指动态扩展,表是能够自动的对内存空间进行动态分配;String 表示字符串,不难理解;
公众号:知识追寻者
知识追寻者(Inheriting the spirit of open source, Spreading technology knowledge;)
二 SDS结构
2.1 redis SDS数据结构
redis3.2之前数据结构如下;
struct sdshdr {
unsigned int len;
unsigned int free;
char buf[];
};
- len 表示 buf(缓冲区)中已经使用的空间长度;
- free 表示 buf中未使用的长度;
- buf[] 表示缓冲区数组,存储字符;
2.12 redis 缓冲区结构
更加的形象的一个存储图像如下 buf 中的实际大小为 11(len + free + 1),其中已经使用空间 len = 5 , 未使用空间 free=5; 保留位空字符 占一位;当我们在redis储存进一个字符串zxzxz
的时候 就已经给我们分配好了内存空间,以及后面能用使用的内存空间;如果是c 语言那么要得到一个 zxzxz 字符长度就需要遍历整个字符数组 遇到 (C语言以 区分内存空间中的字符串)后结束,才计算出一个字符串的长度,然而redis只需要一个sdslen
(非c语言读者不必纠结此类API) 就可以计算得出字符串长度; 从算法角度来看 redis 的一次获取字符串长度 为 O(1), c 语言 为 O(N), 所以redis 快很多;
2.2 redis 空间分配策略
其次通过上图可以发现 储存一个字符串 zxzxz
, 其所占长度为5 , 为使用空间为5, 占1 ;原因是 redis字符串 储存大小小于1MB 的时候 , 存储任意的字符串, 其 free大小永远与 自身的大小相同;当字符串 大小大于1MB时,其就分配free大小固定为1MB, 此称为空间预分配策略
; 如果是c语言 则需要 计算当前字符串在buf中的长度,再计算即将追加的字符串长度,然后分配空间大小;故redis 的速度是相当快,相比于c 操作内存空间;
c 语言 在操作内存空间的时候要不断的计算大小,在追加字符串的时候分配空间大小,如果未进行分配,那么追加的字符串有可能覆盖已经 已经储存到 内存空间的字符串; 比如 内存空间 储存 zzz kkk
; 储存 zzz 的时候所占用3 个位,加一个未分配空间1位,如果向zzz字符串进行追加一个ggg, 那么在未进行计算分配空间的情况下 原有的数据会变成 zzzggg k
, 很直观的发现 内存溢出, 第一个字符串就覆盖至第二个字符串的部分内容;
所以 redis 的操作内容空间是杜绝内存溢出,并且能够储存图片,视频等二进制数据,如果是c语言操作储存,二进制文件中一个 就可能导致内存泄漏,缓冲区溢出等,故c语言一般只操作文本文件;
三 相关链接
如果想要深入redis之SDS源码,可以参考如下链接;
https://blog.csdn.net/yangbodong22011/article/details/78419966
https://juejin.im/post/5cdbafedf265da037c7d090f