记一次redis过期配置不当导致的类缓存雪崩事故

解释一下标题中的字,为什么要这么说呢?这是因为事故本质上还不是真正意义上的缓存雪崩事件,真实原因是由于服务器配置与业务增长量过大导致的.
在正式开始介绍事故经过前,先大概介绍一些概念.

1.什么是redis

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、基于内存亦可持久化的日志型、Key-Value 数据库,是NoSQL(not only SQL)大家族中的一员。

2.什么是redis缓存雪崩与缓存穿透

  • **缓存雪崩 ** 原本存储在缓存中的大量热点key在同一时间全部失效,导致大量的请求直接打在数据库上,这种时候流量大一点数据库肯定直接就挂掉了.效果如图:
    在这里插入图片描述
     * 缓存穿透  缓存穿透是指缓存和数据库都没有的数据,例如数据ID为-1或者数值非常大的请求.当这种类型的请求被大量发起时也会导致数据库压力增大,导致宕机.如下图:
     在这里插入图片描述

3.如何解决缓存雪崩与缓存穿透

解决缓存雪崩

对于缓存雪崩可以在设置过期时间时加上一个随机数值,将热点数据的过期时间错开这样就能有效防止大量key在同一时间过期.

解决缓存穿透

对于缓存穿透可以在接口层增加数据的校验,用户鉴权,参数拦截等,对于 类似id<=0之类的请求直接Return.

4.服务器配置不当可能导致缓存雪崩

除了上面提到的过期时间重合会导致缓存雪崩外还有可能会导致缓存雪崩的原因是:redis的数据过期驱逐策略配置可能会导致部分数据被redis淘汰出现缓存无效的现象.

上周一正常上班期间,突然收到现场同事的消息说客户反映部分时间段(12:00-1:30)调用校验接口出现异常返回,但是查询数据库却存在的现象,手动调度执行缓存更新任务后,校验正常.刚收到消息时以为是数据设置的过期时间太短导致的问题,通过查询却发现数据设置的过期时间都属于正常范围的24小时.手动调度与自动调度后查看数据的过期时间设置也没有问题,这可就奇怪了.没有经验的我以为是部署时出现服务器代码不一致的情况,于是我便挨个检查服务器上的代码与正式使用的发布版本是否有不一样的地方,可是一圈查找下来也没发现什么地方不同(排查方向错误,浪费了大把时间).就在我没有头绪准备放弃的时候,同事小周跟我说他那边没法查询缓存内容了,页面一直转圈,没有返回,我听到这个消息后立马在我的电脑上输入查询帐号和密码登录系统查询,发现刚刚手动执行定时任务写入缓存的数据被清除了,发现这个现象后我特意查看了一遍涉及到缓存的业务代码部分,确定代码里头没有缓存删除相关的代码.上网查阅资料发现当redis发现可以使用的内存空间不足(达到配置的最大值)时,redis 会根据配置文件中空间分配策略来移除部分数据.

与内存策略有关的部分配置文件如下:

# MAXMEMORY POLICY: 当redis使用的内存达到配置文件中设置的maxmemory后,redis会根据配置的策略来移除部分数据
# volatile-lru -> 在设置了过期时间的key的集合中按照最近最少使用原则选择key进行淘汰
# allkeys-lru ->  在所有的key值集合中按照最近最少使用原则进行淘汰.
# volatile-lfu -> 在设置了过期时间的key的集合中按照最近最频繁使用原则选择key进行淘汰.
# allkeys-lfu -> 在所有的key值集合中按照最近最频繁使用原则进行淘汰..
# volatile-random -> 在设置了过期时间的key值集合中随机选择部分key进行淘汰.
# allkeys-random -> 在所有key值的集合中随机淘汰部分key.
# volatile-ttl -> 在设置了过期时间的key值集合中,选择最接近过期时间的数据进行淘汰
# noeviction -> 不淘汰数据,在遇到一个写操作时直接返回错误给客户端.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used

# Note: 不管配置了哪一种数据驱逐策略,当没有符合条件的key能用来淘汰时,遇到写操作时redis会直接返回一给错误给客户端.
# 默认使用的驱逐策略是按照过期时间排序,选择最接近过期时间(过期时间最短的)进行清除
maxmemory-policy volatile-ttl

知道这个后,我立马查看了一下服务器上的配置信息,发现设置的数据清除策略是volatile-ttl,该策略会从设置了过期时间的key值集合中选取部分过期时间最短的进行驱除.而12:00-1:30正是任务执行高峰期,在即将达到maxmemory的设定值时,又出现大量写请求,触发了redis的数据驱逐策略,所以出现部分时间段缓存查询不到数据的情况.
找到问题所在后就好办啦:针对这种情况,可以根据服务器配置来适当调大redis配置中maxmemory的值,如果不希望redis驱逐数据的话,那么可以将驱逐策略maxmemory-policy调整为noeviction,并在运维系统中增加内存使用情况的监控,达到预警值即时告警,通知相关人员处理,避免影响生产.

参考资料:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值