---
URL: "/zh-CN/blog/2025-05/HAP.html"
LLMS_URL: "/zh-CN/blog/2025-05/HAP.md"
lastUpdated: true
commentabled: true
recommended: true
title: "高可用架构设计要点"
description: "高可用架构设计要点"
date:

pageClass: "blog-page-class"
---

---
lastUpdated: true
commentabled: true
recommended: true
title: 高可用架构设计要点
description: 高可用架构设计要点
date: 2025-05-28 10:55:00 
pageClass: blog-page-class
---

# 高可用架构设计要点 #

## 前言：海恩法则和墨菲定律 ##

### 海恩法则 ###

- 事故的发生是量的积累的结果。
- 再好的技术、再完美的规章，在实际操作层面也无法取代人自身的素质和责任心 。

### 薛定谔的猫 ###

- “薛定谔的猫”告诉我们，事物发展不是确定的，而是量子态的叠加。

### 墨菲定律 ###

- 任何事情都没有表面看起来那么简单 。
- 所有事情的发展都会比你预计的时间长 。
- 会出错的事总会出错。
- 如果你担心某种情况发生，那么它更有可能发生 。

### 蝴蝶效应 ###

- 世界会因一些微小因素的变动，而发生很大的变化。

### 熵增原理 ###

- “热力学第二定律”（熵增原理）告诉我们，世界总是在变得更加混乱无序。  

警示我们，在互联网公司里，对生产环境发生的任何怪异现象和问题都不要轻易忽视，对于其背后的原因一定要彻查。同样，海恩法则也强调任何严重事故的背后都是多次小问题的积累，积累到一定的量级后会导致质变，严重的问题就会浮出水面。那么，我们需要对线上服务产生的任何征兆，*哪怕是一个小问题，也要刨根问底：这就需要我们有技术攻关的能力，对任何现象都要秉着以下原则：为什么发生？发生了怎么应对？怎么恢复？怎么避免？对问题要彻查，不能因为问题的现象不明显而忽略*。

架构设计的愿景就是高可用、高性能、高扩展、高效率。为了实现架构设计四高愿景，需要实现自动化系统目标：

- 标准化。
- 流程自助化。
- 可视化：可观测系统各项指标、包括全链路跟踪。
- 自动化：ci/cd 自动化部署。
- 精细化：监控平台、数据分析精细化。

要实现这些，在中小型公司，架构师可以 hold 住，而在大企业/大厂里面，虾兵蟹将是无法搞定的，至少是 vp 级别来推动。

整个自动化体系需要多平台、系统、工具来解决各类场景的自动化执行，各个平台之间要相互联动形成体系化，而不是相互脱离，各自发展。目前还没看到一站式平台可以串接需求、设计、开发、测试、发布、运维等，而高可用系统架构设计要从产品、开发、运维、硬件等全方位去统筹综合考虑形成一体化。 本文着眼整体，全局规划、分层设计，提供一个稳定性建设总体规划的参考。如果缺什么补什么，没有总体规划的建设，后面做出的系统往往是相互割裂，定位不清、无法持续集成，最后就是沦为一堆零散工具而无法形成体系。

下面我们最近半年主要关注和建设的部分。

## 一、可用性 ##

### 业务可用性指标 ###

所谓业务可用性(availability)也即系统正常运行时间的百分比，架构组/SRE 最主要的 KPI (Key Performance Indicators 关键业绩指标)。对于我们提供的服务（web/api）来说，现在业界更倾向用 N 个 9 来量化可用性，最常说的就是类似“4个9(也就是99.99%)”的可用性。

故障时间=故障修复时间点-故障发现（报告）时间点服务年度可用时间%=（1-故障时间/年度时间）× 100%。

### 故障的度量与考核 ###

对管理者/部门而言：可用性是产品的整体考核指标。对于研发工程师而言：使用故障分来考核：

|  类别  |  描述  |  权重  |  描述  |
|  :---  |  :----:  |  :---  |   :---  |
| 高危S级事故故障 | 一旦出现故障，可能会导致服务整体不可用 | 100 |  |
| 严重A级故障 | 客户明显感知服务异常：错误的回答 | 20 |  |
| 中级B级故障 | 客户能够感知服务异常：响应比较慢 | 5 |  |
| 一般C级故障 | 服务出现短时间内抖动 | 1 |  |

考核指标可以使用故障分度量：`故障分 = 故障时间分钟 * 故障级别权重`。

### 服务分级 ###

如果是一个分布式架构设计，系统由很多微服务组成，所有的服务可用性不可能都是统一的标准。为了提高我们服务可用性，我们需要对服务进行分类管理并明确每个服务级别的可用性要求。

|  类别  |  服务  |  可用性要求  |  描述  |
|  :---  |  :----:  |  :---  |   :---  |
| 一级核心服务 | 核心产品或者服务 | 99.99%（全年53分钟不可用） | 系统引擎部分：一旦出现故障，整个系统瘫痪 |
| 二级重要服务 | 重要的产品功能 | 99.95%（全年260分钟不可用） | 类比汽车轮子：该服务出现问题，该重要功能不可用。 |
| 三级一般服务 | 一般功能 | 99.9%（全年8.8小时不可用） | 类比汽车倒车影像：该部分出现问题，稍微影响用户体验 |
| 四级工具服务 | 工具类是服务 | 0.99 | 非业务功能：比如爬虫、管理后台、运维工具 |

## 二、高可用架构设计总体思想 ##

高可用系统的架构设计，要从产品需求、代码开发、运维部署、故障管理等系统全生命周期进行全方位去考量和设计，核心思想就是：

- **故障事前**： 故障预防，总结经验，做到有智慧的绕开问题。
- **故障发现**： 及时发现，通过完善观测平台及时发现问题吧。
- **故障恢复**： 快速恢复，做好应急预案降低故障影响。
- **故障总结**： 复盘总结故障问题，层层剖析问题产生的原因，由表及里分析问题发生的本质。

高可用系统的架构设计思想包括但不限于：

### 系统设计 ###

- **产品层面**：主要是故障发生后的兜底策略等。例如生成式大模型考虑远程代码执行漏洞， 设计时尽量避免将用户输入内容作为代码部分进行执行，如需执行，需要将服务部署在经过安全隔离的环境中。

- **代码架构**：系统都是研发人员设计和编码写出来的，因此首先要对研发层面有一个代码架构规范，例如编码规范、如果代码架构设计不足，就会造成影响全局的架构设计。同时借助代码分析工具，分析代码可能存在的 bug 或者安全漏洞，例如对于业务设计需要将用户输入内容作为代码部分进行执行，需要应用程序做安全防范。

- **做好容量规划和评估**：主要是让开发人员对系统要抗住的 QPS 量级有一个基本认知，方便后续进行合理的架构设计和演进。

### 故障预防 ###

- **应用层面的高可用预防**： 主要是负载均衡、弹性扩缩容、异步解耦、故障容错、过载保护等。
- **数据层面的高可用预防**： 主要是冗余备份（热备，冷备）、失效转移（确认，转移，恢复）等。
- **模块变更机制预防**： 核心模块变更、新数据集、模型上线、流程变更、新模块、核心 sdk 变更等上线的规范化与审批。
- **模块健康度系统**： 查询系统健康状态，如调模块调用情况、资源使用情况、进程情况、服务处理状态等，快速判断故障模块是否异常。我们健康检查系统是通过拉取各个运营系统（容量系统、变更系统、监控系统等）的模块各项指标数据，结合历史故障数据，分析模块可能存在的异常。

### 故障发现 ###

- **运维层面发现**： 主要是发布测试、监控告警、容灾、故障演练等。
- **完善报警治理**： 四五星报警周期治理，优化指标报警方式，完善新指标，提高报警的准确率、可靠性、时效性。
- **故障大屏**： 全面了解整个业务的健康状况。

### 故障恢复 ###

- **制定《故障管理规范》做好故障应急预案，建设大招平台**：针对特定故障建立相应应急预案， 在出现故障后使用相应的应急预案进行快速恢复，最大程度降低影响范围。
- **切流系统工具**： 可用区/IDC 出现故障问题，可以切流到其他可用区。

### 故障总结 ###

- **故障复盘**： 复盘总结每个故障问题，层层剖析问题产生的原因，由表及里分析问题发生的本质。
- **故障汇总**： 进行故障分类、定级、影响等，如果系统组够大当然需要故障管理系统来管理。

## 三、代码架构高可用 ##

系统都是研发人员设计和编码写出来的，因此首先要对研发层面有一个代码架构规范，例如编码规范、如果代码架构设计不足，就会造成影响全局的架构设计。例如我们之前一个系统，很多功能耦合在一个大单体应用里面，某个功能接口出现问题，就导致整个系统崩溃。

通过规范研发流程可以让我们更好地去研发和维护一个高可用的系统：

### 制定研发规范和原则 ###

- **设计文档评审原则**： 例如新项目重构项目的设计文档一定要评审，通过评审及时发现问题。
- **遵守代码架构规范**： 包括编码规范、项目层次规范、模块规范、依赖规范等。工程的顶层目录结构设计规范，团队内部保持统一，尽量简洁，提高代码的可维护性。遵循团队内部的代码规范 代码规范可以大大减少 bug 并且提高可用性。

### 设计阶段 ###

原则上新功能或者模块要有设计文档，规范好相关方案设计文档的模板和提纲，让团队内部保持统一，例如

- **架构**： 数据模型、接口定义；
- **流程**： 正常流程、异常场景设计。
- **交叉影响**： 配置接口、数据库、可靠性、性能等。设计文档能够指导整个开发流程，包括编码、接口文档和测试用例，所有出现的问题都可以追溯到设计文档中。
- **设计文档是否需要评审**： 新项目、重构项目、大的系统优化或者升级一定要评审。

### 编码阶段 ###

遵循代码规范进行编码。

- **单元测试**： 代码编写完需要有一定的单测能力来保证代码的健壮性，同时也能保障我们后续调整逻辑或者优化的时候可以保证代码的稳定。
- **日志规范**： 对日志进行分类，错误日志和业务日志尽量分开存放，便于开发人员查看，也便于通过日志对系统进行及时监控。要接入统一日志系统、能够做到分布式链路追踪。
- **代码安全**： 借助代码分析工具，分析代码可能存在的 bug 或者安全漏洞。

API 安全建议：

- API 数据传输采用随机、不可预测、复杂的 Token 机制；
- 对 API 调用的数据、功能等实施严格访问控制，并严格设置白名单清单；
- 严格定义 API 输入数据类型，并校验、过滤所有传入数据；
- 对 API 的请求采用公开密码算法进行数字签名和校验；
- 加密 API 请求流量，可采用非对称加密算法逐个加密敏感信息字段，加密结果需做 Base64 编码等；
- 设置 API 请求频率限制策略。

### 线上发布阶段 ###

系统灰度发布：确保故障不会造成大面积影响。接口监控完善，确保及时发现发布过程可能存在的问题。总结一下代码层面可能引发的故障/问题：

- 代码逻辑 bug。
- 超时配置不合理。
- 新老版本功能兼容性问题。
- 代码缺陷引发 core 或者内存溢出。
- 代码安全漏洞：如 sql 注入等。
- 日志不规范导致无法快速定位问题，小问题演变故障。

## 四、容量评估和规划 ##

### 容量评估 ###

明确系统的业务场景，如果是管理工具平台相关，可能不太关注 QPS 相关指标。如果是应对业务系统，一般都要考虑 QPS 均值和峰值。如果是新系统，可以先搜集产品和运营同学对业务的大体预估，可以大体估算出 QPS 相关指标。如果是老系统，那么就可以根据历史数据来评估。评估的时候，要从一个整体角度来看全局的量级，然后再细化到每个子业务模块要承载的量级。

### 容量规划 ###

是指系统在设计的时候，就要能够初步规划好系统大致能够维持的量级，比如是十万级还是百万级别的请求量，或者更多。不同量级对应的系统架构设计完全不一样。尤其到了千万、亿级别的量级的时候，架构设计会有更多的考量。这里值得注意的是，不需要在一开始就设计出远超当前业务真实流量的系统，要根据业务实际情况来设计。同时，容量规划还涉及到：系统上下游的各个模块、依赖的存储、依赖的三方服务分别需要多少资源，需要有一个相对可量化的数据。容量规划阶段更多是要依靠自身和团队的经验，比如要了解系统的 log 的性能、redis 的性能、rpc 接口的性能、服务化框架的性能等等，然后根据各种组件的性能来综合评估已经设计的系统的整体性能情况。

### 性能压测 ###

容量评估和容量规划之后，还需要做就是性能压测。最好是能够做到全链路压测。

性能压测的目的：

- 一是确保系统的容量规划是否准确。如果系统规划的容量是能够抗千万级别的 QPS。那么实际上真的能够抗住吗 ？在上线之前首先要根据经验来判断，其次是通过性能压测得暴露系统爆弱环节。
性能压测要关注的指标很多，但是重点要关注的是两个指标：
- 一个是 QPS，
- 一个是响应耗时要确保压测的结果符合预期。

**我们中心的 SRE 压测任务**： 建立常态化压测机制，使核心链路在目标 QPS 下保持稳定。

*搭建压测平台*， 定期根据实际现网请求生成源模块到目标流量的放大系数，测出不同业务资源占用率峰值，辅助容量评估。

## 五、高可用系统架构设计 ##

### 架构分层 ###

为了降低应用服务管理的复杂性，我们把整个系统划分成若干个层次，每一层专注解决某个领域的问题，并向上提供服务。典型架构分层设计如下：*按照功能处理顺序划分应用，这是面向业务深度的划分。同时禁止逆向调用*。 每个公司的架构分层可能不一样，但是目的都是为了统一架构术语，方便团队内部沟通。

- **接入层**： 主要流量入口，经过简单
- **应用层**： 直接对外提供产品功能，例如网站、API 接口等。应用层不包含复杂的业务逻辑，只做呈现和转换。
- **服务层**： 根据业务领域每个子域单独一个服务，分而治之。
- **数据层**： 数据库和 NoSQL，文件存储等。

我们先列出目前我们系统有哪些环节,每个环节是否薄弱. 客户端访问服务器端，经过很多环节，任何环节出问题，都不能访问：接入层：

- dns 被劫持：域名是否使用 https。
- 黑客攻击：是否有弱密，服务器权限，数据库权限。
- ddos 攻击：是否有必要使用高防 IP 接入流量。
- CC 攻击：免费和收费版域名分开，网关是否有限流和防刷措施。

**应用层/服务层：**

- 服务代码 bug。
- 服务引发 core/内存溢出。
- 依赖第三方服务不可用。
- 自身没有做好监控告警，不能及时发现问题。
- 上线变更操作导致故障。
- 流量过载导致服务不可用。
- 服务没有做好性能压测，无法应对流量高峰影响。

**数据层：**

- 数据一致性问题。
- 数据误操作（如误删除）。
- 数据库损坏，如服务器磁盘损坏导致数据库不可用等。

**整体架构层：**

- 服务器故障。
- 系统整体架构容量规划不合理，无法应对流量高峰影响。
- 缺少切流工具无法降低故障影响。

### 接入高层可用设计 ###

在接入层，这里主要是架构运维的高可用要求的事项：

**域名高可用**

- 域名规范解析和规范化管理，应该制定《域名规范管理说明》，例如根据产品重要等级，制定使用高防 IP 的策略。
- 域名解析 DNS 防劫持：必须使用 https。
- ddos 攻击：是否有必要使用高防 IP 接入流量。

**规范 API 管理**
 
**明确各个 API 限流和防刷策略接入层架构参考**

当系统对外的接口繁多，同时不同的项目不同的接口，没有一个统一管理的系统，也不方便监控和跟踪 api 的健康状况。需要 api 网关，方便 api 日常管理，包括控版本管理，升级，回滚。更重要的是 api 网关起到限流防刷（CC 攻击）作用，保护后端服务。

### 应用层高可用设计 ###

**应用层设计主要原则**

- 可以水平扩展：通过接入层的负载均衡，实现故障自动转移。
- 无状态设计：无状态的系统更利于水平扩展，更利于做负载均衡。状态是系统的吞吐量、易用性、可用性、性能和可扩展性的大敌，要尽最大可能避免。
- 回滚设计 ：确保系统可以向后兼容，如果应用服务上线后出现 bug，可以紧急回滚。
- 灰度发布：结合接入层设计 A/B 功能，实现灰度发布，比如按 ip，请求参数等分发流量。
- 幂等设计：系统中的多次操作，不管多少次，都应该产生一样的效果，或返回一样的效果。
- 调用设置超时：调用服务一旦超时，通信框架应该返回异常，调用方根据调度策略选择重试或者请求转移。
- 异步调用：调用不重要的服务同步变为异步。
- 降级处理：服务具备降级能力。
- 运行环境隔离：对于生成式大模型的远程代码执行设计原则：在独立且无敏感数据的环境中执行代码任务，同时限制资源，任务执行完成后将环境销毁。

**应用服务可能存在异常的情况**

- 服务内部出错、异常。
- 服务响应超时。
- 服务负载过高；
- 网络链路延迟或中断；
- 服务依赖链中部分依赖 SLA 不达标，造成整体服务不可用；
- 服务链条过长，造成 SLA 整体不可控；

**提高服务可用性机制**

解决的思路：服务分级治理、服务隔离、自我保护、失效转移或恢复、服务降级。

- **服务分级治理**： 将服务分级管理，对于核心/重要的，使用更好硬件并隔离部署，避免连锁的故障响应。
- **服务隔离措施**： 依据服务重要性分级或流量特点、用户画像等，从物理上隔离服 务。将服务使用的资源（CPU、线程、IO 等）隔离，主要使用舱壁模式；比如核心服务单独部署，三级服务可以混合部署。
- **自我保护措施**： 快速失败(failfast)、限流、调用超时、熔断（Resilience4j）；
- **失效转移机制**： 失效检测、失效重试、失效转移(failover)、失效恢复（failback)；
- **服务降级措施**： 在流量高峰，服务可能由于大量的并发调用导致性能下降，最后引起服务不可用。为了保证网络和核心流程可用，需要服务降级。

依据依赖服务的重要性或依赖程度（强、弱），实行相应服务降级手段：

- **同步变异步**：低优先级服务调用同步变异步， 比如日志存储等。
- **降级开关，拒绝部分服务**： 通过流量网关做相应的限流甚至直接拒绝服务。

**具体容错机制说明**

- **failover：失效转移：失败自动切换”，是一种备份操作模式。**
  Fail-Over 失效转移是一种备份操作模式，当主要组件异常时，其功能转移到备份组件。其要点在于有主有备，主故障时系统能够自动地切换到备用服务上,  保证服务继续运行。比如内部调用 nginx 代理，不能是单点提供服务，需要有主备模式，通过 keep-alive 机制自动切换到备用服务上。核心和重要服务都需要按 N+1 原则部署。通常用于读操作；
- **failfast：快速失败：快速识别，就是只发起一次调用，失败后立即报错。**
  fail-fast 是“快速失败”，尽可能的发现系统中的错误，使系统能够按照事先设定好的错误的流程执行， 对应的方式是“fault-tolerant（错误容忍）”。以 JAVA 集合（Collection）的快速失败为例，当多个线程对同一个集合的内容进行操作时，就可能会产生 fail-fast 事件。例如：当某一个线程 A 通过 iterator 去遍历某集合的过程中，若该集合的内容被其他线程所改变了；那么线程 A 访问集合时，就会抛出 ConcurrentModificationException 异常（发现错误执行设定好的错误的流程），产生 fail-fast 事件。通常用于非幂等性的写操作；
- **failback：故障自动恢复：故障转移（Fail-Over）之后，服务能够自动恢复。
  Fail-over 之后的自动恢复，在簇网络系统（有两台或多台服务器互联的网络）中，由于要某台服务器进行维修，需要网络资源和服务暂时重定向到备用系统。在此之后将网络资源和服务器恢复为由原始主机提供的过程，称为自动恢复。
- **failsafe：失效安全：出现异常时，直接忽略。即使发生了故障，也不会对系统/服务造成伤害，或尽量减少伤害。
  Fail-Safe 的含义为“失效安全”，即使在故障的情况下也不会造成伤害或者尽量减少伤害。维基百科上一个形象的例子是红绿灯的“冲突监测模块”当监测到错误或者冲突的信号时会将十字路口的红绿灯变为闪烁错误模式，而不是全部显示为绿灯。通常用于写入审计日志等操作；

**接口幂等设计**

应用调用服务失败后，会将请求重新转发到其他服务上，这个时候要进行幂等性的判断，有可能服务调用失败是网络问题导致的，实际上业务处理成功了。

### 服务分级治理 ###

服务层设计最主要原则：服务分级管理。线上有很多服务，每个服务的可用性要求不一样，我们需要先这些服务做分级。

- 各级服务的部署原则：核心服务：独立服务器且 N+1 部署。三级和四级服务可以共享服务器部署。
- 各级服务上线发布原则：核心和重要服务：晚上12点上线。，三级和四级随时可上线。
- 各级服务监控原则。

**一级核心服务：**

- **定义**：可用性:99.99%，极高可用性，全年53分钟不可用。

- **条件**：
  - 服务自身可用性：99.99%。
  - 依赖数据资源服务可用性要求：（应用服务研发方自定义）。
  - 依赖第三方服务可用性要求：（应用服务研发方自定义）。
  - 需要部署的服务器数：N 台。
- **服务设计满足以下原则**：
  - 冗余 N+1 部署：故障自动转移到多部署一个节点，避免单点问题。
  - 可监控：服务流量预警、端口存活、进程占用的资源、服务接口功能逻辑是否正常，应用 FGC 等情况。
  - 可回滚、灰度：灰度部署服务，部署的服务出现问题可快速回滚。
  - 可独立部署：可以直接在运维平台打包部署，而不需要依赖其他服务部署完成后才能部署运行。
  - 可独立测试：可以单独测试。
  - 水平扩展：流量激增可快速扩容。
  - 异步设计：服务需要通知第三方服务，必须通过消息队列进行异步方式完成。
  - 幂等设计：服务可以重复调用，不影响结果。
  - 可容错：自身有容错和修复能力：

**隔离手段**：服务使用的资源（CPU、线程、IO 等）隔离，使用舱壁模式；

**自我保护手段**：快速失败(failfast)、流控、超时、熔断；

**失效转移或恢复手段**：失效检测、重试、转移(failover)、回退恢复（failback)；

**降级手段**：依据依赖服务的重要性或依赖程度（强、弱）,同步变异步，降级开关、拒绝部分服务等。

**二级重要服务**

- **定义**： 可用性99.95%（故障具备自动恢复的能力，全年260分钟不可用）。

- **条件**：
  - 服务自身可用性：99.95%。
  - 依赖数据资源服务可用性要求：（应用服务研发方自定义）。
  - 依赖第三方服务可用性要求：（应用服务研发方自定义）。
  - 需要部署的服务器数：N 台。
- **服务设计满足以下原则**：
  - 冗余 N+1 部署：故障自动转移到多部署一个节点，避免单点问题。
  - 可监控：监控进程、端口存活、进程占用的资源，应用 FGC 等。
  - 可回滚、灰度：灰度部署服务，部署的服务出现问题可快速回滚。
  - 故障隔离：服务器只部署唯一该应用服务，该应用服务出现问题，只影响自身服务问题。
  - 可独立部署：可以直接在运维平台打包部署，而不需要依赖其他服务部署完成后才能部署运行。
  - 可独立测试：可以单独测试。
  - 水平扩展：流量激增可快速扩容。
  - 可容错：自身有容错和修复能力。

**三级一般服务**

- **定义**： 可用性99.9%（全年8.8小时不可用）。

- **条件**：

服务自身可用性：99.95%。
依赖数据资源服务可用性要求：（应用服务研发方自定义）。
依赖第三方服务可用性要求：（应用服务研发方自定义）。
需要部署的服务器数：N台。

- **服务设计满足以下原则**：
  - 冗余 N+1 部署：可以单点部署。
  - 可监控：可监控服务进程、端口存活是否正常。
  - 可回滚、灰度：灰度部署服务，部署的服务出现问题可快速回滚。
  - 故障隔离：一个服务器上可以部署多个应用，但保证服务器资源充足。
  - 可独立部署：需要独立部署。
  - 可独立测试：可以单独测试。
  - 水平扩展：流量激增可快速扩容。
  - 可容错：需要具备一般的容错能力。

**四级工具服务**

- **定义**： 可用性99.9%（全年8.8小时不可用）。

- **条件**：
  - 服务自身可用性：99.9%。
  - 依赖数据资源服务可用性要求：（应用服务研发方自定义）。
  - 依赖第三方服务可用性要求：（应用服务研发方自定义）。
  - 需要部署的服务器数：N 台。

- **服务设计满足以下原则**：
  - 冗余 N+1 部署：可以单点部署，进程存活就可以。
  - 可监控：不需要监控。
  - 可回滚、灰度：只要部署成功就可以。
  - 故障隔离：哪个服务器有资源就可以部署。
  - 可独立部署：不用考虑。
  - 可独立测试：不用考虑。 
  - 水平扩展：不用考虑。
  - 可容错：不用考虑。

## 六、高可用的数据层架构 ##

数据是最宝贵的资产。数据存储高可用主要手段是冗余备份和失效转移机制。数据备份是保证数据有多副本，任意副本的失效都不会导致数据的永久丢失。从而实现数据完全的持久化。而失效转移机制是保证当一个数据副本不可访问时，可以快速切换访问数据的其他副本。保证数据可用。

### 数据架构设计原则 ###

### 数据一致性设计 ###

#### 分布式的 CAP 理论 ####

在一个分布式系统中，Consistency（一致性）、 Availability（可用性）、Partition tolerance（分区容错性），最多只能同时三个特性中的两个，三者不可兼得。

- **C 一致性（Consistency）**： 说的是每一个更新成功后，分布式系统中的所有节点，都能读到最新的信息。即所有节点相当于访问同一份内容，这样的系统就被认为是强一致性的。
- **A 可用性（Availability）**： 是每一个请求，都能得到响应。请求只需要在一定时间内返回即可，结果可以是成功或者失败，也不需要确保返回的是最新版本的信息。
- **P 分区容错性（Partition tolerance）**： 是说在网络中断，消息丢失的情况下，系统照样能够工作。这里的网络分区是指由于某种原因，网络被分成若干个孤立的区域，而区域之间互不相通。

在非金融的互联网分布式应用里面，主机多，数据大，部署分散。所以节点故障，网络故障是常态。一般是为了保证服务可用性而舍弃一致性 C。即保证 AP。

#### 分布式的 BASE 理论 ####

BASE 理论，它是在 CAP 理论的基础之上的延伸。包括基本可用（Basically Available）、柔性状态（Soft State）、最终一致性（Eventual Consistency）。

- **基本可用**： 分布式系统出现故障的时候，允许损失一部分可用性。比如，阿里双十一大促的时候，对一些非核心链路的功能进行降级处理。
- **柔性可用**： 允许系统存在中间状态，这个中间状态又不会影响系统整体可用性。比如，数据库读写分离，写库同步到读库（主库同步到从库）会有一个延时，这样实际是一种柔性状态。柔性事务和刚性事务对立，刚性事务也叫强一致性，比如 ACID 理论。
- **最终一致性**： 例如数据库主从复制，经过数据同步延时之后，最终数据能达到一致。

柔性事务(遵循 BASE 理论)放弃了隔离性，减小了事务中锁的粒度，使得应用能够更好的利用数据库的并发性能，实现吞吐量的线性扩展。异步执行方式可以更好的适应分布式环境，在网络抖动、节点故障的情况下能够尽量保障服务的可用性 (Availability)。因此在高可用、高性能的应用场景，柔性事务是最佳的选择。

柔性事务对 ACID 的支持：

- 原子性：严格遵循。
- 一致性：事务完成后的一致性严格遵循，事务中的一致性可适当放宽。
- 隔离性：并行事务间不可影响；事务中间结果可见性允许安全放宽。
- 持久性：严格遵循。

在业内，关于柔性事务，最主要的有以下四种类型：

- **两阶段型**： 就是分布式事务两阶段提交，对应技术上的 XA、JTA/JTS。这是分布式环境下事务处理的典型模式。
- **补偿型**： TCC 型事务（Try/Confirm/Cancel）可以归为补偿型。服务器A 发起事务，服务 B 参与事务，服务 A 的事务如果执行顺利，那么事务 A 就先行提交，如果事务 B 也执行顺利，则事务 B 也提交，整个事务就算完成。但是如果事务 B 执行失败，事务 B 本身回滚，这时事务 A 已经被提交，所以需要执行一个补偿操作，将已经提交的事务 A 执行的操作作反操作，恢复到未执行前事务 A 的状态。*这个需要服务 A 可以幂等操作*。
- **异步确保型**： 将一些同步阻塞的事务操作变为异步的操作，避免对数据库事务的争用。
- **最大努力通知（多次尝试）**： 交易的消息通知与失败重试（例如商户交易结果通知重试、补单重试）

### 完善的数据备份和恢复机制 ###

完善的数据备份和恢复机制能力，在发生数据丢失的时候，可以使用备份快速恢复。

## 七、服务运营 ##

运营层面主要故障总结：

- 运营操作失误
- 缺乏应急机制。
- 缺乏故障处理机制。
- 缺乏故障演练，导致切流后引发更大故障。

具体措施：

### 故障预防 ###

#### 灰度发布 ####

服务发布上线的时候，要有一个灰度的过程。先灰度 1-2 个服务实例，然后逐步放量观察。A/B 测试就是一种灰度发布方式，指为产品已发布 A 版本，在发布 B 版本时，在同一时间维度，让一部分用户继续用 A 版本，一部分用户开始用 B 版本，如果用户对 B 版本没有什么反对意见，那么逐步扩大范围，把所有用户都迁移到 B 版本上面来。灰度发布可以保证整体系统的稳定，在初始灰度发布时就可以发现及调整问题，以保证其影响度。通过灰度发布降低发布影响面和提升用户体验，就算出问题，也只会影响部分用户，从而可以提前发现新版本中的 bug，然后在下一次发布前提前修复，避免影响更多用户；灰度发布的主要分类：

- 金丝雀发布：在原有部署版本可用的情况下,同时部署新版本应用作为金丝雀。
- 滚动发布：一般是取出一个或者多个服务器停止服务，执行更新，并重新将其投入使用。周而复始，直到集群中所有的实例都更新成新版本。
- 蓝绿发布：蓝绿部署是不停老版本，部署新版本然后进行测试。确认 OK 后将流量切到新版本，然后老版本同时也升级到新版本。

#### 容灾备份部署 ####

- 备份：数据备份（热备，冷备（冗余），异地）
- 过载保护
- 同城多活-》异地多活
- 流量切换
- 重试，防雪崩（概率很小，成本很高）

#### 故障演练 ####

故障演练是应用高可用能力测评的核心， 通过例行化故障演练、找出系统风险点、优化业务系统、产出可行有效的故障处理预案。

### 完善的服务故障发现 ###

#### 监控告警机制 ####

在高可用服务设计章节提到，核心服务可以监控：服务流量预警、端口存活、进程占用的资源、服务接口功能逻辑是否正常，应用 FGC 等情况，需要一个完善监控告警机制，并在告警后，通过一定的策略进行处理，以致服务可以快速恢复。例如，监控 FGC，如果在一分钟内存出现10次 FGC，自动重启服务。

- 网络流量监控 。
- 系统监控：服务器资源和网络相关监控（CPU、内存等） 。
- 日志监控：统一日志收集（各个服务）监控，跟踪(log2) 。
- 应用监控：端口存活、进程占用的资源，应用 FGC 等情况。
- 业务监控：服务接口功能逻辑是否正常。
- 立体监控：监控数据采集后，除了用作系统性能评估、集群规模伸缩性预测等， 最终目标是还可以根据实时监控数据进行风险预警，并对服务器进行失效转移，自动负载调整，最大化利用集群所有机器的资源。

#### 全链路观测平台 ####

构建服务全链路观测能力，并有效降低 MTTR 各项指标。掌握数据分析方法，构建数据服务指标，有效评估业务整体服务质量，沉淀一般通用指标方案，能成功复用到其他项目。

## 八、高质量的服务管理 ##

- 服务规范管理：CMDB 对项目、服务、服务器进行统一管理。 
- 代码质量管理：通过 ci 工具流程快速检测代码规范和安全隐患。
- 自动化发布：发布不影响用户，完善发布流程，自动化发布，可以及时回滚  。
- 自动化测试：上线完成后进行全面自动化测试。
- 性能压测：通过对服务压测，了解服务可以承载并发能力，以致可以让运维通过预警进行服务器扩容 。
- 代码控制：测试环境使用测试分支，beta 环境发布 tag，线上使用该 tag 发布。
- 发布流程：规范上线发布流程。
- 灰度发布：灰度发布服务 。
- 应急处理机制 。
- 故障处理规范。

形成闭环管理：有迹可循，来源可溯、去向可查等完整的生命周期管理。

## 九、能力和职责 ##

> 海恩法则提到：再好的技术、再完美的规章 ， 在实际操作层面也无法取代人自身的素质和责任心 。

因此要做到高可用的架构设计，职责也要清晰明确，要不然出现问题，相互推诿，问题解决进度很慢，会直接影响业务服务可用性。

### 职责清晰明确 ###

#### 架构师职责 ####

- 高可用架构设计：包括业务流程，模块划分组合，框架设计，流程纰漏，最后架构设计，技术实现步骤。
- 系统性的思考，权衡利弊，综合各种因素，设计出具有前瞻性的架构。
- 和运维协调沟通，提出高效的服务治理解决方案，把控服务质量管理。
- 协调沟通：开发之间沟通，产品之间沟通，市场沟通，运维沟通、沟通后产出图形化文档及设计。
- 规范和统筹：保证系统秩序，统一，规范，稳定，高效运行。

#### 运维/SRE 职责 ####

- 熟悉系统技术架构，和架构师制定各种规范化要求。
- 和架构师共同协调沟通，对系统架构提出可靠性，伸缩，扩展，数据库切分，缓存应用等解决方案。
- 提供监控系统，自动化发布系统，代码管理，文档平台，自动运维平台等基础设施制定运维规范。
- 建立运维安全体系。
- 建立容灾备份体系。

#### 研发职责 ####

- 参与架构师的架构师设计，并根据设计实现具体细节。针对开发功能进行自测，压测。
- 开发代码，使用工具或组件符合架构师制定规范。
- 包括代码规范、文档规范。代码部署符合运维部署规范要求。

### 作为架构师/SRE 具备能力 ###

> 人的能力素质是解决问题的根本

**作为架构师，需要能力**： "具备对操作系统、容器技术、网络，大型分布式微服务架构深入理解和实践经验。能理解业务的可靠性需求，转化为技术指标，运用云原生、混沌工程、全链路压测等技术手段，建立业务的可观测，提升业务的 MTBF(平均故障间隔时间 Mean Time Between Failure)、降低 MTTR(平均修复时间 Mean time to repair)，通过系统与数据能力不断帮助业务取得成功"。

**自动化体系建设能力**： 能对日常发布、变更工作、容量规划进行主动的自动化体系建设，并能沉淀指导方法，有效指导多业务建设。

**掌握故障预防和发现技巧**： 掌握通过构建和实施全链路压测和混沌工程等故障预防手段提升 MTBF。掌握通过构建和实施系统异常检测和监控告警机制等故障发现手段降低 MTTI。

**构建观测平台能力**： 具备构建服务全链路观测能力，并有效降低 MTTR 各项指标。精通数据分析方法，构建数据服务指标，有效评估业务整体服务质量，沉淀一般通用指标方案，能成功复用到其他项目。

**技术深度能力**：性能分析，基础扎实，深入底层： 能多维度的分析业务的性能瓶颈，通过架构调整，内核、软件参数等手段调优，沉淀一般通用性调优方案。

**技术广度能力**： 理解云原生相关技术与生态，能指导业务架构、技术架构调整落地为云原生应用。
