文章简介
工作这几年,技术栈在不断更新,项目管理心得也增加了不少,写代码的速度也在提升,感觉很欣慰,毕竟是在一直进步,但是过程中也有许许多多的曲折,也踩过了数不尽的坑坑洼洼,从一个连百度都不知道用的萌新到一个悠哉悠哉的老油子也不容易,很多人应该都有类似的经历和感受,因此博客中也会整理一些曾经碰到过的事故和问题给自己提个醒。
由于接下来要在perfect-ssm项目中引入缓存模块,恰好在翻看日记时看到了这次事故的记录,因此整理了这篇文章,根据事件发生时的日记来回顾一下这次事件,通过这次数据库事故的真实案例及后续的事故处理作为引子来讲讲缓存,为什么要这么做呢,因为我觉得网上关于缓存使用的重要性和必要性的文章已经很多了,一个又一个的原因及使用缓存的益处都写的很清晰,我再去写一遍有些多余,不如通过这种亲身经历的案例来得好。
虽然当时也知道缓存的重要性,也想去在项目中使用,但是由于当时太菜了也不知道怎么去在项目中整合缓存,所以使用缓存的事情就一拖再拖,而这次事件及后续的处理也是我第一次在项目开发中使用缓存,这也是为什么我选择使用这篇日记来写这篇文章并作为缓存接入的引子,其实还有很多日记,不过这篇就显得比较特殊了,刚好要在perfect-ssm里用到,因此结合这篇日记整理了一篇文章。
项目介绍
前面写了三个段落,不能再继续写了,主角该出场了,先来简单的介绍一下发生这次事故的项目,当时所在的公司是一家小型的电商公司,公司主要的线上产品也就是一个商城项目,上线运行了一段时间,还处于继续开发和优化的阶段,用户界面就是很雷同的一些电商属性:商品、购物车、订单、支付,后台则是一些运营数据,仓库系统(商品的入库和出库),订单管理等,用户量和订单量还算不错吧,比上不足比下有余,马马虎虎可以让公司正常运转,OK,基础信息介绍完毕。
第一次崩溃
这次事故发生的时间点是在某天的上午(额...又是发生在上午),事发比较突然,客服陆陆续续接到几个用户的反馈电话,起初并没有在意,以为只是某些用户的误操或者某些商品在仓库里没货了,这些都经常遇到也就没放在心上(处于萌新阶段的自己最大的优点应该就是心比较大,什么事情都觉得无所谓,哈哈哈哈),但是接下来的投诉越来越多,老大就让我赶紧去看看是怎么回事,我这时候才打开网站开始查问题(心大不大?或者说楞不楞?)。
诡异的事情也发生了,网站打开一切正常,网站首页好好的,搜索功能也正常,商品详情页也可以用,当时心里一紧,这是发生了什么事情啊?服务器卡了?tomcat集群挂了其中的一台?赶紧去看服务器,结果所有实例的运行一切正常,看到这个结果心里的紧张又多了几分,和平时的剧情不太一样,这个时候不应该是服务器挂掉然后重启的桥段吗?答案是no...
又去找客服,到底是什么事情,客服说基本上都是说无法下单,我又赶紧去下单,走一下订单流程,果然,卡在页面上一动也不动了
无法生成订单,陆陆续续点了其他页面,发现都是正常的,订单列表和订单删除都能用,只有订单生成不行,赶紧去查日志,也没有报错(这个我有点记不清了,到底报没报错以及报了什么错,只是记得查了日志也没查出什么问题),我赶紧去找老大,报!服务器没问题!日志也没问题!数据库也可以正常的查询!订单表也正常!就是无法生成订单,可能是订单接口有问题!(可以脑补一下当时的愣头青场景),这个时候我也懵了,到底是什么情况呢?什么都正常怎么会出现这种情况,以我当时的水平只能在旁边喊666,然后就把事情推到了老大身上(美滋滋...),没办法,我真的不会,也想不明白是什么问题。
老大当时也按照我的思路去查了(可能觉得我中间有偷懒以致于没查出来),当然他也什么都没查出来,然后就开始去看数据库,查了也挺久的,我记得这个过程中我是很煎熬的,也帮不上什么忙,还要听客服那边催,中间也侥幸的觉得是不是哪里抽风了过会儿就好了,就去下了几次单,结果都不行,最后只能坐在老大旁边看他敲代码,最气的是,很多sql命令和linux脚本也看不懂...
代码没问题,日志没问题,集群也好好的,基本也就可以猜到问题应该在数据库了,不过我没有查看和操作的权限,所以具体是不是,当时我也不知道。
老大一直在查,我就只能呆呆的等着,过了一会儿老大说是有两张表锁住了(我的内心OS:表锁住了?什么意思?怎么会锁住?等等...数据库锁是什么东西),试着去解决但是没有成功,一时也想不出好的办法,客服那边同事催的也紧,气氛有点僵,然后我就说出了我的"高见",老大,要不咱们重启数据库吧,话一说完,老大看了我一眼,我猜眼神里应该满是赞善,然后对着我笑了笑,他可能觉得这是个很好的方案吧,他怎么就没想到呢?(ps:也可能是在心里骂我,这个愣头青,一出问题就知道重启,tomcat重启,nginx重启,服务器重启....现在又要mysql重启)当然,由于比较混乱,我说了这个方案后,他也就有些妥协了,然后就去杀了一些进程,并重启了mysql服务,大概也就花了两三分钟左右的时间,虽然是线上环境,影响肯定是有一些的,但是也绝对不会太大,毕竟业务刚起步,系统也是在开发和完善中。重启后,果然就有了效果,可以正常下单了,我们也松了一口气。又观察了一段时间,发现系统一切正常,刚好也到了中午,也就去外面吃饭了,回来之后,继续检查并观察了数据库的情况,发现一切正常,于是就将这件事当做是一个偶然事件,没有特别注意了,由于公司人员紧张(初创公司的技术部,算是什么部门......),每个人的事情都很多,老大也就去忙其他事情去了,给的建议是让我去查一下sql,是不是用了太多的联查,或者创建的索引不合适之类的问题导致了死锁,由于没有带来特别大的影响,也就当成一个普通的偶然事件了,老大也说了,下个版本要加上缓存功能,不然随着业务的增长数据库可能会有些撑不住。
又崩溃了
可能有些朋友心里会有一些疑惑,事情就这么结束了?怎么这么快?
肯定没有!事情肯定不会就这么完了的,不然我也不会单独整理这么一篇文章了,在下午的四点钟之后,又出现了同样的问题,不过这次就严重的多了。
依然跟上午的情况类似,在工位上开发的时候陆陆续续又收到了客服的信息,与上午同样的用户反馈,这下就不像上午似的手忙脚乱了,验证了网站应用后发现问题和上午一样,于是老大直接去查了数据库,再接着就是重启了数据库,网站又可以正常运行了,但是这个时候,*都能意识到网站出问题了,绝对不是偶然事件,虽然选择了无奈的重启数据库服务,但也不能每次都这么做,必须把问题找到并解决,但是我了解到的信息就是数据库几张表被锁住了,关键是我也不知道怎么做,去百度也百度不出个鸟儿来,当然,问题肯定是出在数据库这里,老大给我的建议也是去找下单逻辑的问题以及相关联的sql是不是有问题......(肯定没有找到问题啊,因为这次的事件根源并不在此)
在大家检查代码检查sql和在网上找解决方案的期间,同样的问题又再次发生了,不过这次比前两次更严重,不仅仅是下单流程,其他的功能也不能用了,接口大部分也挂掉了,数据库的问题更严重了,下午这两次事件发生的时间基本没有隔太久,就是说刚重启没多久,数据库又崩了(这感觉像不像是被攻击了?嘿嘿嘿),真的是爆炸,问题也没定位到,当所有人都觉得我们是被人攻击了甚至感到了绝望气息的时候,巧了巧了,仓管那边也过来反馈,说无法录入商品进行上架操作,还说上午也碰到了类似的情况,这个时候我们几个开发才反应过来,仓库后台是最近更新的,可能问题和这个有关,于是赶紧详细地问了一下仓管,上架了多少商品,有几个人在上架,得到的答案也很满意,上午也入库了,不过打电话之前入库的比较多,是叫了几个兼职一起做的,这个时候好像有点儿眉目了,想了一下更新的功能以及新的入库代码我们才恍然大悟,也渐渐地清楚了问题的根由!有问题的sql语句在这里!于是我们与仓库主管沟通,由于仓管系统刚更新,有些不稳定导致了一些问题,先暂停一下入库,我们赶紧把问题修复掉。
原来攻击我们网站的是自己人!
乖乖隆叮咚,原来"攻击"我们网站的是自己人!
具体的经过忘记了,总之是记得当天网站出现过三次事情,现在总结起来也就清晰了很多,基本上每次事情发生的时候,仓管都在做入库操作,最后入库的量比较大,根据仓管负责人的描述也就大致能够对应起来了。第一次第二次还好,只是表锁住了,但是第三次就比较严重了,数据库服务资源耗尽了,根本连不上,只有部分请求是正常的。当然根据仓管的说法再联想一下大致也就清楚了,由于前两次入库的商品并不多也不密集,因此虽然存在锁表的情况以及下单失灵的问题,但是依然有部分下单请求是可以正常执行的,大部分接口也是可以正常运行的,但是第三次由于入库的商品数量较大以及速度较频繁,不仅仅导致了锁表,也导致了数据库连接被耗尽,进而导致大部分接口也挂掉了。
看到这里肯定有很多朋友会问,你们网站是怎么做的,一入库就会崩溃,那还玩什么啊?先别激动,我们当时也是被搞得措手不及,以前也做过很多次的入库操作,一切都是正常的,根本没有过这种把数据库拖垮的情况,所以发生这件事的时候,作为当事人的我们也都挺惊讶的,由于以前根本没有过类似这种事件的发生,我们也想当然的忽略了,没往仓管方面去考虑,而且下午两次事件的发生时间又特别近,根本来不及排查问题。而这次事故的发生就是这么巧合,因为仓管后台刚做了改版不久,加了一些功能,原来比较稳定的功能被要求修改,主要原因在于这次更新后的页面设计以及对应的sql语句问题,与数据库的配置没有特别大的联系,当然,数据库配置高的话可能这个事故的发生会晚一些,但迟早还是会发生。
崩溃的部分结束了
不知不觉已经码了这么多的文字,粗略的估算了一下,大概有六千多字了,看来对那时候的自己以及当时经历的事情还是有很多的感慨和想法的,有些场景依然历历在目,而当时自己的一些想法和反应现在还是有一些印象的,真的觉得当时的自己好傻好呆。
本来想将后续的原因分析和事件处理过程也一起写进来的,但是如果加进来的话文章的篇幅确实有些太长了,这篇文章就已经回忆了这么多事情,所以具体原因和后续的解决过程还是再整理整理放在后面一篇文章里讲吧,如果写在一起真的就太长了,估计很多人要一拉到底了,哈哈哈哈。
结语
关于本次崩溃事故的记录到这里就告一段落了,糟糕的系统设计和拖垮系统的sql语句会在下一篇文章中再详细介绍。
首发于我的个人博客,新的项目演示地址:perfect-ssm,登录账号:admin,密码:123456
如果有问题或者有一些好的创意,欢迎给我留言,也感谢向我指出项目中存在问题的朋友,本篇主要讲述一次Mysql崩溃的事件。
如果你想继续了解该项目可以查看整个系列文章Spring+SpringMVC+MyBatis+easyUI整合系列文章,也可以到我的GitHub仓库或者开源中国代码仓库中查看源码及项目文档。