redis数据结构之String

redis中的字符串类型,分为两种,一种是C语言本身的字符串,一种是自己构建的一个数据类型(simple dynamic string)SDS。C字符串主要用于字符串字面量用于一些无须对字符串修改的地方,比如redis中日志打印;在reids中可以被修改的字符串就用SDS来代替C字符串;redis中使字符串类型的键值对都是SDS作为底层数据实现的,当然键值在redis中都是字符串类型的哦,下面我们见识一下SDS的数据结构图解,水平有限,见谅!


用java代码表示的数据结构
/**
 * Redis 中字符串结构
 * @author zhenwei
 *	simple dynamic String
 */
public class SDS {
	//当前字符串长度
	int len;
	//空闲长度
	int free;
	//字符串存储数组,长度 = len+free
	char[] buffer;
}


这个数据结构是对于C字符串做了一些冗余设计,有点类似于空间换时间的概念,SDS的使用场景:所有的key键,以及字符串类型的值数据;

SDS相对C字符串不一样的地方
1.字符串长度,SDS直接获取len属性的复杂度为O(1),C字符串要遍历整个buffer,复杂度为O(n)
2.杜绝缓存区溢出
在C执行strcat(char *dest,const char *src) 方法时,会假设dest已经得到足够大的空间(由开发者分配),可以容下src字符串,一旦假设不成立就会出现缓存溢出的危险,
SDS则杜绝了此问题,在字符串拼接时,会根据free判断当前空间有多少剩余,是否能满足拼接的字符串,然后判断是否进行扩容(增大free空间),所以这部分工作由SDS完成,不需要开发者控制
3.减少字符串修改时内存重新分配的次数
刚才提到当C字符串拼接时,需要开发者提前分配空间来满足字符串的增长;
如果需要缩短字符串,需要释放一不需要的空间;
redis在使用过程中会出现频繁的数据变更,如果想C字符串一样频繁的进行内存分配,而内存分配在系统中是一个比较耗时的操作,应该尽量避免;
redis中的SDS已经提前做了空间的预分配,所有在字符串增长时会降低重新分配的次数,如果新增的字符串空间<free,则不需要做新的空间分配(起码不需要实时的做这个事情,会延迟一下下),否则就分配一部分空间来满足需要
4.惰性释放
上面将字符串拼接时的内存分配,在字符串缩减,比如被截取等情况下,需要进行相应的空间释放,但是SDS中,不清楚后续这个字符串会做什么的数据变更,就将多余的空间作为Free属性保留下来,做未来的扩展,如果真的free很大的时候,也可以调用redis 相应的api 进行手动释放
5.二进制数据安全
C字符串中的字符必须是满足某种编码的,并且除了末尾是一个空字符外,字符串中不能出现空字符串,否则最先被判断为空的就误认为是字符串结尾,所以C字符串只能保存文本,不能保存图片 视频等文件格式的二进制数据;
而redis中并不是以字符数组进行的保存,而是以字节数组的方式对字符串进行保存,,这样就可以兼容各个数据类型,不会出现奇奇怪怪的问题
6.兼容部分C字符串的功能


参考书籍:《Redis设计用于实现》黄健宏

猜你喜欢

转载自ludizhang.iteye.com/blog/2308709
今日推荐