在Redis中使用SDS(简单动态字符串)来代替c风格字符串
struct SDS{
int len,free;
char buf[];
}
列表,慢查询,发布订阅,监视器等功能中都用到了链表
typedef struct list{
listNode *head,*tail;//头,尾
unsigned long len;//长度
void *(*dup)(void *ptr);//复制函数
void (*free)(void *ptr);//释放函数
int (*match)(void *ptr,void *key);//匹配判断函数
}list;
listNode 的底层是双向无环链表
Redis中数据库,哈希表等功能的底层都用到了字典
typedef struct dictht{
dictEntry **table;//值数组
unsigned long size; // 哈希表大小
unsigned long sizemask;//掩码
unsigned long used;//已使用数量
}
typedef struct dictEntry{
void *key;//键
union{//值
void *val;
uint64_t u64;
int64_t s64;
}v;
struct dictEntry *next;//下个哈希表节点
}dictEntry;
typedef struct dict{
dictType* type;
void *privatedata;
dictht ht[2];//维护两个,为了完成负载因子均衡
int trehashidx;//不在rehash时,值为-1
}
在Redis中会根据不同的键类型,选择不同的处理函数(type->hashFunction() , 如计算,处理,销毁函数),Redis使用MH2算法.
使用链地址法,在链的头部插入新节点,保证插入的O1复杂度
负载因子 = 保存节点数量 / size
在进行bgsave,bgrewrite时 触发rehash的负载因子值为5 , 不进行时为 1 (因为要避免写时复制时多余的内存写入)
利用ht[1]来完成扩展(第一个大于used*2的2的幂)或者收缩(第一个大于used的2的幂) 空间大小
在大小改变后,将ht[0]中的元素rehash到ht[1]中,完成后交换两者地址,完成rehash
渐进式rehash:每次访问ht[0]时rehash一个rehashidx上的数据,当rehashidx等于达到上限时说明rehash完毕,将rehashidx置为-1(通过渐进rehash避免服务长时间停止响应)
rehash 读操作 会先在ht[0],后在ht[1]上读 , 写操作全部写在ht[1]
跳跃表支持平均logN,最坏o(N)的不稳定查找复杂度,可以通过顺序性批量操作节点,是有序列表的底层实现之一,还是集群内部的数据结构.
typedef struct zskiplistNode{
struct zskiplistNode *backward; // 后退指针
double score;//分数
robj *obj;//实际对象
struct zskiplistLevel{ //层
struct zskiplistLevel *forward; //每层上的前进指针
unsigned int span; // 跨度
}level[];//层的大小是1~32的随机数
}zskiplistNode;