当前位置: 首页 > 科技观察

秒杀系统宕机,凌晨1点紧急救援!

时间:2023-03-22 00:44:03 科技观察

公司最近安排了一波抢购活动。由于后台小哥的操作失误,活动没有效果,被用户和代理商投诉。经理让我带同事去复查网上事故。图片来自Pexels。是什么原因造成的?抢购活动计划准时零点开始:22:00,运营人员通过后台上线商品。23:00,后台小哥已经将商品导入缓存,提前预热。抢购开始的那一刻流量非常大。按照计划,大部分用户的查询请求都是通过Redis来承担的,避免所有的请求都落在数据库上。缓存命中如上图,预计大部分请求都会命中缓存,但是后台小哥在预热缓存的时候,设置了所有商品的缓存时间为2小时后过期。所以所有的产品都在同一个时间点失效,瞬间所有的请求都落在了数据库上,导致数据库在压力下崩溃,所有的用户请求都超时报错。其实所有的请求都是直接落到数据库上的,如下图:缓存雪崩是什么时候发现的?凌晨01:02,SRE接到系统告警,登录运维管理系统发现数据库节点CPU和内存飙升超过阈值,赶紧联系后台开发人员定位检查。为什么我没有早点发现?由于缓存设置的过期时间为2小时,缓存可以在凌晨1点前命中大部分请求,数据库服务正常。发现后采取了哪些措施?后台小哥通过日志定位和排查发现问题后,进行了一系列操作:首先,通过APIGateway(网关)限制大部分流量。然后重启宕机数据库服务。再次预热缓存。确认缓存和数据库服务正常后,网关流量正常放行,01:30左右抢购活动恢复正常。如何避免下次发生?造成这次事故的原因其实是缓存雪崩。查询数据量巨大,请求直接落在数据库上,导致数据库压力过大宕机。其实业界解决缓存雪崩的方法已经比较成熟,比如:统一过期添加互斥锁,缓存永不过期统一过期设置不同的过期时间,让缓存失效的时间点尽可能统一。通常可以在有效期上加上一个随机值,也可以统一规划有效期。缓存键过期时间均匀分布,互斥锁与缓存击穿的解决方案一致。同时只允许一个线程建立缓存,其他线程阻塞排队。互斥访问缓存永不过期与缓存崩溃的解决方案是一致的。缓存在物理上永远不会过期,并且使用异步线程来更新缓存。异步更新缓存回顾总结和同事一起回顾了这次线上事故,大家对缓存雪崩有了更深的认识。为了避免再次发生缓存雪崩事故,我们一起讨论了多种解决方案:统一过期加互斥锁缓存永不过期希望技术人员对每一行代码都保持敬畏之心!作者:雷佳,毕业于华中科技大学,硕士;大厂:华为、网易、百度……编辑:陶家龙