和缓存相关的几个核心概念
缓存污染:
指留存在缓存中的数据,实际不会被再次访问了,但又占据了缓存空间。换句话说,由于缓存空间有限,热点数据被置换或者驱逐出去了,而一些后面不用到的数据却反而被留 下来,从而缓存数据命中率急剧下降.
要解决缓存污染的关键点是能尽可能识别出未来热点数据,或者未来更有可能被访问到的数据。由此可见,在高并发的互联网系统中,缓存的命中率是至关重要的指标。
而缓存的命中率的提升,和缓存数据淘汰算法 , 密切相关。
Redis的数据清除策略
在使用Redis时,我们一般会为Redis的缓存空间设置一个大小,不会让数据无限制地放入Redis缓存中。可以使用下面命令来设定缓存的大小,比如设置为4GB:
CONFIG SET maxmemory 4gb
既然Redis设置了缓存的容量大小,那缓存被写满就是不可避免的。当缓存被写满时,我们需要考虑下面两个问题:决定淘汰哪些数据,如何处理那些被淘汰的数据
如果我们设置了Redis的key-value的过期时间,当缓存中的数据过期之后,Redis就需要将这些数据进行清除,释放占用的内存空间。
Redis中主要使用定期删除 + 惰性删除两种数据过期清除策略。
(1)定期删除:redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果有过期就删除。注意这里是随机抽取的。
为什么要随机呢?你想一想假如 redis 存了几十万个key ,每隔100ms就遍历所有的设置过期时间的key的话,就会给CPU带来很大的负载。
为什么不用单个key的到期删除策略呢?定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略。
(2)惰性删除:
定期删除可能导致很多过期的key 到了时间并没有被删除掉。这时就要使用到惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且过期了,是的话就删除。
2、定期删除+惰性删除存在的问题:
如果某个key过期后,定期删除没删除成功,然后也没再次去请求key,也就是说惰性删除也没生效。这时,如果大量过期的key堆积在内存中,redis的内存会越来越高,导致redis的内存块耗尽。那么就应该采用内存淘汰机制。
Redis的缓存淘汰策略:
Redis共提供了8种缓存淘汰策略,其中 volatile-lfu 和 allkeys-lfu 是Redis 4.0版本新增的。
1、noeviction:不进行淘汰数据。一旦缓存被写满,再有写请求进来,Redis就不再提供服务,而是直接返回错误。Redis用作缓存时,实际的数据集通常都是大于缓存容量的,总会有新的数据要写入缓存,这个策略本身不淘汰数据,也就不会腾出新的缓存空间,我们不把它用在 Redis 缓存中。
2、volatile-ttl:在设置了过期时间的键值对中,移除即将过期的键值对。
3、volatile-random:在设置了过期时间的键值对中,随机移除某个键值对。
4、volatile-lru:在设置了过期时间的键值对中,移除最近最少使用(最近最久未使用)的键值对。
5、volatile-lfu:在设置了过期时间的键值对中,移除最近最不频繁使用的键值对, 或者移除 最不经常 使用的键值对
6、allkeys-random:在所有键值对中,随机移除某些key。
7、allkeys-lru:在所有的键值对中,移除最近最少使用(最近最久未使用)的键值对。
8、allkeys-lfu:在所有的键值对中,移除最近最不频繁使用的键值对, 或者移除 最不经常使用的键值对
通常情况下推荐优先使用 allkeys-lru 策略。这样可以充分利用 LRU 这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。如果你的业务数据中有明显的局部周期性流量( 局部冷热数据区分明显),建议使用 allkeys-lru 策略。