一次连锁反应的线上事故

405 阅读3分钟

1.事故过程        

       阶段1: 某一天业务高峰开始没多久,突然线上系统大量超时报警,看日志是调用a服务的接口不可用,查看事发最早的日志,发现是a服务的慢sql导致db拖挂了,同时导致所有接口慢,此时用户在不停的重试,导致慢的更慢,api的tomcat连接数也打满了。排查发现那条慢sql没有建立对应的索引,dba紧急加上索引,此时事故结束。        

       由于一条慢sql导致整个系统不可用,虽然加上索引解决了问题,不过相关开发讨论觉得这块太过于依赖db,需要梳理下,看能不能在有些地方加入redis缓存。经过排查代码和业务,了解到这块业务的数据都是提前做好的,短时间内不会变更,很适合用redis缓存。于是在当晚就上线了一版redis缓存替换db的方案。        

       阶段2: 第二天业务高峰时期同样出现了昨天的情况,大量接口超时不可用,开始以为是慢sql导致的,可是经过监控和日志发现并没有任何服务有慢sql,同时收到a服务宕机的报警。运维第一反应是重启a服务。重启完成后,系统正常。可是过了一个小时多,系统又不可用了,收到a服务宕机的报警。运维登录服务器查看,a服务的机器已经挂了,可是服务注册中心仍有a服务,a服务还能上报注册中心,这才导致应用还会调用a服务但是会超时,a服务处于假死状态。由于系统使用高峰期,于是只能再次重启a服务,暂时先保证系统可用。       

       阶段3: a服务重启过了一个多小时,又出现上面的情况,不过这次运维提前做好了准备,立马jstack了现场,之后重启服务,直到当天业务结束。分析jstack日志发现,是报的jedis异常,不过这个异常挺诡异的,并非业务bug导致的。通过查询redis相关异常发现这个是jedis的bug导致的,当并发超过5万左右的时候jedis连接池就不够用(我们测试的,不代表全部情况),需要升级jedis到2.10以上版本。修复方案是升级jedis或者弃用jedis,问题修复。

2.事故原因分析         

事故的起因是一条慢sql,不过后面的jedis问题也是隐患的,只不过以前没有现在的业务量,并发数没有达到这个量级而已。对于慢sql缺少监控,对于db表、索引等缺少规范。对于第三方工具类缺少压测等性能测试后就使用。

3.总结和警醒        

       第一:对慢sql加强监控,建库建表要规范,根据业务使用情况核查索引等关键点是否规范是否缺失。        

       第二:redis等第三方中间件的使用要试用,要压测,经过验证后满足线上业务高并发高可用高性能等方面的要求后放可上线使用。