脚本宝典收集整理的这篇文章主要介绍了Redis设计实现-学习笔记,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
最近在准备面试,问到redis相关知识,只能说个皮毛,说的既不深入也不全面,所以抓紧突击一下,先学《redis设计与实现》。
选择看书的原因是:
书中全面深入,且能出书一定十分用心;
搜博客也找不到比书更全面的文章,且费时;
直接看源码一个是对C掌握不好,且易困,效率不高,所以跟着书同步学源码,是我认为现在最好的选择。
redis做了一个用作字符串的SDS,除了一些不需要修改的场景,都是用SDS
C字符串的底层实现总是一 个N+1个字符长的数组
sds.h:
struct sdshdr { // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 int free; // 数据空间 char buf[]; };
1 | C字符串 | SDS |
2 | 求长度,需要遍历O(n) | 直接取len就可以O(1) |
3 | 容易造成缓冲区溢出 | |
4 |
减少了内存重新分配次数 (速度要求严苛,避免分配内存耗时多) |
|
5 | 二进制安全 |
4:SDS有free,可以比C字符串多一些预留空间。空间优化策略主要有两种:
redis自己构建的链表:
/* * 双端链表节点 */ tyPEdef struct listNode { // 前置节点 struct listNode *prev; // 后置节点 struct listNode *next; // 节点的值 void *value; } listNode;
/* * 双端链表迭代器 */ typedef struct listITer { // 当前迭代到的节点 listNode *next; // 迭代的方向 int direction; } listIter;
/* * 双端链表结构 */ typedef struct list { // 表头节点 listNode *head; // 表尾节点 listNode *tail; // 节点值复制函数 void *(*dup)(void *ptr); // 节点值释放函数 void (*free)(void *ptr); // 节点值对比函数 int (*match)(void *ptr, void *key); // 链表所包含的节点数量 unsigned long len; } list;
也叫:符号表、关联数组、映射,用于保存键值对;
/* * 字典 */ typedef struct dict { // 类型特定函数 dictType *type; // 私有数据 void *PRivdata; // 哈希表 dictht ht[2]; // rehash 索引 // 当 rehash 不在进行时,值为 -1 int rehashidx; /* rehashing not in progress if rehashidx == -1 */ // 目前正在运行的安全迭代器的数量 int iterators; /* number of iterators currently running */ } dict;
理解:
哈希表使用链地址法来解决键冲突:
哈希表节点dictEntry的指针构成一个链,hash相同的就排在当前dictEntry的next
1.为ht[1]分配空间,与ht[0]比较,扩容则分配
// 新哈希表的大小至少是目前已使用节点数的两倍 // T = O(N) return dictExpand(d, d->ht[0].used*2);
收缩则分配大小等于ht[0]的?
/* * 缩小给定字典 * 让它的已用节点数和字典大小之间的比率接近 1:1 * 返回 DICT_ERR 表示字典已经在 rehash ,或者 dict_can_resize 为假。 * 成功创建体积更小的 ht[1] ,可以开始 resize 时,返回 DICT_OK。 */ int dictResize(dict *d) { int minimal; // 不能在关闭 rehash 或者正在 rehash 的时候调用 if (!dict_can_resize || dictIsRehashing(d)) return DICT_ERR; // 计算让比率接近 1:1 所需要的最少节点数量 minimal = d->ht[0].used; if (minimal < DICT_HT_INITIAL_SIZE) minimal = DICT_HT_INITIAL_SIZE; // 调整字典的大小 // T = O(N) return dictExpand(d, minimal); }
2.把ht[0]复制并重新hash计算到ht[1]上
3.把ht[0]释放,ht[1]设置为ht[0]。
哈希表会自动在表的大小的二次方之间进行调整。
在没有bgSave或bgRewriteAOF命令时,负载因子大于1;或者有bgSave或bgRewriteAOF命令时,负载因子大于5;时执行
负载因子= 已保存/哈希表大小
skipList
todo
1
1
1
1
1
1
1
1
1
1
1
以上是脚本宝典为你收集整理的Redis设计实现-学习笔记全部内容,希望文章能够帮你解决Redis设计实现-学习笔记所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。