Redis的过期策略

==Redis的过期策略==是:定期删除+惰性删除

定期删除
  • 这里的定期删除是指Redis默认每隔100ms就随机抽取一些设置了过期时间的key。检查其是否过期,如果过期就删除
  • 定期删除每次只是随机抽取一部分的key进行判断其是否过期而已。如果是全部取出来判断的话,假设Redis里放了10w个设置了过期时间的key,每隔几百毫秒,就检查全部10w个key,那cpu的负载会很高,都消耗在检查过期key上了,这将是一场性能的灾难。
    惰性删除
  • 因为定期删除具有随机性,所以可能导致很多过期的key没能及时的清除掉。所以Redis同时采用了惰性删除的策略。
  • 惰性删除是指,在获取某个key时,Redis会先检查一下,这个key如果设置了过期时间那么它是否已经过期,如果过期了就会被删除,不会返回任何结果。
    内存淘汰机制
  • 如果定期删除漏掉了很多过期key,而这些key又没被及时查询,不触发惰性删除,久而久之,大量过期key堆积在内存空间里,就会导致Redis的内存块耗尽。
  • 这时Redis需要走内存淘汰机制。
    Redis的内存淘汰机制
    策略|含义
    —|—
    noeviction|==不进行内存淘汰的策略==。当内存不足以容纳新写入数据时,新写入操作会报错。
    allkeys-lru(常用)|当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key。
    allkeys-random|当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key。
    volatile-lru|当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key。
    volatile-random|当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
    volatile-ttl|当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。
    Redis设置内存淘汰机制的指令
  1. 获取当前内存淘汰策略:config get maxmemory-policy
    • Redis 默认采用 noeviction 策略,即不进行内存淘汰的策略。
  2. 获取Redis能使用的最大内存大小:config get maxmemory
    • 如果不设置最大内存大小或者设置最大内存大小为 0,在64位操作系统下不限制内存大小,而在32位操作系统下最多使用3GB内存(32 位的机器最大只支持 4GB 的内存,而系统本身就需要一定的内存资源来支持运行,所以 32 位机器限制最大 3 GB 的可用内存)。
  3. 设置内存淘汰策略:config set maxmemory-policy allkeys-lru

    • 返回 OK ,设置成功。当然也可以通过修改Redis的配置文件 redis.conf来设置:
      maxmemory-policy allkeys-lru
  4. 设置Redis最大占用内存大小:config maxmemory 100mb 设置内存大小为100mb

简单手写LRU算法

淘汰算法:最近最少使用算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int CACHE_SIZE; //缓存的大小,最多能存储的数据

public LRUCache(int cacheSize) {
// true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最
super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
CACHE_SIZE = cacheSize;
}
/**
* 钩子方法,通过put新增键值对的时候,若该方法返回true
* 便移除该map中最老的键和值
*/
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
// 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
return size() > CACHE_SIZE;
}
}