事故第一线
2024-08-20一个稀疏平常的日子,基于业务的要求,开发人员对已上线的新计费模型,进行配置修改,支持新计费模型流量的开启。
事故时间线
- 2024-08-20 14:47 开发人员进行计费的配置变更修改。
- 2024-08-20 14:48 开发人员发现线上出现费用预估失败,进行配置还原。
- 2024-08-20 14:49 运维人员发现业务指标下降,拉齐核心人员来应急处理。
- 2024-08-20 14:50 DBA排查发现计费数据库CPU被打满。
- 2024-08-20 14:51 DBA开始中断慢SQL,并对关键慢SQL进行限流。
- 2024-08-20 14:56 DBA尝试重启数据库。
- 2024-08-20 15:02 数据库重启成功,业务指标有所恢复。
- 2024-08-20 15:05 数据库CPU又被打满。
- 2024-08-20 15:15 开始业务限流。
- 2024-08-20 15:40 业务整体恢复正常。
- 2024-08-20 15:45 开始进行数据修复。
事故影响
事故影响范围:
- 影响时长:约60分钟
- 影响完成订单量: 约10万订单
- 影响流水收益: 约200万
事故根因
由于配置变更,切换计费模型,影响系统崩溃的根因:
- 计费模型变更后,数据库索引发生了变化。
- 原计费模型查询费用的条件变量,数据库都建立了索引;新计费模型查询费用的条件变量,数据库没有建立索引。
- 由于新计费模型缺少数据库索引,从而导致数据库查询效率变低,出现大量慢SQL,数据库CPU被打满。
- 计费模型变更后,Redis缓存的key发生了变化。
- 计费模型变更后,由于Redis缓存无法命中,流量全部穿透打到数据库,导致数据库压力瞬间增大。
事故责任
- 这个责任很明确,主要责任肯定是计费团队。计费团队的设计、开发、测试都有一定的责任,数据库索引和流量穿透这种常见的问题都没有识别到。
- 数据库团队要承担次要责任,因为开发人员其实很快就发现了问题,并进行了操作回滚。但是,数据库由于前面的流量击穿,导致事故时长延迟到了1个小时。
改进措施
| 待改进点 | 改进措施 | 责任人 | 时间点 | 备注 |
|---|---|---|---|---|
| 计费团队由于未识别到技术风险,导致问题被触发 | 开发:对计费工程中所有涉及流量穿透的场景进行排查整改。 测试: 对计费过程所有涉及到稳定性风险的场景,重新进行集成验证。 | 计费团队负责人 | 2024-12-30 | 技术上稳定性场景的整体排查 |
| DBA团队由于数据库紧急恢复措施不足,导致问题处理延迟 | 对数据库CPU打满场景进行破坏性验证,确保下次出现问题能够控制在10分钟内恢复 | DBA团队负责人 | 2024-12-30 | 应急流程的处理措施 |
事故复盘的意义
最近工作的2-3年,我在一线最核心的业务上来带领团队。一次大的事故对于一个团队来说,就像是一次赌博,一把就会输掉了整个团队一年辛苦付出的心血。
虽然这个事件非常严重,甚至对于员工的好几年绩效都会造成影响,但是事故好像总是在所难免,也没有任何一个技术团队敢保证绝不犯错。
那么对事故进行劳心劳力复盘的意义又是什么?
- 识别问题根源:帮助团队深入了解问题的本质,找出bug产生的真正原因,而不仅仅是表面现象。
- 改进流程: 识别开发、测试、发布流程中的不足之处,进而优化流程,减少未来同类问题的发生。
- 提升团队能力: 复盘过程中的讨论和分析可以提高团队成员对问题解决能力的认识,增强团队协作和沟通。
- 增强责任感: 每个成员都可以清楚地看到自己在问题中的角色和责任,这有助于培养成员的责任感。
- 风险管理:复盘有助于识别潜在风险,使团队能够更好地进行风险评估和管理。
事故复盘的方法
确定复盘的目标
问题复盘的内容涵盖事实、分析、定责和改进4 个部分,一次成功的问题复盘需要达成以下 4 个目标:
- 讲清楚事实:事实是复盘的基础,如果连事实都没有讲清楚就开始分析、定责和改进,无异于搭建空中楼阁,做得再漂亮也是没有意义的。
- 全面且深入地分析:首先需要保证没有遗漏问题,其次需要深入分析问题根因,否则以后问题还是会以其他方式反复出现。
- 得出让各方心服口服的定责结论:需要有明确的定责标准,避免拍脑袋定责,或者按照级别和关系来定责。
- 制定可以落地的改进措施:避免提出一些虚头巴脑的措施,看起来高大上,实际上却不知道怎么落地,后续也无法跟踪。
我们可以通过时间线、问题链、责任链和改进线这 4 条不同的线索来展开复盘,从而实现事实、分析、定责和改进这 4 个部分的目标。
时间线
为了讲清楚事实,我们要明确时间线,也就是问题发生的经过,包括问题发现、问题处理过程中采取的各种关键措施、问题恢复的时间和问题影响的结果等。
这个时间信息非常关键,因为它能够反映出问题发现速度、各项措施执行时间和团队响应效率等指标。
问题链
通常情况下,一个问题往往不是单一原因导致的,而是多个原因“碰巧”组合在一起所导致的,所以分析整个问题的传导路径,才能全面地了解产生问题的过程。
同时,针对单个问题的分析也不能浅尝辄止,而应该采用“5W 根因分析法”深入分析,找到根本原因,这样才能为后续制定改进措施提供有效的指导。
问题链的路径逻辑有两类:业务流程和项目流程。
- 业务流程是指,端到端的业务处理的过程,分析的对象是各个关联的系统。
- 项目流程是指,端到端的项目开发的过程,分析的对象是项目各个阶段相关的人员,比如开发、测试、产品和运维等。
责任链
定责是问题复盘中最棘手的部分,因为定责的结果会直接影响团队和个人的绩效,所以做到公平公正、让各方都心服口服是一项很大的挑战。
通常情况下,制定明确的定责标准有利于尽量减少争议,常见的标准包括以下 4 条:
- 违反公司规章 / 制度 / 流程的承担主责:比如公司规定必须要有灰度策略才能升级,某业务版本直接全量升级导致发生问题。
- 出现重大纰漏的承担主责:比如测试时漏测了某个常见的业务场景,导致上线后发生问题,测试承担主责,产品承担主责(因为上线前验收阶段没有发现问题),开发反而不一定承担责任(看具体的公司和团队要求)。
- 问题源头承担主责:比如 A 系统磁盘故障导致接口响应很慢且问题持续很长时间,从而进一步导致 B 系统对外响应也超时,这种情况下 A 系统应该承担主责,B 系统承担次责。
- 问题放大者承担主责:比如 A 系统磁盘故障导致接口响应很慢但只持续了几分钟,结果诱发了 B 系统的设计缺陷,导致 B 系统瘫痪超过 1 小时,这种情况下 B 系统应该承担主责。
对于研发团队庞大的公司,这个责任链确实要细化和明确,各个相关方定责了就是要承担相关的责任。尤其,涉及到一些重大的事故,一旦确定了责任人,可能对其收入和职业发展都有一定的影响。
对于一般中小型公司,这个责任链反而更简化,开发团队负责的业务范畴出了问题,都是开发人员承担主要职责,其它相关方都是次要责任。
改进线
为了制定可以落地的改进措施,我们要明确改进计划。
改进计划的思路来源于两个方面:时间线和问题链,通过时间线找到问题处理过程中不合理和可以优化的地方;通过问题链找到具体需要解决的问题。
具体措施可以是流程上的调整(增加或删除流程步骤),技术上的手段(增加功能、优化系统)和团队方面的措施(学习、培训、奖惩机制)等。无论采取什么措施,都要求能够落地执行。
事故对当事人的价值
每次事故对当事人来说,都是沉重的打击,尤其在事故发生到复盘的整个过程,更多的都是反思和痛定思痛。整个复盘的过程,也不会基于当事人的视角来回溯这件事情。
那么一次事故,除了让公司和个人都付出了代价,那么对当事人还有什么其它价值吗?
- 开发人员会对系统的稳定性更加重视。系统的稳定性虽然非常重要,但是如果不发生在自己身上,在其心中的警觉性总会差一根玹。这也是为什么失败比成功,更能够让人警醒。
- 当事人要通过复盘,明确好自己和他人的职责,从而更加了解自己工作的边界,为以后的良好合作,梳理清晰彼此的职责。
未来还很漫长,一次事故虽然对当事人当前会造成不好的影响,但是我们一定也要从中学会更多的经验和教训,这样才能让自己未来的职场之路,走得更持久、更健康。