我眼中如何设计一个高可用系统

系统定位

一个系统明确之初,就应该定义它设计的目标,比如现有的很多大型电商系统,可用性是它设计的目标,全年要达到5个9,而很多银行系统要求很强的事务性,那强一致就是其设计目标,保证不能错;还有一些系统需要很低的延迟等;定义好我们系统的目标后,围绕这些东西可以有很多设计理念可以运用;

高可用系统

高可用系统设计上,首先定义好我们可用率的目标,比如是99.999%,表示全量最多不可用5分钟,有了指标后,我们就要拆分下如何如何达到这个目标,因为大部分系统肯定不能自己闭环,你要依赖外部服务,db,mq等;

  1. 强依赖(典型的后端的db,或者不可或缺的外部服务)
  2. 弱依赖(忍受容错,可以被降级掉)

整体服务的可用率就可以计算出来了,假设强依赖之间是相互独立的
$$
self * \prod_{dependencies}availability = 0.9999 * \prod_{dependencies} 0.9999 = 0.9997
$$
可以看出要达到最终的目标,我们需要提升自己,或者强依赖;还有一些情况是当我们不知道对方的SLA时,如何预估这个值来帮助我们设计系统,此时会用到两个指标来预估;

  • Mean Time Between Failure (MTBF)
  • Mean Time to Recover (MTTR)
    $$
    Availability Estimate = MTBF / (MTBF + MTTR)
    $$
    比如MTBF=150days,MTTR=1hour,我们可以预估一个可用率是99.97%,有了以上数据支撑后,需要技术上做一些事情来支撑,可用率的提升,简单总结为以下几点:

    容量管理

    我们需要很清楚自己的系统,知道他在不同资源下的水位,如何设计系统限流等

    网络管理

    你需要清楚自己服务的部署情况,是否会有跨机房的通信,网络延迟是怎样的,是否会导致堆积,如何处理Dos,如何做Load Balance,网络的FO等

    服务管理

    将自身服务按照有状态和无状态进行拆分,因为你的业务特点,可能会面临每时每刻的峰值变换,要能方便的scale-out

    Isolation

    有了独立的Replica之后,我们可以显著的提升可用率,它的计算模式变为了:
    $$
    self * \prod_{dependencies}not/availability = 0.9999 * \prod_{dependencies} 0.001 = 0.9997
    $$
    level0:我们需要互相独立的available zone来提供服务,方便基础设施出现问题后进行切换
    level1:关键性的模块支持副本,提升这些模块的可用率,避免一些单点问题

    容灾管理

    设计的目标是出现故障后,如何缩短恢复的时间,梳理业务的预案,出现问题后available zone的切换方案,关键模块的切换方案,或者能不能做到自动化的FO
    ;梳理主链路,一些弱依赖出现问题能否直接降级掉,减低风险;容灾也需要经常测试,因为不同场景的切换,可能导致流量超过某个zone的承载极限,最好能支持快速的auto-scaling;

    变更管理

    系统出现问题的情况很多都是由于变更(部署,热变更)等,所以我们需要遵循一些变更的best practice:
    灰度发布,小批量多次进行发布,减少影响范围
    蓝绿发布,整个发布分成两个部分,当一个部分出现问题,可以FO到另外部分,然后快速回滚,进行恢复
    功能开关,新功能上线的时候默认把开关关闭,少量打开确认无问题后,才全量放开
    测试,包括代码部分的单测,集成测试;上线后的灰度测试等;测试需要覆盖正常和异常的情况

    监控&报警

    我们需要对系统有深入且实时的了解,以便做出正确的应对