写点什么

系统设计 - 高可用思想简介

作者:三叶草
  • 2022 年 9 月 13 日
    贵州
  • 本文字数:2712 字

    阅读完需:约 9 分钟

一、如何衡量高可用

软件系统在运行过程中,会出现各种各样问题,如何确保系统出问题时,不对客户业务产生影响。业界提出了 SLA 的定量的指标,即服务提供商和客户约定,全年服务的可用性要达到多少分钟。提出 SLA 主要也是给客户信心,同时约束服务厂商提供更可靠的服务;


例如:服务提供商对外承诺 5 个 9(即 99.999%),那全年服务失效时间最大为 365*24*60*0.001%=5.26min,也就是说服务最多允许 5.26 分钟的不可用时间,超过了这个时间的话,可能就涉及对客户赔偿了。

SLA:服务等级协议(简称:SLA,全称:service level agreement)。是在一定开销下为保障服务的性能和可用性,服务提供商与用户间定义的一种双方认可的协定。通常这个开销是驱动提供服务质量的主要因素;

二、高可用的价值

  • 用户价值

  • 用户更放心

毫无疑问,世界上几乎没有不会产生 bug 的软件;那用户在使用软件之前其实心里就会默认这个系统会出 bug,而 5 个 9 以上的 SLA 可用性承诺,能最大程度的减少用户的顾虑

  • 带来最直接的经济价值

每年大家会发现,新闻报道出来某某某云服务中断半小时,上云的客户业务中断半小时,导致直接受损利益千万级别;如果能保证全年的可用性,那客户也就不会由于突然的软件系统失效,导致经济受损

  • 服务质量的好评

这个标准是很灰度的,平时不出问题,大家可能不会喷客户服务;一旦客户服务出问题,可能瞬间就在网上发酵,某某软件烂的惨不忍睹等等

  • 自身价值

  • 全局的系统视野

要想达到 5 个 9 的可用性,需要针对系统中所有的组件进行高可用改造优化,同时需要考虑周边依赖服务的高可用性,一旦有个组件不可用了,如何快速发现并隔离故障,除此之外,还要考虑整体的性能,包括计算资源、网络资源、存储资源等,如果保证可用的基础前提性,尽可能的高性能;这些东西做完后,会发现对技术人员统筹全局的思维大有帮助

  • 减少不必要的 oncall 工作安排

达到 5 个 9 以上的系统,运维自动化做的都很好,包括监控、告警、自恢复、故障应急资料之类的;一般情况下,是不需要很多 oncall 在值守运维工作了

  • 生活质量提升

系统高可用,那大家精力就可以从无止境的修 bug 中,转移到设计更好的软件特性上,确保软件更高的高可用以及性能,实现良性循环,然后就能早点下班了

  • 附加的一些意向不到的收获

专利、论文等

为了达到 99.999%的高可用,总有一些黑科技被引入,这些黑科技如果业界没有人想到的话,就可以转换成专利或者发表论文了

三、高可用的设计思想

1、设计思路

一般从我的经验来说,设计一个系统可用性框架,有三个思路:

  • 正向端到端分析系统的数据流向,然后分析数据经过的所有组件的可用性,针对不可靠的组件,进行改造

  • 参考业界优秀的大型系统的设计理念(比方说可以看操作设计、k8s 或友商等),横向对比一下,业界已经做了哪些能力,我们的差距在哪里

  • 现网 bug 回溯改进,进行举一反三,层层迭代,优化系统可用性

2、常见的故障场景

通常,在正向端到端分析系统可用性的时候,重点会考虑如下的故障场景

  • 网络问题

  • 网络连接异常

  • 网络带宽超时拥塞

  • 性能问题

  • cpu 高

  • 内存高

  • 硬盘空间快满了

  • 中间件负载太高(数据库、redis、kafka、etcd 等)

  • 安全问题

  • 异常客户大批量请求攻击

  • 网络攻击

  • 运维问题

  • 监控问题

  • 平滑升级问题

  • 硬件问题

  • 硬盘损坏

  • 机房掉电

  • 网卡出问题

  • 周边依赖管理问题

  • 周边依赖服务宕掉,不可用了

  • 周边服务超时了

  • ......

3、方法论

为了防御形形色色的故障,保障系统的高可用性,一般会从如下几个方法进行设计系统

  • 高可靠架构

  • 对系统组件进行容灾架构部署,防止单系统失效,服务整体不可用

  • 集群的使用方式,可以是主备、集群模式,或者自治的单个系统,具体选型,看业务需要

  • 集群的机房最好跨机房、跨地域,鸡蛋不要放到一个篮子里面,最大程度减少单点故障

  • 缓存

  • 针对周边服务的依赖,可以通过缓存进行解耦,当周边服务出问题后,可以通过缓存延缓系统失效时间,给周边服务的修复预留一段时间

  • 针对中间件的访问,可以通过缓存加速访问,提升性能

  • 缓存的话,通常可以使用二级缓存,中间件缓存+本地内存的缓存

  • 过载保护

大型的系统,一般都绕不开过载问题,而常见的现网故障有很大一部分,也是由于过载引发的系统瘫痪,导致用户使用收到影响,如何设计好对过载的防护,是个很重要的工作。主要包含如下几个部分:

  • 过载发现

  • 监控系统的构建,明确监控哪些指标,至关重要,根据自己系统的特性,设计关键的指标

  • 实时流量

  • 系统 cpu、内存指标

  • 系统处理时延

  • ......

  • 过载保护

  • 流控

流控可以分为多个维度,比如系统总体的承载能力是多少,每个用户的流控是多少,每个 api 的流控是多少等,按需选用最合适自己业务的

  • 降级

当系统万一出现问题时,是不是可以考虑降低用户执行速度,确保用户业务最终执行成功;有限保证 vip 客户,在保证普通客户;有限执行核心业务,在执行非核心业务等等,具体选型的话,也是看系统所面向的用户业务具体是什么样的

  • 熔断

  • 这个基本上是迫不得已的手段,走到熔断这里,一般情况下是系统可能由于某一特殊原因,无法在支撑后续大流量的接入,一旦不处理,放任后续流量接入的话,系统负载能力可能会恶化(资源竞争越来越厉害,可能谁都抢不到,陷入死循环),最终导致所有用户都无法使用

  • 这里熔断,断的是导致系统异常的流量,将这类流量拉入黑名单,主动限制该流量的下发频率;如果后续该流量回复正常,系统在自动解开限制

  • 弹性能力

以上几点都是属于防御手段,一般情况下都是会导致用户的请求失败的;而应对这个负载问题,最根本的其实是提升系统面对突发流量的弹性能力,如果系统可以立刻处理掉这些突增流量,那么就不用使用防御手段了。针对弹性能力,有如下考虑点:

  • 系统组件可弹性伸缩

  • 中间件可弹性伸缩

  • 过载预测

以上都是过载流量过来的时候,做的一些方案,可能会由于弹性不及时,导致请求失败;另一种思路,可以从流量过来之前,进行流量的提前预测,将资源提前准备好,最大程度的降低流量对资源的瞬时冲击

  • 重试

万一某次请求在系统中失败了,可以通过增加重试逻辑,让请求多试几次,增加成功率

  • 确保重试接口,幂等的

  • 限制重试次数,防止一直重试,在系统负载过高的时候,失败重试过多压垮系统

  • 平滑升级

系统在演进过程中,需要不断迭代版本,如何保证客户正在运行的业务不受影响,也是一个需要重点考虑的问题,通常实现的时候,会涉及如下几个方法

  • 进程支持优雅退出

正在执行请求的进程,在接收到升级信号时,不要暴力退出,等请求执行完毕后,在推出

  • 灰度切流

支持升级的时候,将某个集群的流量切换到其他集群

  • 滚动升级

多集群的组件,支持一个一个的升级,避免全量升级后,引入 bug,系统不可用

  • ......


以上的设计思想,是实战中的常用一些手段,除此之外,还要重点考虑成本问题,不能因为 5 个 9 的可用性,导致成本骤增,如果这样的话,可能要看一下整体的架构设计是不是出问题了,从架构优化。

用户头像

三叶草

关注

还未添加个人签名 2019.11.17 加入

还未添加个人简介

评论

发布
暂无评论
系统设计 - 高可用思想简介_高可用_三叶草_InfoQ写作社区