说道问题,先说一个场景吧,便于大家理解。
在很久之前,PM打来电话说问答用户反馈说,用户的抽奖次数有问题,说今天一次也没抽奖怎么提示没有无抽奖次数了呢?
后来经过追查发现问题如下:

  1. 由于Redis做了读写分离
  2. 有的服务器集群读取的是从服务器
  3. 从服务器key已经过期,但是没有删除.

说道这里,或许又会有朋友说这是一个 XXX坑了, 也不能尽然这么描述,这个问题是确实存在的,咱们来梳理下Redis的删除机制。
redis 从服务器是无写权限的,所以没法做删除操作。

解决方案:

  1. 在程序拉取是否过期的时候不能只判断值是否存在,同时判断下 ttl
  2. 从存储入手,通过scan扫库(以下为原理)
    当redis中的key被scan的时候,相当于访问了该key,同样也会做过期检测,充分发挥redis惰性删除的策略。这个方法能大大降低了脏数据读取的概率,但缺点也比较明显,会造成一定的数据库压力,谨慎合理使用,否则有可能影响线上业务的效率
  3. 升级Redis3.2 版本

说到这来,咱们向下延伸下.

一、Redis key的三种过期策略

惰性删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key,很明显,这是被动的!
定期删除:由于惰性删除策略无法保证冷数据被及时删掉,所以redis会定期主动淘汰一批已过期的key。
主动删除:当前已用内存超过maxmemory限定时,触发主动清理策略,该策略由启动参数的配置决定,可配置参数及说明如下:

volatile-lru:从已设置过期时间的数据集中根据LRU算法删除数据(redis3.0之前的默认策略)
volatile-ttl:从已设置过期时间的数据集中挑选过期时间最小的数据删除
volatile-random:从已设置过期时间的数据集中随机选择数据删除
allkeys-lru:从所有数据集中根据LRU算法删除数据
allkeys-random:从所有数据集中任意选择删除数据
noenviction:禁止从内存中删除数据(从redis3.0 开始默认策略)
maxmemory-samples:删除数据的抽样样本数,redis3.0之前默认样本数为3,redis3.0开始默认样本数为5,该参数设置过小会导致主动删除策略不准确,过大会消耗多余的cpu