3 内存淘汰
3.1 内存淘汰策略
配置项
noeviction(Redis默认策略)
不删除任何东西,只需在写操作中返回错误。即不会继续服务写请求 (但DEL 请求可继续服务),读请求可继续进行。
这保证不会丢数据,但会让线上业务无法持续进行。
- config.c
createEnumConfig("maxmemory-policy", NULL, MODIFIABLE_CONFIG, maxmemory_policy_enum, server.maxmemory_policy, MAXMEMORY_NO_EVICTION, NULL, NULL),
allkeys-random
当内存不足以容纳新写入的数据时,在键空间中,随机移除某key。
但是凭啥随机呢,至少也是把最近最少使用的key删除。
allkeys-lru
当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key,没有设置过期时间的 key 也会被淘汰。
allkeys-lfu(Least Frequently Used)
LRU的关键是看页面最后一次被使用到发生调度的时间长短,而LFU关键是看一定时间段内页面被使用的频率。
volatile-lru(最常用)
尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。
没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
区别于 allkey-lru,这个策略要淘汰的只是过期的 key 集。
volatile-lfu
volatile-random
淘汰的 key 是过期 key 集合中随机的 key。
volatile-ttl
淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl
越小越优先被淘汰。
volatile-xxx 策略只会针对带TTL的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。
- 若只拿 Redis 做缓存,推荐 allkeys-xxx,客户端写缓存时不必携带TTL
- 若你还想同时使用 Redis 持久化,推荐 volatile-xxx,这样可以保留没有TTL的 key,它们是永久 key 不会被 LRU 淘汰。
数据淘汰策略
1.volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
2.volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
3.volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
4.allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰;
5.allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰;
6.no-enviction(驱逐):禁止驱逐数据。
应用场景
可以充分的利用Redis的特性,大大提高效率。
在主页中显示最新的项目列表
Redis使用的是常驻内存的缓存,速度非常快
LPUSH用来插入一个内容ID,作为关键字存储在列表头部
LTRIM用来限制列表中的项目数最多为5000
如果用户需要的检索的数据量超越这个缓存容量,这时才需要把请求发送到数据库
删除和过滤
如果一篇文章被删除,可以使用LREM从缓存中彻底清除掉
排行榜及相关问题
排行榜(leader board)按照得分进行排序
ZADD命令可以直接实现这个功能
ZREVRANGE命令可以用来按照得分来获取前100名的用户
ZRANK可以用来获取用户排名,非常直接而且操作容易
按照用户投票和时间排序
排行榜,得分会随着时间变化。
LPUSH和LTRIM命令结合运用,把文章添加到一个列表中
一项后台任务用来获取列表,并重新计算列表的排序,ZADD命令用来按照新的顺序填充生成列表。列表可以实现非常快速的检索,即使是负载很重的站点。
过期处理
使用Unix时间作为关键字,用来保持列表能够按时间排序。对current_time和time_to_live进行检索,完成查找过期项目的艰巨任务。另一项后台任务使用ZRANGE…WITHSCORES进行查询,删除过期的条目。
计数
进行各种数据统计的用途是非常广泛的,比如想知道什么时候封锁一个IP地址
INCRBY命令让这些变得很容易,通过原子递增保持计数
GETSET用来重置计数器
过期属性用来确认一个关键字什么时候应该删除
特定时间内的特定项目
这是特定访问者的问题,可以通过给每次页面浏览使用SADD命令来解决
SADD不会将已经存在的成员添加到一个集合。
Pub/Sub
在更新中保持用户对数据的映射是系统中的一个普遍任务。Redis的pub/sub功能使用了SUBSCRIBE、UNSUBSCRIBE和PUBLISH命令,让这个变得更加容易。
队列
在当前的编程中队列随处可见。除了push和pop类型的命令之外,Redis还有阻塞队列的命令,能够让一个程序在执行时被另一个程序添加到队列。