赞
踩
这几年,我在饿了么和阿里本地生活经历了业务快速发展的黄金时期,也遇到了一些令人“出乎意料”的事故。
2018 年的 915 事故,应该是这几年最严重的一次宕机,直接导致技术组织调整和一位技术大牛的离开,公司也赔了数亿的红包;1225 圣诞节宕机事故更是导致骑手罢工,甚至半年后还有城市经理和我抱怨说:“如果那一天系统不出问题,订单量肯定会创新高。”
2018 年 915 事故官方公开信
经历了大小数以百计的事故后,从 82 原则上看,我发现 20% 是因为人员能力和机制流程的欠缺,80% 则是因为人员的稳定性意识不足,并且故障应对方法不当。而作为技术 Leader 的你,如何认识稳定性、如何应对故障、如何从过往的事故中汲取足够的经验,就成为一个团队能否做好稳定性的关键。
一般来讲,通过统计系统不可用的时长或次数就可以对稳定性进行量化,比如业内常说 4 个 9 的可用性(即 1 年内 99.99% 的时间系统是可用的,不可用时长仅为 52.6 分钟)。
在饿了么和阿里,每个财年我们会确定稳定性 KPI,以事故数的计量为准,结合团队情况和过往结果背负不同数量的事故指标。事故按照影响程度的不同会划分为几级,不同级别的事故数指标也不同。所以针对稳定性的提高也可以看作围绕事故的治理,可以从事故发生的前、中、后分阶段来看对应的关键点。
事故的类型:可用性事故、资损类事故。
事故前预防:主动治理减少系统的风险隐患,重点在变更管控、可用性设计、应急预案与演练。
事故中应急:“止血、恢复”是原则。
事故后复盘:目的不是追责,查根因、改进架构、完善应急、总结经验才是我们想要的。
这一讲,我们来了解一下故障的应急与事故的复盘(预防治理我会在下面两讲分不同事故类型来详细讲解),因为事故的发生要结合具体的上下文背景、系统架构、甚至组织结构来看,并非千篇一律。
希望今天的内容能帮你更深刻地理解稳定性的价值,并结合实际工作更加有条不紊地应对线上故障、有价值地进行事故的复盘总结。
从事故特性上看,我们可以分为可用性事故和资损类事故。
可用性事故:技术原因导致系统部分或者全部功能不可用,业务没办法正常完成对应流程或者提供对应服务。比如因为网络、DB、接口 Bug 等原因,用户没办法登录、商品列表不显示等。
资损类事故: 系统的功能都能正常使用,但因为逻辑、计算等原因让业务的某一方产生了资金损失。比如用户支付一律为 0 元、错发 999 无门槛优惠券、商户清结算少打款给商户等等。
那么它们的区别是什么呢?
可用性事故的根因大多在技术本身,包括但不限于: DB 设计、接口实现、链路架构、上下游的依赖、中间件的实现等原因,特点是发现容易、杜绝难、业务影响明显、对应急处理速度要求高。
而资损类事故更多和隐蔽的业务逻辑和架构设计的缺陷有关,可能还涉及产品逻辑或业务错配,特点是非常隐蔽、难发现、往往持续时间长、防控成本高、大部分开发同学意识薄弱。
因为这样的特性差异,两类事故在预防治理的思路和方法上有一定区别,但在故障的应急和事故复盘上,思路相对一致。那么当故障发生时,你要发挥什么作用呢?
事故现场往往伴随着“混乱”,试想一下,你团队的小伙伴昨晚刚发布上线了新系统,今天上午一切正常,下午 App 核心页面突然无法显示、客服反馈说大量用户来电投诉,可谁都说不清楚到底是怎么回事,十几分钟过去了,系统依然没有恢复,类似的场景你是否经历过?
那么这时,你应该起到“定海神针”的作用,故障发生时控场就是你的核心职责。 要有条不紊地安排同学进行排障、确定信息沟通的秩序、结合信息做好线上同步,并参与决策。
在阿里,故障的处理有一个“ 1-5-10 ”的标准,即 1 分钟发现、5 分钟响应、10 分钟恢复。很明显,故障处理的核心在于“快”,让业务最快止血、恢复、避免影响进一步扩大。
故障处理的生命周期,可以分为 4 个阶段:发现异常、排查问题、判断决策、恢复处理。这 4 个阶段对应的行动并不是完全串行的,虽然有一定的依赖关系,但在实际的处理过程中应该并行展开。类似 fork/join 的模式,不断完成小任务、不断汇总信息,不断做出判断与决策,形成循环直到故障恢复。
接下来,我以外卖点餐的业务为例,讲一下故障的发现、排查、决策与恢复都要注意哪些核心要点,因为故障处理的核心原则相同,所以这些要点在其他业务场景中也适用。(时序图与真实系统间我做了一些模糊处理,但是不影响案例说明。)
我们要点外卖的话,大体的流程是这样的:
用户打开 App,根据用户 LBS 显示餐厅列表,选择进入某一家餐厅;
添加菜品到购物车,进入结算页确定收货人、优惠红包、订单金额,生成订单;
跳转第三方支付,并返回支付结果;
商家接收订单推送,操作接单并备货;
骑手根据调度取餐,送达用户,订单完成。
用户来电反馈订单无法支付、App 无法登录,研发发现下单 QPS 曲线同比下跌,这些都是事故发生时的现象,虽然现象不完全等于故障点,但通常最早出现异常现象的地方和故障根因关联最大,所以第一时间发现异常对于锁定问题至关重要。
故障发现就是系统异常反馈到研发的过程,这里我画了一个简单的脑图,分类说明故障发现的几种常见方式:
开发同学往往更关注技术类指标,比如 QPS、CPU LOAD,可 Leader 除此之外应该更多地从业务场景出发,结合需求来看系统的业务监控覆盖是否完全。业务监控往往更加敏锐,但是要想用好,就需要对业务和系统有较长链路的理解和掌握,而这恰恰是技术 Leader 的优势。
比如用户进入餐厅后会添加菜品到购物车,并跳转到结算页完成下单。菜品服务会提供一个查询接口,根据餐厅 ID 返回菜品信息。假设这个查询接口最近做了变更,在库存逻辑的处理中埋下了一个 Bug,导致实际库存小于 50 时,库存的返回值被默认为 0,而其他数据则一切正常。
那么此时类似 CPU、内存、I/O 等技术指标可能都不会异常。而因为是部分实际库存小于 50 的菜品被影响,用户依然可以添加其他菜品到购物车,但因为部分菜品库存为 0,用户想吃却没办法下单,那么这个时候订单成交量的环比、同比曲线就有可能下跌,而这个现象会让我们感知到异常,进而排查问题处理。
总的来说,人工的被动反馈在时间和速度上有较强的不确定性,很容易出现“小故障 * 长时间 = 大事故”的情形。而纯粹的技术指标监控又会忽略掉接口正常响应,但是业务异常的场景,只有两者结合,通过监控告警,最大程度上缩短故障感知的时间,才能早发现早解决,减少业务影响。
发现异常,接下来就是排查故障点和故障原因,故障排查最直接有效的核心思路就是直接锁定 + 排除。
直接锁定:最近的变更点与异常现象间有直接的逻辑关联,进而可以直接锁定到故障点。比如,刚对下单接口进行了发布变更,接口的 QPS 曲线就暴跌,可以基本断定是刚才的发布导致。
排除法:当干扰因素过多(用户、订单等几个系统同时发生变更,引起订单下跌),很难直接锁定到故障点,就要结合业务场景,让整条架构链路上的所有关联方进行自查自证,通过排除法锁定故障。
这里你要注意的是,要敢于先怀疑、排查自己的系统,再去考虑上下游关联方的问题,为的就是在信息混乱的现场,减少信息的不确定性,以身作则,带领团队成员将范围缩小,针对性地找到问题。
如果你负责的是优惠券相关的系统,在下单的核心路径上,主要的场景就是优惠券领取、发放、展示、核销。你即使不是全部熟悉,也应该与团队同学共同协同,逐个确认这几个场景的核心接口是否有异常,通过对应的监控、日志收集信息并找问题,如果某一处没有发现问题,就排除并继续循环。
如果还是没办法确定问题,或者只能确定大致范围,就要充分利用之前的事故经验了,此时一定要果断,可以结合情况启用标准应急手段(比如服务重启、发布回滚、非关键链路降级)。总的来说,在排障的过程中,如果团队成员都没有头绪,你一定要起到主导作用,可以参考我总结的一些要点做好“控场”。
故障排查三要点
既然故障的表现是业务功能有损,那么在故障决策时为了让业务最快止血和恢复,就无法追求完美,一些为了抢时间的有损决策,就需要 CaseByCase 的人为处理。
比如平台要搞一个 517 红包雨的活动 ,但是红包系统逻辑错误,导致满 50-10 的红包发放成满 10-50,此时已发的红包要作废吗 ?不作废有大额资损,作废会导致大量客诉。类似红包错配的场景,业务决策非常复杂,能否第一时间止损很大程度上取决于技术 Leader 的现场反应和操作, 要注意故障决策的两个关键点 :
一定要有明确的决策人、主导者和有效的沟通方式(钉钉群、多人电话会议、紧急作战会议室等),让信息可以通畅地交流出来,并且决策人可以根据情况做判断与取舍,形成所有人明确的处理结论。 比如,第一时间停止错误红包的发放,确保故障没有增量,并把决策第一时间同步给团队成员,并同步相关负责人后续的动作,对已发放的红包,明确要求负责人汇总各类关键信息(红包数量、涉及金额、涉及用户数、有效时长、可能资损等)。
所有的信息一定要数据化,不同的数据量级会导致决策不同,比如红包错发 50W 可能只是暂停发放,但是存量红包依然可以核销,损失公司可以承担。但是如果错发 5000W,大概就要涉及一系列的调整,这是非常影响决策的。
往往业务决策后就需要执行相应的技术操作,最好的情况当然是在系统设计时就准备了预案,那么此时可以安全且快速地执行,并且对不涉及业务决策的问题可以技术直接操作,节省时间,比如常见的应急“三板斧”:变更回滚、服务重启、降级&限流。
而如果没有预案或情况比较复杂,就涉及线上Fix,比如因代码不兼容所以无法回滚,或者故障导致脏数据进而影响正常的业务流程推进,又或者红包金额错误需要做数据订正。你在这个环节要额外注意, 因为一来这种操作相当于一次“紧急变更”,有可能引入新的风险,二来不同的实现 Fix 成本和用时可能不同,Leader 需要给出自己的判断。
比如刚刚提到的红包错配、错发的问题,假设影响金额过大,公司决定对存量红包作废止损,那么站在技术角度有很多方法,你需要让团队成员明确使用哪种方式:
下单环节,在“我的优惠券”中通过前端隐藏对应的红包,让用户无法选择 ;
根据红包批次 ID 或者类型,通过脚本刷数,将红包批量作废 ;
在下单接口的校验环节,增加逻辑判断,禁止这批红包核销 ;
通过风控系统拦截使用这类红包的订单。
技术 Leader 要考虑不同恢复手段引入的新风险、操作用时、用户体验影响的不同,结合当前紧急程度、系统、具体操作人的情况,给出一个技术方面确定的判断。类似的问题,如果完全没有预案,我们之前常见的做法还是不动线上系统以免引入新问题,主要通过刷数据解决。
故障恢复时 Leader 的关注点
讲到这儿,你是不是觉得处理完事故就万事大吉了呢?并不是,你还要对这次事故做一个全面彻底的复盘,不让类似的问题重复发生,那么复盘都要注意哪些关键点呢?
复盘的核心不是为了追责或者甩锅,而是最大程度榨干事故的剩余价值,通过全盘的思考与总结,来看看系统设计、流程机制、应急处理、人员安排等各方面有哪些不足,哪些可以提升的地方,哪些问题是共性的,需要在各团队进行“大扫除”。
通过一次事故,解决一类问题,让一个人(团队)踩过的坑变成所有人踩过的坑,正所谓“一次学费,受益终身”。
你可以从时长、现象、处理时间轴、根因、改进计划这几个维度进行复盘, 在以下几个方面进行深究:
事故时长:1-5-10 是否达成,如果没有是为什么?哪个环节用时最多,如何提高和改善?
事故根因:根因不等于直接原因,一个事故的直接原因往往并不复杂,但是根因可能是多个维度的缺失,需要像剥洋葱一样一层层找下去。拿库存接口变更这个Case来说,直接原因就是某段代码逻辑变更导致,但是应该在测试、发布、监控、应急影响、预案设计等多个环节展开去看,根因的挖掘并不忌讳“吹毛求疵”。
事故改进措施:由点推到面、明确到人、明确时间。与根因类似,要结合多个维度形成组合拳的改进点,避免一次性动作,要将重点放在对未来、对同类问题的预防上。核心就是如果再一次发生类似的问题,这些改进措施是不是能起到作用。
关于事后复盘,你可以这样理解,我们要深挖事故如何发生的、如何处理的、未来怎么预防。但要避免情绪化,在复盘会上的反思、感悟、懊恼没有任何意义,如何带领团队把精力放在改进措施的落实以及事故前的治理上更有价值, 另外,你需要留出时间让团队伙伴进行内部的 Review,避免为了开会而复盘。
虽然你会尽全力保障系统的稳定性,但是按照墨菲定律来说故障又一定会发生,这就形成了一个悖论,即不管你怎么努力还是会出问题,所以我一直强调:“稳定性是一个先有意识后有能力的事儿”,这一点尤为重要,毕竟你的态度和认识决定了团队的重视程度。 这一讲我想强调这样几个重点:
毫不夸张地说,系统稳定性对于研发而言一条生死线,这方面做得不好,其他再好也是枉然,因为稳定性问题“下岗”被优化的 Leader 不在少数。
对于故障的应急响应,业务的止损与恢复是最重要的,决断就是要付出一些代价的。
事故的复盘不是为了追责过去,而是为了在未来避免类似的情况发生。
业务快速发展的同时,技术必然存在妥协。 业务上需要快速的需求交付,技术上需要架构的可扩展,但速度和质量在工程领域总是存在冲突,而稳定性往往就是问题爆发的冲突点。作为技术 Leader,你要平衡好这两种诉求,让技术与业务协调发展的同时,最大程度确保系统的稳定运行,毕竟“没有质量的交付,再多再快都毫无意义”。
留个作业: 把最近半年或一年你印象最深刻的事故重新复盘一遍吧,从事故根因、应急处理以及复盘改进几个角度去 Review,未来类似的事故是否还会发生,如果发生你能更好的应对吗?
最后,感谢你的阅读,如果这节课让你有收获,欢迎你将它分享给其他的朋友,我们下一讲见。
复盘,最大程度压榨事故的剩余价值。这个深有体会,不应该变为追责会,而是需要转换为分析会,对架构策略处理等各方面进行分析总结,而不能是问责会。
是的,会上问责只会把有价值的复盘会转化为无意义的甩锅会
总结一下,这一课主要是系统高可用之 应急策略整理并输出一套适合自己业务场景的SOP,提供部门新人以及其他同学参考
应急策略适用在很多需要紧急处理和决策的场景,可以根据自己的团队与业务情况做计划,首先确保骨干都能掌握,毕竟不是每个人都有这种处理能力。
假如事故原因分析下来是由于人为的问题如个别员工粗心、能力不足等,那是否要从制度方面来解决?
如果真的是“人为问题”和“个别员工粗心或能力”这么强的限定条件,我建议优先解决制造问题的人,制度是应该有,但不应该是“服务于个别人的”。
1-5-10里大家都是如何实现1分钟内发现故障的
只能靠监控告警,人工是几乎不可能的,监控本身有很多个纬度,具体可以参考文章里的脑图。
开阔视野了,业务指标和技术指标结合了
老师好,围绕于稳定性建设有两个问题。1.每个case如何定级呢?这个基线应该怎么来,每个业务的特点有所不同。2.如何将稳定性建设变得可复制,在大的团队方向上复制呢?是通过wiki,工具,标准,流程的建立吗?
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/480748
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。