Redis 章节学习总结

来源:互联网 发布:淘宝网的结算方式 编辑:程序博客网 时间:2024/04/29 10:45

第一章节:简单动态字符串(SDS)
SDS结构定义:

struct sdshdr{
int len;//记录SDS保存的字符串长度
int free;//记录数组中未使用的字节数量
char buf[];//保存字符串
}

SDS与C字符串的区别

  1. 复杂度
    c字符串并不记录自身记录,获取长度时遍历整个字符串。复杂度为O(N),sds有len属性复杂度为O(1)

  2. 缓冲区溢出
    c字符串不记录字符串长度,进行strcat容易产生缓冲区溢出。而sds的空间分配策略杜绝了缓冲区的溢出。(对sds进行修改时,先进行空间检查,不满足时,API自动扩展空间大小,再执行修改操作)

  3. 内存重分配次数
    c字符串每次增长或缩短都会进行一次内存重分配。
    (内存重分配涉及复杂算法,是一个比较耗时的操作)
    sds采用空间预分配与惰性空间释放策略是先分配优化策略
    空间预分配:sds的api对sds修改时,不仅对sds分配必须的空间,还会分配额外的未使用空间
    未使用空间数量公式;
    1.sds的len属性小于1MB ,分配同len属性相同的未使用空间。
    2.sds的len属性大于1MB,程序分配1MB未使用空间。

    例:strcat(s,"cluster");//set s "redis"SDS长度修改为13字节,free分配13字节

    惰性空间释放
    释放用于优化SDS的字符串缩短操作。缩短字符串时,并不立即回收多出来的字节,而是使用free将字节数量记录起来,待后续使用。

  4. 字符编码
    C字符串只保存文本数据,SDS可以保存文本或者二进制数据。

第二章节:
整数集合是集合键的底层实现之一。集合包含整数值元素,数量不多,且不重复。
结构:

uint32_t encoding;//编码方式,数组存储真正类型以编码为准
uint32_t length;//集合包含元素数量
int8_t contents[];//存储元素,包含数组项,值按大小排列

升级规则:当新元素添加类型长于现保存类型,整数集合需要整体升级。升级步骤:根据新元素类型扩展整个数组空间,并为新元素分配空间。底层数组现有元素做新类型转换,并存储相应位置,同时维护元素有序性。

第三章节:
链表:提供高效节点重排能力,以及顺序访问节点方式,通过增删改查灵活调整链表长度(列表底层实现之一是链表),多个listNode可以通过prev next形成双向链表。
链表结构:
listNode{
listNode * prev;//前置节点
listNode * next;//后置节点
void * value;//节点值
}
链表特性:
双端:每个节点都有prev next 指针获取某个节点及后置节点复杂度位O(1)
无环:表头表尾都以NULL为终点
带表头及表尾指针,获取表头及表尾复杂度O(1)
带链表计数器,获取长度复杂度O(1)
多态:链表可以保存不同类型的值。

第四章节:
字典:一种用于保存键值对的抽象数据结构
哈希表,哈希表节点

哈希算法:根据键值对计算出哈希值和索引值,然后根据索引值,将包含键值对的哈希表节点放到哈希数组指定索引上。
解决哈希冲突:当多个键被分到同一索引上时,redis采用链地址法来解决冲突,每个哈希节点都有一个next指针,可以通过指针构成一个单项链表。
rehash(重新散列):为了将哈希表的负载因子维持在合理范围内,程序需要对哈希表大小进行相应扩展或收缩
渐进式rehash:字典同时保持两个h[0],h[1]哈希表,分多次渐进式的将一个哈希表的键值rehash到新哈希表上,期间查找先h[0],未找到h[1],新增操作只在h[1]。
哈希表扩展伸缩条件:
1.没有执行bgsave或 bgwriteaof,并且哈希表负载因子大于等于1
2.正在执行bgsave或 bgwriteaof,并且哈希表负载因子大于等于5
3.哈希表负载因子小于0.1时,程序开始执行收缩操作。