注:主要内容整理来自redis中几种哈希函数的研究
哈希就是离散算法
将一个键值转换成我们需要的数组索引下标的方法
Redis算法 LRU
LRU(Least Recently Used)最近最少使用统计算法
当Redis使用的内存超出设置的可以最大使用内存后
Redis会通过LRU的配置来回收内存
Redis对象的lru是用1<<24 - 1长度的字节表示的
可以连续标识194天的数据
Redis这里的LRU算法是近似算法
不是完全精确地获取到最合理的答案
而是按照采样结果查找到一个比较近似的结果
这个结果可能不是最合理的
但肯定不是最坏的
Redis算法 引用计数
Redis的内存回收算法采用
引用计数算法
通过增减对象的引用计数来判断
是否需要回收对象的内存
- 优点- 代码逻辑清晰
- 不会有集中清理数据时造成的假死现象
 
- 缺点- 无法解决循环引用问题(无视弱指针吧)
- 增加/减少引用数时的函数要对称,不能漏掉(c里面没有构造析构函数)
 
Redis 源码分析-quicklist
Redis 源码分析-ziplist
ziplist本质上就是字符串数组
当存储元素数量<UINT16_MAX时,可以直接读取长度
当存储元素数量>=UINT16_MAX时,需要遍历整个ziplist才能获取长度
采用了不同的编码来对数字,字符串存储进行了压缩
- 结构
 <总字节数(4字节)><最后一个元素的偏移量(从头开始算)(4字节)><总元素个数(2字节)><数据(不定字节)>…<0xFF结尾标记(1字节)>
- 数据的结构- 头- 前一个数据的编码类型和长度- 当长度小于0xFE时,是一个字节
- 当长度大于等于0xFE时,是5个字节(第一个字节+4个字节的长度信息)
 
- 当前数据的编码类型和长度
 第一个字节的前两位- 字符串- 00??????
 数据头总共占用一个字节
 后六位表示字符串长度
- 01??????|????????
 数据头总共占用两个字节
 后14位表示字符串长度
- 10______|????????|????????|????????|????????
 数据头总共占用5个字节
 后4个字节表示字符串长度
 
- 00??????
- 数字- 11000000
 表示int16_t
 后面两个字节为具体数据
- 11010000
 表示int32_t
 后面4个字节为具体数据
- 11100000
 表示int64_t
 后面8个字节为具体数据
- 11110000
 表示int24_t
 后面3个字节为具体数据
- 11111110
 表示int8_t
 后面1个字节为具体数据
- 11110001-11111101
 直接表示0-12的值
 后面没有数据
 值直接就在当前字节中
 其中
 11110001 0
 11110010 1
 …
 11111101 12
 就是字节后4位的值直接转化为整数
 然后-1所得的值
 结尾不是1110是因为1110为int8_t
 结尾不是1111是因为1111为ziplist结尾标记
 
- 11000000
 
- 字符串
 
- 前一个数据的编码类型和长度
- 数据
 根据数据长度定义的连续字符串
 
- 头
相关文件
- ziplist.h
- ziplist.c
Redis 源码分析-skiplist
Redis 源码分析-intset
Redis 源码分析-哈希表
Redis 源码分析-压缩map
本质上就是char*字符串
通过指定的格式排列的数据结构
基本格式
| 1 | <zmlen> // 当zmlen小于254时,记录的是键值对的个数,当等于254时,表示需要遍历整个zipmap才能指导具体的长度 | 
| 1 | #define ZIPMAP_BIGLEN 254 // zm的长度上限,当数据长度超过254时,使用254标记,并将后4(根据unsigned int长度变化)为记录为数据长度 | 
相关文件
- zipmap.h
- zipmap.c