面试官:如何构建一个高可用的系统?(2)

前文《面试官:如何构建一个高可用的系统?》,我们讲了从"减少故障次数"的角度,进行高可用系统的构建。

讲正文之前,我们先把"故障时长"的组成部分,进行一下拆解,以便于更好地制定优化策略。

总故障时长 = 故障发现时长 + 故障定位时长 + 故障解决时长

听行业内的一个资深架构师说,衡量一个研发团队的专业度,可以从"系统故障是由业务团队先行发现,然后再通知研发团队的",还是"系统故障是由研发团队通过技术机制自行发现的",这个角度去进行判断。

我觉得这个说法非常有道理,自己工作职责的一亩三分地,出了故障还浑然不知,等着其他团队发现后进行告知,这样也太说不过去了。

当然,另外一个角度就是,如果等到其他团队发现故障后进行告知,那也就意味着故障已经持续好一阵子了,"故障发现时长"也已经不短了。

而从"故障定位"和"故障解决"上,不但可以看出研发团队的专业性,还可以看出这个研发团队是否训练有素。

训练有素的团队:出了故障后,团队核心成员迅速聚集,完成信息对齐、方案制定和人员分工后,团队成员紧张有序地执行各自的任务。

散兵游勇的团队:出了故障后,团队成员慌作一团且一脸懵逼,然后大家你一言我一语地开始猜盲盒模式,"可能是xx的问题"、"没准是xxx影响的",接下来开启小白鼠实验模式,"重启一下试试"、"回滚一下试试"、"要不先把xxx定时任务停了"之声不绝于耳。

接下来我们正式讲,从"降低故障时长"的角度,有哪些保证系统高可用的策略。

添加图片注释,不超过 140 字(可选)

监控告警

监控告警是针对于"故障发现" + "故障定位"的。

监控

系统监控可以分为三层:基础监控、服务监控和业务监控。

添加图片注释,不超过 140 字(可选)

其中,Prometheus + EFK + SkyWalking号称监控三件套,分别对应指标度量、日志分析和链路追踪,而Grafana则负责对Prometheus的指标数据进行可视化。

Prometheus + Grafana的作用是,采集硬件和服务各个维度的指标数据,帮助研发人员获知和监控其运行情况,当出现指标异常的情况时,以报警的方式通知研发人员。

EFK是Elasticsearch + FileBeat + Kibana的缩写,可以帮助研发人员采集、管理和分析分布式应用程序的业务日志,旨在快速排查并解决程序级问题。

SkyWalking的作用是,对分布式应用程序进行链路追踪,性能指标分析和服务依赖分析。

告警

一直以来,告警存在两大痛点:

  1. 告警疏漏,在系统出现故障的时候,工程师并没有收到通知。
  2. 无效告警过多,工程师被过度打扰后变得麻木,反而错过了有效的告警。

前者我们不进行过多解释了,无非就是一个细心活儿而已,但对于后者,我们则需要进行告警降噪。

(1)告警需要合理分级

添加图片注释,不超过 140 字(可选)

简而言之,影响用户和收入的,需要电话通知并立即进行处理,其他的都可以暂缓。

换句话说,那种拿着几条系统告警,动不动就上纲上线、家国情怀、道德绑架的研发负责人或产品经理,还是让他们洗洗睡吧。

(2)告警需要控制范围

我见过最极端的情况是,运维同学配置的告警规则是,任何一个服务发生问题,就把整个研发团队的所有人都进行告警通知,而并不对服务的负责人进行区分。

我们还是需要专人专事的,哪怕你给服务的依赖方发送告警也可以,但直接一刀切是有问题的。

(3)告警需要控制数量

短时间内的重复告警,需要限制最大次数和发送频率;短时间内的非重复告警,需要具备聚合发送的功能。

上线规范

80%的故障都是由于发布上线导致的,上线规范旨在可跳过"故障定位"环节,快速解决由本次上线而导致的系统故障。

其关键点在于,针对每次上线发布的"回滚方案"。

就像我们开车时的防御性驾驶一样,必须要有"主动安全"的思想,用来预见并应对其他驾驶员、行人、不良天气或路况所引发的危险。

我们也必须"主动安全"地进行系统发布上线,重视每次上线发布所对应的"回滚方案"。

80%以上的回滚方案都是简单的,无非是代码回滚到上一个版本,涉及到库表变更的会麻烦一些,比如:

(1)本次发布上线中,在某张表中新增了一个字段,且该字段不允许为空,也没有设置默认值。这时如果代码回滚了,同时需要将该字段改为允许为空。

(2)本次发布上线中,在课程表中新增了一条"数学课"的数据记录,当代码回滚的时候,该属性表中这条新增的记录是否也要删除,这个就需要case by case进行分析了。

如果不删的话,有可能对应"数学课"的代码逻辑(比如:价格优惠)已经回滚了,如果删了的话,上线后回滚前产生的业务数据,有可能就关联不到"数学课"的数据记录了。

除此之外,如果涉及到横跨公司多个项目组的大版本迭代上线,或是短期内进行了多次的迭代上线,这种情况如果进行回滚的话,需要制定比"代码回滚和数据库回滚"更加复杂的策略。

比如:再发一版的Hotfix,或是通过配置中心切换代码执行分支等。

添加图片注释,不超过 140 字(可选)

无脑预案

无脑预案,是针对于"故障定位"和"故障解决"的。

当系统发生故障时,团队成员可能会出现脑子一片空白,很难迅速做出合理反应的情况。而衡量一份应急预案的好坏,关键看其是否足够"无脑化"。

即:在整个过程中,只需要按照应急预案中的步骤执行,而不需要进行思考。因为思考就会产生选择,而选择取舍是最耗费时间的事情。

如果做不到这点,那么证明应急预案还有优化的空间。

举例如下:

添加图片注释,不超过 140 字(可选)

BTW:上图仅仅是举个例子,真实场景中,对于数据库服务器的CPU使用率100%的处理分支,要复杂很多。

无脑预案并不是一蹴而就的事情,需要随着业务迭代和架构演进,不断地进行更新迭代。

当然,不断地更新迭代并不等于持续网上累加,从熵减的角度来说,也需要不断做减法,该废弃的废弃,该合并的合并。如果无脑预案只增不减的话,那么几年以后,就会变成一本厚书。

另外,无脑预案的另一个作用是"去单点化"。

因为团队成员中的每个人,都把自己处理系统故障的经验共享出来,沉淀在了这份无脑预案中。那就意味着,每个团队成员都可以处理预案中任何场景的问题。

故障演练

故障演练,旨在模拟生产环境中可能出现的故障,测试系统或应用在面对故障时的反应和响应能力,也是针对于"故障定位"和"故障解决"方向的。

上文我们讲了"无脑预案",但仅仅这样是不够的,故障演练的目的有两个:

(1)对"无脑预案"中的执行步骤进行验证,保证其在当前的系统版本中是正常生效的。

(2)把"无脑预案"中的执行步骤熟练化、标准化,如:整体执行时间从半个小时缩短到五分钟,从仅团队核心员工到团队中的任何员工都可以执行完成。

添加图片注释,不超过 140 字(可选)

这里解释几个关键点:

(1)故障注入,使用已准备好的故障注入工具,根据演练计划,进行不同故障场景模拟,以随机盲盒模拟的方式最好。

(2)故障反应,根据面临的故障现象,与"无脑预案"中的条例进行匹配,找出对应的处理方式。这一步的核心点在于"判断"。

(3)故障响应,按照"无脑预案"中的处理步骤进行一一落地,直到完成整个故障解决流程。这一步的核心点在于"执行"。

(4)清理现场,清理故障演练所带来的脏数据,这一步的核心点在于"数据的可回溯性"。

(5)恢复环境,将生产环境恢复环境到正常状态,并由测试和运维同学进行逐一检查,包括:硬件、服务、业务主流程等。这一步尤为关键,如果因为故障演练而带来故障,那就贻笑大方了。

结语

构建高可用系统的三部曲,目前已经完成了两部,"减少故障次数"和"降低故障时长",而最能衡量出一名资深研发工程师,是否具备大中型系统的架构能力,主要是看第三步"缩小故障范围"中的"链路拆分"。

相关推荐
似璟如你6 分钟前
Java开发八股文之基础篇+spring+集合
java·开发语言·面试
brzhang7 分钟前
别再梭哈 Curosr 了!这 AI 神器直接把需求、架构、任务一条龙全干了!
前端·后端·架构
安妮的心动录21 分钟前
安妮的2025 Q2 Review
后端·程序员
程序员爱钓鱼21 分钟前
Go语言数组排序(冒泡排序法)—— 用最直观的方式掌握排序算法
后端·google·go
然我25 分钟前
路由还能这么玩?从懒加载到路由守卫,手把手带你解锁 React Router 进阶技巧
前端·react.js·面试
Victor3561 小时前
MySQL(140)如何解决外键约束冲突?
后端
Victor3561 小时前
MySQL(139)如何处理MySQL字符编码问题?
后端
云和数据.ChenGuang2 小时前
gitlab-ci.yml
面试·职场和发展·gitee·运维面试题·运维技术总结
007php0072 小时前
服务器上PHP环境安装与更新版本和扩展(安装PHP、Nginx、Redis、Swoole和OPcache)
运维·服务器·后端·nginx·golang·测试用例·php