数据结构实现原理
全局Hash表
Redis键值对存储在全局Hash表中,查询效率极快,时间复杂度为O(1)
通过Rehash解决因Hash冲突导致的查询效率降低的问题
String
简单动态字符串
优点
是一个种“万金油”数据结构,什么类型都可以放
缺点
元数据(记录数据长度、空间使用)占用内存较多
底层数据结构
简单动态字符串
压缩列表
时间复杂度O(N)。目的是节省空间,只有数据量少的时候才会使用
跳表
时间复杂度O(logN)。在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位
缓存过期策略以及过期缓存删除
过期缓存删除
每 100 毫秒会删除一些过期 key
超过 25% 的 key 过期,则重复删除的过程,直到过期 key 的比例降至 25% 以下
淘汰策略
volatile-random
设置了过期时间的键值对随机被淘汰
volatile-lru
设置了过期时间的最近未访问的被淘汰
volatile-lfu
设置了过期时间的键值对访问次数少的被淘汰
allkeys-lru
所有键值对最近未访问的被淘汰
allkeys-lfu
所有键值对访问次数少的被淘汰
Redis中LRU算法
每个键值对中保存最近被访问的时间戳(RedisObject中保存)
第一次会随机选出 N 个数据,把它们作为一个候选集合,把 lru 字段值最小的数据从缓存中淘汰出去
第N次淘汰,筛选新的数据进入候选集合,并进行淘汰。能进入候选集合的数据的 lru 字段值必须小于候选集合中最小的 lru 值
Redis中LFU算法
LFU 缓存策略是在 LRU 策略基础上,为每个数据增加了一个计数器,来统计这个数据的访问次数。当使用 LFU 策略筛选淘汰数据时,首先会根据数据的访问次数进行筛选,把访问次数最低的数据淘汰出缓存。如果两个数据的访问次数相同,LFU 策略再比较这两个数据的访问时效性,把距离上一次访问时间更久的数据淘汰出缓存。Redis4.0版本新增淘汰策略
实现原理
RedisObject中保存最近访问时间戳和访问次数
ldt 值:lru 字段的前 16bit,表示数据的访问时间戳
counter 值:lru 字段的后 8bit,表示数据的访问次数,最大值255。通过设置参数,概率性累计访问次数,避免很宽达到255
相比LRU更加关注访问次数
使用策略建议
allkeys-lru 策略:业务数据中有明显的冷热数据区分
allkeys-random 策略:业务应用中的数据访问频率相差不大,没有明显的冷热数据区分
volatile-lru 策略:业务中有置顶的需求,比如置顶新闻、置顶视频,同时不给这些置顶数据设置过期时间。这样一来,这些需要置顶的数据一直不会被删除,而其他数据会在过期时根据 LRU 规则进行筛选。
allkeys-lfu策略:针对有扫描查询的场景