面试官:如何构建一个高可用的系统?(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)恢复环境,将生产环境恢复环境到正常状态,并由测试和运维同学进行逐一检查,包括:硬件、服务、业务主流程等。这一步尤为关键,如果因为故障演练而带来故障,那就贻笑大方了。

结语

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

相关推荐
颜淡慕潇38 分钟前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决
尘浮生2 小时前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
尚学教辅学习资料2 小时前
基于SpringBoot的医药管理系统+LW示例参考
java·spring boot·后端·java毕业设计·医药管理
monkey_meng3 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马3 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng3 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
W Y3 小时前
【架构-37】Spark和Flink
架构·flink·spark
Gemini19953 小时前
分布式和微服务的区别
分布式·微服务·架构
阑梦清川3 小时前
在鱼皮的模拟面试里面学习有感
学习·面试·职场和发展
paopaokaka_luck7 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计