title: 缓存不当至服务崩溃 date: 2017-12-20 22:45:20 tags: categories: Redis
论坛系统的首页推荐贴是一个访问非常频繁的数据,且更新频率较低。
为了减少中间层把大量无意义的请求发往后端接口,3个月前在缓存上做了如下调整:中间层负责记录缓存,后端只负责从 DB 中查出数据,需要更新时再去删除此缓存(两者连接了同一个 Redis)。
这就埋下了隐患,当缓存过期时,会迸发大量的请求抵达后端,直接对 DB 造成压力。
然而该 SQL 在正常走索引的情况下查询速度是毫秒级,另一方面并发量没有大到夸张。运转看似正常,没再继续做改进,也未能预估到风险的严重性。
有经验的人肯定知道,如果后端的 SQL 查询速度较慢,或因网络拥堵,中间层不能及时更新数据到缓存,必然会堆积大量的SQL查询,服务可以瞬间宕机。
论坛项目交接他人之后,其优化的过程中发现这条索引影响了其他业务的查询,也遗漏了对热数据的影响检测,对该索引执行了删除。像是启动了定时炸弹,一周后缓存自然过期,最终结果是“击穿”了 20 秒的慢查询。。。
当发现重启 MySQL 后又迅速死掉,基本可以定位到问题是缓存穿透所至。
至此服务回复正常运转,但随着旧索引的添加,其他业务的优化也遭到了负影响。即刻开始了进一步优化。
采用删除缓存来更新数据的方案是“学”自项目其他业务,最大优点是简化了事务中重建缓存的方式,虽然并不能真正避免脏读等问题。
热数据切不可这样操作,需要完善的缓存重建方案做后盾。
开发阶段周全地评估可能风险是十分必要的,这需要更多经验,也要努力避开思维惯性。