余晟:让自家系统瘫痪,这事我也干过
文/余晟
最近几天国内互联网圈接连出现停服事故,先是支付宝停服超过 2 小时,然后是携程停服超过 8 小时。一时间许多人大惊:原来大玩家们的运维水平这么出乎意料。
我想说的是,我认识的做技术的,许多人都有把网站(系统)搞瘫痪的经历。有些聚会上,说不出自己把系统搞崩溃过的经历,人家都不认为你是“自己人”。还好,我是可以荣列“自己人”队伍的,下面我要说的就是我的经历。
2007 年,我当时在“抓虾网”做后台开发。网龄老一点的读者大概会记得这个网站,当时排名第一的中文在线 RSS 阅读器。如果不理解什么是“RSS 阅读”,可以理解为“博客的朋友圈”:当时还没有微信,只有博客,在线 RSS 阅读就是把你关注各博客的更新都抓回来,拼成“朋友圈”方便阅读的工具。
问题出现在一天晚上。有一张数据库的表里记录了当前等待执行的任务,通常来说,里面的记录应该不超过 100 条。不幸那天程序出了点问题,到下午 6 点堆积了两三千条记录,我一直调到晚上 8 点多才算解决,看着数据量一点点降下去,我放心地回家了。
到 11 点半,洗漱完毕,马上要上床睡觉了,我想登上服务器确认问题已经解决。检查发现,还有不到 200 条记录。看来问题确实已经解决了,只是看着这个数字确实有些不爽,平时都不到 100 呢。于是我想,不如把表给清空了吧,数字就好看了,反正都是会反复执行的临时记录,也没什么影响。
等我输入清空数据库表的 truncate 语句之后,稍微感觉有些异样,怎么执行了这么久,平时不用 1 秒的语句,现在竟然执行了 5 秒。再看看监控系统,瞬间大惊失色,瞌睡全无:原来我把最重要的博客地址列表给清空了,抓取、分析、存储模块群龙无首,都在空转。
与 delete from 相比,用 truncate 语句清空,速度很快,但无法通过日志来恢复;虽然数据库有热备,但可以想象,1 秒不到的时间里,这条错误的指令已经发送到各台热备机,所以大家都清空了这张表……
我当时刚刚工作不久,而且一直做后台开发,从来没有遇到过这样程度的在线问题。第一反应就是打电话给领导,于是我拨通了振宇(现任去哪儿网集团 执行副总裁&无线事业群 CEO)的电话。振宇听完我的描述,只平静地说:赶紧恢复数据,最迟明天早上必须要解决,不要让用户感觉到。
我本来是想让他告诉我怎么处理,结果他只给了我一个目标。后台系统平时都是我在维护,找其它同事也帮不上忙。所以我虽然满头大汗,也只能努力静下心来,想想到底要怎么办。
首先我把相关的模块都停下来,避免弄得自己心烦意乱。然后把数据库的表都画在纸上,看看互相之间的关联,能不能拼一份数据出来。很快我找到了从 几张表拼出原始数据的方案(这时候才知道冗余设计是多么好)。写了一个 Python 脚本测试,通过。那么赶紧上线!这时候是凌晨 1 点。
然而事情并没有那么简单,数据倒是恢复出来了,速度慢得吓人。一共有五百多万条数据要恢复,每秒钟只能恢复不到 50 条数据,全部恢复要超过 1 天,肯定会严重影响客户体验的。
虽然已经接近 2 点了,但我睡意全无(也不敢有)又束手无策。只能一边徒劳地看着恢复进度,一边分析:如果没有冷备(当时确实没有),看来全部恢复是得 1 天了。怎么能不让用户发现呢?出个维护通告?……忽然我想到,既然用户订阅数都在,先把活跃用户订阅的、订阅数量多的博客地址挑出来,然后再恢复其它的。
很快我统计出符合条件的记录,大概六十万条,按照每秒 50 条的速度,一小时可以恢复 18 万条,4 小时左右可以全部恢复完毕。现在不到 3 点,全部恢复完毕是早上 7 点左右,用户的第一个活跃期在早上 8 点多(当时绝大多数人都是 PC 上网),应该来得及。
再写程序,测试,通过,再上线,观察了一段时间,发现速度是正常的,符合预期。这时候已经四点多,全身湿透了。我给振宇发了个短信说“已经在恢复了,确保不会影响客户体验”,才倒下去睡觉……
天亮了,起床第一件事就是检查恢复进程,发现没有问题。然后我怀着忐忑的心情,装做没事人一样去上班,果然没有人发现问题。中午吃饭的时候我偷 偷找到运维的同事,说了这件事情。他的反应更让我出乎意料:这有啥,大家都有采坑的时候,我以前在百度,迷糊了把几个T的前端缓存删掉了,出去抽颗烟,回 来该怎么样还怎么样……
到当天下午,没有人订阅的数据也已经恢复了,整个过程还算成功,没有用户发现异样。
后记
这次事件给我的印象太深刻了,尤其是大半夜惊心动魄地调试,说折阳寿真是不夸张。所以在这之后,我把冷备做起来了,把备份恢复方案做起来了,把 数据库分账号控制做起来了,再也不敢随便清空数据表了……吃一堑长一智,好的系统都是一个个小坑填出来的,重要的是看到小坑就要去甜,不能永远靠人力处 理,靠手工搏斗。长期来看,我改变了工作习惯,每次接手生产系统,第一时间会去关注系统的完整和安全,不再着迷于系统架构和代码质量。
现在再回想,还有两点庆幸:一是抓虾是面对中文用户的服务,后来面对要支持多国协作的系统时,才真正知道“全球化”意味着什么;二是振宇当时只 设定了目标,给了我锻炼和成长的机会(后来和新浪谈技术合作,他给我发的短信只有一句话“今天一定要把新浪的人搞定”,我印象也很深刻)。
当然,对我来说,最重要的收获是一条终身受用的道理:哪怕情况再紧急,也不能手足无措,静下来心来仔细分析,这才是解决问题的根本途径。有经验和没有经验的差别,很多时候不在专业技术上,而在于把握能力上。