面试官问:Redis缓存淘汰策略有哪些?
我们知道:Redis是基于内存的,面试官问:
- 生产环境Redis内存如何分配?
- Redis键过期了如何删除?
- ......
图片
本小节不仅适用于工作,也是面试的高频问题。
文章导读
图片
Redis内存分析
一、Redis默认内存是多少?
在 64bit 系统下,默认不限制内存大小,不设置内存大小和maxmemory = 0表示不限制 Redis 内存使用
二、如何查看Redis最大内存是多少?
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "0"
# maxmemory
三、如何查看Redis内存使用情况?
127.0.0.1:6379> info memory
四、如何配置和修改?
127.0.0.1:6379> config set maxmemory 104857600
OK
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "104857600"
图片
五、生产环境如何配置?
建议:一般取物理内存的3/4
Redis过期键删除?
我们知道,redis一般会设置过期时间。那么这些键过期了是立刻从内存中删除吗?
通常,键删除会有不同的策略
一、立刻删除
立即删除能保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是删除操作会占用cpu的时间,造成CPU额外的压力。
redis.conf 中,通过调整过期键的检测频率
# The range is between 1 and 500, however a value over 100 is usually not
1. a good idea. Most users should use the default of 10 and raise this up to
1. 100 only in environments where very low latency is required.
hz 10
但是这会产生大量的性能消耗,同时也会影响数据的读取操作。
二、惰性删除
数据到达过期时间,不做处理。等下次访问该数据时,
- 如果未过期,返回数据 ;
- 发现已过期,删除,返回不存在。
惰性删除策略的缺点是,它对内存是最不友好的。如果一个键已经过期,而这个键又仍然保留在redis中,那么只要这个过期键不被删除,它所占用的内存就不会释放。
#开启憜性淘汰
lazyfree-lazy-evictinotallow=yes
三、定期删除
这种方案有效规避上述两种极端情况, 定期删除策略的难点是确定删除操作执行的时长和频率:
- 如果删除操作执行得太频繁或者执行的时间太长,定期删除策略就会退化成立即删除策略。
- 如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除束略一样,出现浪费内存的情况。
- 因此,如果采用定期删除策略的话,服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。
Redis内存淘汰策略
基于上述的了解,假如:
1 定期删除时,从来没有被抽查到
2 惰性删除时,也从来没有被点中使用过
上述两个步骤,依然会有大量过期的key堆积在内存中,导致redis内存空间紧张或者很快耗尽。
因此,有没有一个更好的兜底方案......?这就是要讲的淘汰策略
一、LRU和LFU区别?
LRU(Least Recently Used,最近最少使用页面置换算法)
假设我们有一个容量为3的LRU缓存,访问数据的顺序如下:
- 访问数据1,缓存中现在有:[1]
- 访问数据2,缓存中现在有:[1, 2]
- 访问数据3,缓存中现在有:[1, 2, 3]
- 再次访问数据1,缓存中现在有:[2, 3, 1](因为1被重新访问,它被移到了列表的末尾)
- 访问数据4,由于缓存已满,最不常用的数据2将被淘汰,缓存中现在有:[3, 1, 4]
原理:如果数据最近被访问过,那么在不久的将来它很可能再次被访问。因此,LRU会淘汰最长时间未被访问的数据。
适用场景:适用于最近被访问的数据在未来某个时间点很可能再次被访问。
LFU(Least Frequently Used,最近最不常用页面置换算法)
假设我们有一个容量为3的LFU缓存,访问数据的顺序如下:
- 访问数据1,计数器:{1: 1}
- 访问数据2,计数器:{1: 1, 2: 1}
- 访问数据1,计数器:{1: 2, 2: 1}
- 访问数据3,计数器:{1: 2, 2: 1, 3: 1}
- 访问数据1,计数器:{1: 3, 2: 1, 3: 1}
- 访问数据4,由于缓存已满,访问次数最少的数据2将被淘汰,计数器:{1: 3, 3: 1, 4: 1}
原理:LFU算法会跟踪每个页面在特定时间段内被访问的频率。当需要淘汰页面时,LFU算法会淘汰在该时间段内访问次数最少的页面。
适用场景:LFU算法适用于那些访问模式可能随时间变化的场景,或者访问频率能够较好地反映页面重要性的情况。
小结
- LRU关注数据的最近访问时间,淘汰最长时间未被访问的数据。
- LFU关注数据的访问频率,淘汰访问次数最少的数据。
二、Redis有哪些淘汰策略?
redis.config 配置文件中,
# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
1. allkeys-lru -> Evict any key using approximated LRU.
1. volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
1. allkeys-lfu -> Evict any key using approximated LFU.
1. volatile-random -> Remove a random key having an expire set.
1. allkeys-random -> Remove a random key, any key.
1. volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
1. noeviction -> Don't evict anything, just return an error on write operations.
解释下:
volatile-lru:使用近似的最近最少使用(LRU)算法淘汰键。但是,只有那些设置了过期时间的键(即“volatile”键)才会被考虑淘汰。
allkeys-lru:使用近似的LRU算法淘汰任何键,无论它们是否设置了过期时间。
volatile-lfu:使用近似的最少频率使用(LFU)算法淘汰键。同样,只有设置了过期时间的键会被考虑。
allkeys-lfu:使用近似的LFU算法淘汰任何键,不考虑它们是否设置了过期时间。
volatile-random:随机淘汰一个设置了过期时间的键。
allkeys-random:随机淘汰任何键,不论它们是否设置了过期时间。
volatile-ttl:淘汰具有最短剩余生存时间(TTL)的键,即那些最接近过期时间的键。
noeviction:不淘汰任何键。当内存达到最大容量时,Redis将不会进行任何淘汰操作,而是在写入新数据时返回错误。
三、生产如何选择淘汰策略?
在生产环境中选择缓存淘汰策略时,通常需要根据应用的具体需求和数据特性来定。这里给出常见案例:
电商平台的商品推荐
电商平台需要为用户展示个性化的商品推荐,其中热门商品的访问频率较高。可选择:LFU(Least Frequently Used)
redis-cli config set maxmemory-policy allkeys-lfu
因为LFU策略可以保留访问频率高的商品,确保推荐列表中展示用户最可能感兴趣的商品。
金融交易平台的实时数据
金融交易平台需要提供实时的股票价格和交易数据,数据的实时性至关重要。过期的时价被淘汰。
可选择:TTL(Time To Live)结合LRU(Least Recently Used)
redis-cli config set maxmemory-policy volatile-lru
TTL确保数据在一定时间后自动过期,而LRU保证最近访问的数据被优先保留。
电信运营商的用户数据管理
电信运营商需要处理和缓存大量用户的通话记录、短信记录等,用户通常更关心最近的通信记录。
可选择:LRU(Least Recently Used)
redis-cli config set maxmemory-policy allkeys-lru
因为LRU策略可以确保最近生成的通话记录和短信记录被优先缓存。
社交媒体平台的用户动态
社交媒体平台需要为用户展示好友的最新动态和帖子,用户通常对最新动态感兴趣。
可选择:LRU
redis-cli config set maxmemory-policy allkeys-lru
因为LRU可以保证最新的帖子被优先展示。
好了,今天就聊到这里,读者可依据实际情况择优选择策略。