话说距离周五上线后第一天的数据库故障已经好几天了,上次的紧急恢复过程中也没来得及复现现场问题,用户微信入口的代码逻辑并不复杂,也没有什么明显漏洞。
海创园的办公场地已经跟夏日的游泳池一样了,所有的边边角角都放满了桌子和人。各个部门负责安排新人座位的人肯定已经头很大了,要在如此紧张的空间中再挖掘出来能坐人的地方简直就是门艺术~ 不堪重负下终于开始启用新办公地点,周一部门从“乡下”搬到西溪路的“城里”,转身做了城里人。
周一开了第二个屏幕专门盯了一天系统监控,流量和负载都较平稳,到下班也没发现什么异常,可以愉快的回家了。
周二也盯了半天,一切正常,活动将在周四晚间结束。看看没什么大问题,由于之前太累,周三开始调休。但,墨菲定律又生效了,这东西是看星际穿越从诺兰那学的,用在这里正合适。
周三4点多合作方又通知5点钟计划另一个公众号要推图文引入用户进入游戏,虽然在家休着但闲着无事打开监控系统看着有啥问题没。到了时间,应用服务器cpu和数据库负载确实有所上升,但看起来问题不大,于是打开爱奇艺准备欣赏道士出山,后面证明这是个悲剧,跟林志玲的道士下山没半点关系。
看了没几分钟,运维同学打电话来,说“上次你说想要的现场来了,连接数又上来了”,马上登上数据库机器查看,cpu usage, load average值跟上次故障如出一辙;但这次有所不同,一是已经有了上次的经验,二是运维同学这次没在高速的半路上,可以一起及时处理。
数据库的配置是8核虚机,上次已经知道负载大是tomcat应用尝试建立更多的jdbc连接,而数据库的最大连接已经配成了3000,但操作系统文件句柄没放开,所以仍只能开到1024个连接。
阶段一:降级应用##
既然是14个tomcat应用尝试开更多连接,那首先要降低数据库压力就从关tomcat开始,关了一半tomcat机器,观察数据库连接仍然是1024,考虑到TCP的close wait可能需要部分时间,所以又等了一会,确认没有降低后决定继续关tomcat。做这个动作时有个疑问,上次单个tomcat连接数据库的参数应该已经调成了60,数据库端的连接数最大应该只有840,为何这次又到了1000多?
tomcat关到只剩两个时,数据库连接数开始降下来了,到了300,此时系统负载虽然CPU仍然是99%,但load average已经从500降到了基本安全的1点几。这个机的生产库虽然有些配置问题导致数据库的sql query log没有输出,但根据上次另一台机的经验,慢查询都在查单条用户表数据上,这个操作是在每个用户进入页面时,如果session中不存在此用户信息时做的操作。
阶段二:加数据库##
此时的现象似乎单个数据库不能承受这个业务逻辑上进行的查询,所以此时做的第二个动作就是开始准备用多个数据库给前端业务分流。在运维同学给我准备数据库的时候,抽空查了一下连接池配置,发现设置的最大连接数量不是之前设想的60,而是150,可能是由于上次问题时临时改的,所以之前应用连接到1000+到正常的。
此时两个数据库已经准备好,将之前备份的主库dump到新数据库,重新修改war包的数据库ip地址,启动3个tomcat对应一个数据库并重新发布;后又启动3个tomcat对应另一个数据库。再看监控,分流数据库访问似乎并不能缓解问题,起的数据库都马上CPU 99%,想让用户正常访问页面仍然困难。
阶段三:迁移缓存##
既然数据库hold不住,只能临时改程序将所有用户数据放在redis缓存里,由于是集群部署所以将原jedis连接池配置从1000改为100。改好上传正要发布时,电话那边几个哥们居然喊着火了,刚搬去的新办公室就着火了?我不在现场只能听到电话免提里的背景音,背景人声里似乎有物业要让他们断电撤退,但听到运维的哥们镇定的说等等先别断,让我把这个程序先布上去。。。
这个着火算是个小插曲,过了一会这几个哥们似乎没动地方,继续在处理问题,估计不是要紧的大火,生命没啥危险。此项更改先在一个单实例tomcat上测试,前端nginx已改为指向此单个tomcat。缓存上来需要预热,用户第一次进来还是需要找下数据库,后面就不需要了。确认功能没问题后,开始将新的war包部署到所有tomcat并全部启动。10几分钟过去后,缓存连接在最开始时有个峰值到了1000,之后稳定在了600,查看应用服务log开始正常了。
8点多应用基本正常后,电话那边几个哥们开始叫全家桶外卖了,咱也终于能把吃了一半的饭吃完。
遇到线上故障,首要的是开发自己要冷静,顶住各方面的压力。如你这里正忙着尝试恢复,那边上级领导一个个的打电话来询问情况,这还不算完,还有合作方的人看到服务不可用了也来打电话找你,这时开发哪有精力理会这些,自己要知道轻重缓急,不能lost focus,集中精力做自己该做的事情。
上次参加杭州Oracle用户组时一个DBA说过,做这行,要能承受很大压力,因为每天接触的都是业务方最核心的数据库,一旦遇到数据库崩溃,你在恢复的时候自己决不能慌,这时可能有很多人(领导,同事,焦急的客户)围在你身后看着你,这时你要打键盘手都要抖那可不行。这句话对处理线上故障的开发人员也是一样,想必携程的事故处理的当事人也会有同感。
最后送上百度百科里墨菲定律的解释,祝各位周末愉快。
“墨菲定律”(英文:Murphy's theorem)主要内容有四个方面:一、任何事都没有表面看起来那么简单;二、所有的事都会比你预计的时间长;三、会出错的事总会出错;四、如果你担心某种情况发生,那么它就更有可能发生。
“墨菲定律”的根本内容是“凡是可能出错的事有很大几率会出错”,指的是任何一个事件,只要具有大于零的机率,就不能够假设它不会发生。
在科学和算法方面,它与英文所谓的“worst-case scenario(最劣情形)”同义,数学上用大O符号来表示。例如,对插入排序来说,最劣情形即是要排序的阵列完全倒置,必须进行 n*(n-1) 次的置换才能完成排序。在实验上,证明了最劣情形不会发生,并不代表比它轻微的情形就不可能,除非能够很有信心的推论事件的概率分布是线型的。
文章来自微信平台「麦芽面包」,微信号「darkjune_think」。转载请注明。