1.动态字符串
用的是c语言,自己写的简单动态字符串sds,分为
struct sdshdr{
//记录buf数组中已使用字节的数量
int len;
//记录 buf 数组中未使用字节的数量
int free;
//字节数组,用于保存字符串
char buf[];
}
为什么设计呢
- 1.常熟复杂度获取字符串的长度,c语言是要遍历一遍计数的,空间换时间,直接读len就行了
- 2.防止缓存溢出,字符串strcat时,可能由于分配的空间不够导致 内存溢出,现在设置了sds,修改时判断len会不会溢出,溢出就扩展,不会溢出。
- 3.减少分配内存的次数,c语言每次的长度变化都会导致内存分配,但是sds有len,free,有两个策略:
- 空间预分配:拓展时,由于有预留的空间,减少了空间间的变动,
- 惰性空间释放 :在缩小长度时,不会立即的会及回收
- 4.二进制安全,因为C字符串以空字符作为字符串结束的标识,而对于一些二进制文件(如图片等),内容可能包括空字符串,因此C字符串无法正确存取;而所有 SDS 的API 都是以处理二进制的方式来处理 buf 里面的元素,并且 SDS 不是以空字符串来判断是否结束,而是以 len 属性表示的长度来判断字符串是否结束。
2.链表list
C 语言内部是没有内置这种数据结构的实现,所以Redis自己构建了链表的实现。
Redis链表特性:
①、双端:链表具有前置节点和后置节点的引用,获取这两个节点时间复杂度都为O(1)。
②、无环:表头节点的 prev 指针和表尾节点的 next 指针都指向 NULL,对链表的访问都是以 NULL 结束。
③、带链表长度计数器:通过 len 属性获取链表长度的时间复杂度为 O(1)。
④、多态:链表节点使用 void* 指针来保存节点值,可以保存各种不同类型的值。
3.Map
字典又称为符号表或者关联数组、或映射(map),是一种用于保存键值对的抽象数据结构。字典中的每一个键 key 都是唯一的,通过 key 可以对值来进行查找或修改。C 语言中没有内置这种数据结构的实现,所以字典依然是 Redis自己构建的。
4.zset
zset是Redis提供的一个非常特别的数据结构,常用作排行榜,微信点赞等功能,以用户id为value,关注时间或者分数作为score进行排序。与其他数据结构相似,zset也有两种不同的实现,分别是zipList和skipList。z具体使用哪种结构进行存储,规则如下:
- zipList:满足以下两个条件
- [score,value]键值对数量少于128个;
- 每个元素的长度小于64字节;
- skipList:不满足以上两个条件时使用跳表、组合了hash和skipList
- hash用来存储value到score的映射,这样就可以在O(1)时间内找到value对应的分数;
- skipList按照从小到大的顺序存储分数
- skipList每个元素的值都是[socre,value]对