说在前面
感谢牛客举办这样一个有意思的活动,也督促我有更多看书的动力哈哈哈。
也要感谢一下那位给我点赞的同学,让我以总计两票的微弱优势获得了这次的读书活动~
关于这本书
《redis的设计与实现》的作者在前言当中说,这本书可以帮助我们更好的了解redis,避开那些可能引起性能问题的陷阱。
引言给我们提示
1.如果只是对redis原理感兴趣但并不想研究源码,本书够用了
2.本书分为 数据结构、单机实现、多机实现和独立功能实现
3.自底向上的章节流程
数据结构
字符串
没有使用C语言自带的字符串表示,而是重新构建了简单动态字符串(simple dynamic string, SDS)的类型。
struct sdshdr{ int len;//已使用字节数量 int free;//未使用字节数量 char buf[];//字节数组,保存字符串 }
sds相比于c语言的字符串,更加安全且效率更高,具体体现在以下几点
获取字符串长度
因为有len属性,所以获取的时间复杂度从O(N)降到O(1)
杜绝缓冲溢出
c语言字符串长度固定,如果字符串拼接前忘记分配空间会造成溢出,sds在拼接前会检测。
内存重分配次数
空间预分配:free和len共同构建buf[]的长度,同时扩张时free的长度也会更新。
惰性空间释放:使用trim方法删除某些字符时,空间并不会真正回收。
链表
和数据结构课程中所学的链表一样,在发布与订阅、慢查询、监视器等功能中都会用到链表。
typedef struct listNode{ //前节点 struct listNode *prev; //后节点 struct listNode *next; //节点值 void *value; }listNode; typedef struct list{ listNode *head; listNode *tail; unsigned long len; void *(*dup)(void *ptr);//节点复制函数 void *(*free)(void *ptr);//节点值释放函数 void (*match)(void *ptr, void *key);//节点值比较函数 }
字典
字典是一种键值对的数据结构。redis的数据库底层就是字典。
struct dictht{ //哈希表 } struct dictEntry{ //用于保存多个键值对 } struct dict{ //dict头 } struct dictType{ //特定类型操作 }
哈希算法
插入数据时,根据哈希函数插入指定索引位置。当存在hash冲突时,使用链地址法,也就是在桶位置构建一个链表。rehash的保证负载因子维持在合理范围,使用dt[0]和dt[1]进行相互拷贝实现。
跳跃表
跳表是一种特殊的链表,对于每个Node可以指向下一个或其他多个节点。支持平均O(logN)的查找复杂度。跳跃表是有序集合的底层实现之一。
//跳表节点 typedef struct zskiplistNode{ struct zskiplistNode *backward; double score; robj *obj;//成员对象 struct zskiplistLevel{//层 struct zskiplistNode *forward; unsigned int span;//跨度 }level[]; } //跳表信息 typedef struct zskiplist{ struct sikplistNode *header, *tail;//头尾 unsigned long length;//节点数 int level;//层数 }