🛡️ 高可用与容灾¶
学习时间:5小时 | 难度:⭐⭐⭐⭐ 进阶 | 前置知识:04-分布式系统基础
🎯 本章目标¶
- 理解高可用架构的核心模式
- 掌握故障检测与自动转移机制
- 深入理解熔断器、限流、降级策略
- 了解多活架构的设计原则与实践
- 掌握灾备方案设计和SLA计算
📋 目录¶
1. 高可用模式¶
1.1 高可用的定义¶
高可用(High Availability, HA)是指系统在一定时间内保持正常运行的能力。
Text Only
可用性 = 正常运行时间 / 总时间 × 100%
"几个9"的含义:
99% = 2个9 = 每年停机 3.65天
99.9% = 3个9 = 每年停机 8.76小时
99.99% = 4个9 = 每年停机 52.6分钟
99.999% = 5个9 = 每年停机 5.26分钟
1.2 主从模式(Active-Standby)¶
Text Only
正常状态: 故障转移后:
┌──────────┐ ┌──────────┐
│ Master │ ← 处理所有请求 │ Master │ ← 故障!
│ (Active) │ │ (Down) │
└────┬─────┘ └──────────┘
│ 同步
┌────▼─────┐ ┌──────────┐
│ Slave │ ← 待命 │ Slave │ ← 提升为Master
│(Standby) │ │(→Active) │ 接管所有请求
└──────────┘ └──────────┘
| 优势 | 劣势 |
|---|---|
| 实现简单 | 资源利用率50%(备机闲置) |
| 故障切换快 | 切换期间有短暂中断 |
| 数据一致性好保证 | 只有一倍冗余 |
1.3 主主模式(Active-Active / Dual Master)¶
Text Only
┌──────────┐ 双向同步 ┌──────────┐
│ Master A │ ←─────────→ │ Master B │
│ (Active) │ │ (Active) │
└────┬─────┘ └────┬─────┘
│ │
▼ ▼
处理写请求 处理写请求
(region_A的用户) (region_B的用户)
| 优势 | 劣势 |
|---|---|
| 资源利用率100% | 数据冲突问题 |
| 负载分担 | 双向同步复杂 |
| 某节点故障另一个接管 | 需要冲突解决方案 |
冲突解决策略:
| 策略 | 说明 | 适用 |
|---|---|---|
| 最后写入胜出(LWW) | 以时间戳较新的为准 | 简单场景 |
| 业务规则 | 根据业务逻辑合并 | 复杂场景 |
| 分区避免 | 不同Master写不同数据 | 用户维度分区 |
| 人工介入 | 冲突时告警人工处理 | 关键数据 |
1.4 集群模式¶
Text Only
无主集群(如Cassandra):
┌───┐ ┌───┐ ┌───┐
│N1 │──│N2 │──│N3 │
└─┬─┘ └─┬─┘ └─┬─┘
│ │ │
┌─┴─┐ ┌─┴─┐ ┌─┴─┐
│N4 │──│N5 │──│N6 │
└───┘ └───┘ └───┘
所有节点对等,无Leader
写入时写W个节点,读取时读R个节点
W + R > N 保证一致性
有主集群(如Redis Cluster):
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Master 1 │ │ Master 2 │ │ Master 3 │
│ slot 0- │ │slot 5461-│ │slot 10923│
│ 5460 │ │ 10922 │ │ -16383 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
┌────▼─────┐ ┌────▼─────┐ ┌────▼─────┐
│ Slave 1 │ │ Slave 2 │ │ Slave 3 │
└──────────┘ └──────────┘ └──────────┘
1.5 模式对比¶
| 模式 | 可用性 | 资源利用 | 复杂度 | 一致性 | 适用场景 |
|---|---|---|---|---|---|
| 主从 | 高 | 50% | 低 | 强 | 数据库、缓存 |
| 主主 | 很高 | 100% | 高 | 需处理冲突 | 多地域部署 |
| 集群 | 极高 | 100% | 很高 | 可配置 | 大规模系统 |
2. 故障检测与转移¶
2.1 心跳检测¶
Text Only
心跳机制:
节点定期发送心跳消息("我还活着")
超过阈值未收到心跳 → 判定故障
Node A → ♥ → ♥ → ♥ → ♥ → ✗ → ✗ → ✗ → 判定Node A故障
↑
超过N次未收到心跳
心跳参数设计:
心跳间隔: 1-5秒(太短增加网络开销,太长检测慢)
超时阈值: 3-5次心跳间隔
示例:心跳间隔2秒,3次超时
最快检测时间: 4秒
最慢检测时间: 6秒
2.2 Gossip协议¶
Text Only
Gossip(流言)协议:
节点随机选择其他节点交换信息
类似于流言传播
Round 1: Round 2:
A知道B故障 A告诉C: "B故障了"
A随机选C通知 D告诉E: "听说B故障了"
Round 3: Round N:
C告诉D: "B故障了" 所有节点都知道B故障了
E告诉F: "B故障了"
传播速度: O(logN) 轮,N个节点
优势:
- 去中心化,无SPOF
- 最终收敛
- 容忍网络分区
劣势:
- 检测速度不如心跳快
- 信息传播有延迟
使用Gossip的系统:
- Redis Cluster
- Cassandra
- Consul(Serf)
2.3 φ(Phi) Accrual故障检测¶
Text Only
传统检测:二值判断(活着 or 死了)
Phi检测:输出一个怀疑程度(0~∞)
φ值 │
│
10 │ ╱──── 几乎确定故障
│ ╱
5 │ ╱
│ ╱
1 │ ╱──── 开始怀疑
│ ╱
0 │──╱────────── 正常
└──────────────────→ 心跳延迟
φ > 阈值(如8) → 判定故障
优势:自适应不同网络延迟
使用:Cassandra、Akka
2.4 故障转移流程¶
Text Only
完整的故障转移(Failover)流程:
1. 故障检测
├── 心跳超时
├── 健康检查失败
└── 多个监控节点确认
2. 确认故障(防止误判)
├── 多次重试
├── 多个检测源确认
└── 排除网络分区
3. 选举新Leader
├── 数据最新的从节点
├── 优先级最高的
└── Raft/Paxos选举
4. 切换流量
├── DNS切换(分钟级)
├── VIP漂移(秒级)
├── LB配置更新(秒级)
└── Service Discovery更新(秒级)
5. 数据恢复
├── 检查数据一致性
├── 修复可能的数据丢失
└── 补发丢失的消息
6. 原节点恢复
├── 作为新的从节点加入
└── 同步数据
3. 熔断器¶
3.1 熔断器模式¶
Text Only
没有熔断器: 有熔断器:
Service A → Service B(故障) Service A → 熔断器 → Service B(故障)
← 超时(30s) ← 快速失败(5ms)
Service A → Service B(故障)
← 超时(30s) 熔断器检测到B连续失败
... → 断开电路
请求堆积、A也变慢 → 后续请求直接返回降级结果
→ 级联故障! → 定期探测B是否恢复
熔断器就像电路中的保险丝:
检测到下游异常 → 切断连接 → 保护上游不被拖垮
3.2 熔断器状态机¶
Text Only
┌──────────┐ 连续失败 ┌──────────┐
│ Closed │ 达到阈值(如50%) │ Open │
│ (关闭) │ ──────────────→ │ (打开) │
│ 正常放行 │ │ 快速失败 │
└──────────┘ └────┬─────┘
▲ │
│ 超时后(如30s)
│ 探测请求成功 │
│ ▼
│ ┌──────────┐
└─────────────────────── │Half Open │
恢复 │ (半开) │
│ 放行少量 │
│ 探测请求 │
└──────────┘
│
探测失败 │
│
▼
回到Open
状态说明:
| 状态 | 行为 | 转移条件 |
|---|---|---|
| Closed (关闭) | 正常放行所有请求 | 失败率超阈值 → Open |
| Open (打开) | 快速拒绝所有请求 | 等待超时 → Half-Open |
| Half-Open (半开) | 放行少量探测请求 | 成功 → Closed / 失败 → Open |
3.3 熔断器框架对比¶
| 特性 | Hystrix | Sentinel | Resilience4j |
|---|---|---|---|
| 开发商 | Netflix(已停更) | Alibaba | 社区 |
| 熔断 | ✅ | ✅ | ✅ |
| 限流 | ❌ | ✅(强项) | ✅ |
| 降级 | ✅ | ✅ | ✅ |
| 热点限流 | ❌ | ✅ | ❌ |
| 系统保护 | ❌ | ✅(CPU/Load) | ❌ |
| 控制台 | Dashboard | Dashboard(丰富) | Grafana |
| 响应式 | RxJava | ❌ | ✅ 原生支持 |
| 适用 | 历史项目 | 国内/阿里云 | Spring Boot |
3.4 熔断器实现¶
Python
import time
import threading # 线程池/多线程:并发执行任务
from enum import Enum
class CircuitState(Enum):
CLOSED = "closed"
OPEN = "open"
HALF_OPEN = "half_open"
class CircuitBreaker:
"""熔断器:当下游服务连续失败时自动断开,避免级联故障"""
def __init__(self, failure_threshold=5, recovery_timeout=30,
half_open_max_calls=3):
self.failure_threshold = failure_threshold # 触发熔断的连续失败次数
self.recovery_timeout = recovery_timeout # Open状态持续时间(秒),之后进入Half-Open
self.half_open_max_calls = half_open_max_calls # 半开状态最多放行的探测请求数
self.state = CircuitState.CLOSED # 初始状态:关闭(正常放行)
self.failure_count = 0 # 当前连续失败计数
self.success_count = 0 # 半开状态下的成功计数
self.last_failure_time = None # 最后一次失败的时间戳
self.half_open_calls = 0 # 半开状态已放行的请求数
self.lock = threading.Lock() # 线程锁,保证状态转换的原子性
def call(self, func, *args, **kwargs): # *args接收任意位置参数;**kwargs接收任意关键字参数
"""通过熔断器调用函数:根据当前状态决定放行或快速失败"""
with self.lock:
if self.state == CircuitState.OPEN:
# Open状态:检查是否到了尝试恢复的时间
if self._should_try_reset():
self.state = CircuitState.HALF_OPEN # 进入半开状态,允许少量探测
self.half_open_calls = 0
else:
raise CircuitBreakerOpenError("Circuit breaker is OPEN") # 直接快速失败
if self.state == CircuitState.HALF_OPEN:
# 半开状态:限制探测请求数量
if self.half_open_calls >= self.half_open_max_calls:
raise CircuitBreakerOpenError("Half-open call limit reached")
self.half_open_calls += 1
try: # try/except捕获异常
result = func(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise
def _on_success(self):
"""调用成功时的处理"""
with self.lock:
if self.state == CircuitState.HALF_OPEN:
self.success_count += 1
# 半开状态下连续成功达标 → 恢复为关闭状态
if self.success_count >= self.half_open_max_calls:
self.state = CircuitState.CLOSED
self._reset_counts()
elif self.state == CircuitState.CLOSED:
self._reset_counts() # 关闭状态下成功则重置失败计数
def _on_failure(self):
"""调用失败时的处理"""
with self.lock:
self.failure_count += 1
self.last_failure_time = time.time()
if self.state == CircuitState.HALF_OPEN:
self.state = CircuitState.OPEN # 半开状态下失败 → 重新打开熔断器
elif self.failure_count >= self.failure_threshold:
self.state = CircuitState.OPEN # 失败次数达到阈值 → 触发熔断
def _should_try_reset(self):
"""判断Open状态是否已超时,可以尝试Half-Open恢复"""
return (time.time() - self.last_failure_time) >= self.recovery_timeout
def _reset_counts(self):
"""重置所有计数器"""
self.failure_count = 0
self.success_count = 0
class CircuitBreakerOpenError(Exception):
pass
Java
// Java使用Resilience4j实现熔断器
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
// 配置熔断器参数
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 失败率超过50%触发熔断
.waitDurationInOpenState(Duration.ofSeconds(30)) // 熔断后等待30秒再尝试恢复
.slidingWindowSize(10) // 用最近10次调用统计失败率
.minimumNumberOfCalls(5) // 至少5次调用后才开始计算失败率
.build();
// 创建名为"myService"的熔断器实例
CircuitBreaker breaker = CircuitBreaker.of("myService", config);
// 使用熔断器包装远程调用,失败时自动触发熔断保护
String result = breaker.executeSupplier(() -> {
return remoteService.call();
});
4. 限流与降级策略¶
4.1 限流策略¶
| 维度 | 说明 | 示例 |
|---|---|---|
| 接口级 | 限制单个接口QPS | /api/order 限制 1000 QPS |
| 用户级 | 限制单个用户请求频率 | 每用户 100次/分钟 |
| IP级 | 限制单个IP请求数 | 每IP 50次/秒 |
| 全局级 | 限制整个系统QPS | 系统总QPS ≤ 10000 |
| 热点级 | 限制热点参数 | 商品ID=xxx 限制 100/秒 |
4.2 降级策略¶
Text Only
降级 = 当系统超负荷时,主动关闭一些非核心功能
降级级别:
Level 0(正常):所有功能正常
Level 1(轻度):关闭推荐、广告等非核心功能
Level 2(中度):关闭评论、点赞等次要功能
Level 3(重度):只保留核心功能(如下单、支付)
Level 4(极端):只读模式,停止写入
降级方式:
┌─────────────────────────────────────────────┐
│ 手动降级:运维人员通过开关控制 │
│ 配置中心 → 修改开关 → 服务读取 → 降级生效 │
│ │
│ 自动降级:系统根据指标自动触发 │
│ 监控指标 → 超过阈值 → 自动触发 → 降级生效 │
│ │
│ 降级返回: │
│ - 返回默认值/兜底数据 │
│ - 返回缓存的旧数据 │
│ - 返回简化版本的结果 │
│ - 返回友好的错误提示 │
└─────────────────────────────────────────────┘
4.3 限流、熔断、降级的区别¶
| 维度 | 限流 | 熔断 | 降级 |
|---|---|---|---|
| 触发 | 请求量超过阈值 | 下游失败率过高 | 系统负载过高 |
| 目的 | 保护自身不被压垮 | 保护自身不被下游拖垮 | 保证核心可用 |
| 对象 | 入站流量 | 出站调用 | 系统整体 |
| 粒度 | 请求级 | 服务级 | 功能级 |
| 处理 | 拒绝/排队 | 快速失败/fallback | 关闭/简化功能 |
| 比喻 | 高速收费站控流 | 电路保险丝 | 战略性撤退 |
5. 多活架构¶
5.1 多活架构概述¶
Text Only
单机房部署: 多活部署:
┌──────┐ ┌──────┐ ┌──────┐
│机房A │ │机房A │ │机房B │
│全部 │ │服务 │ │服务 │
│服务 │ │数据 │ ⟷ │数据 │
└──────┘ └──────┘ └──────┘
风险:机房故障 = 全网故障 优势:一个机房故障,另一个接管
5.2 同城双活¶
Text Only
同城双活架构:
用户流量
│
┌────▼────┐
│ DNS/LB │ ← 流量分发
└──┬───┬──┘
│ │
▼ ▼
┌─────┐ ┌─────┐
│机房A│ │机房B│ ← 同城(网络延迟 < 2ms)
│ │ │ │
│ App │ │ App │ ← 双活,都处理流量
│ │ │ │
│ DB │ │ DB │ ← 一主一从 或 双主
│(主) │ │(从) │
└──┬──┘ └──┬──┘
│ │
└───┬───┘
│ 同步复制(低延迟)
特点:
- 两个机房都处理读流量
- 写流量通常指向主库所在机房
- 网络延迟低,可以做同步复制
- 数据一致性较容易保证
5.3 异地多活¶
Text Only
异地多活架构(如北京-上海-广州三地):
北京用户 上海用户 广州用户
│ │ │
┌────▼────┐ ┌─────▼────┐ ┌────▼────┐
│ 北京机房 │ │ 上海机房 │ │ 广州机房 │
│ │ │ │ │ │
│ App │ │ App │ │ App │
│ Cache │ │ Cache │ │ Cache │
│ DB(主) │ │ DB(主) │ │ DB(主) │
└────┬────┘ └────┬─────┘ └────┬────┘
│ │ │
└──────────────┼──────────────┘
│
异步数据同步
延迟: 30-100ms
异地多活核心挑战:
| 挑战 | 说明 | 解决方案 |
|---|---|---|
| 数据同步延迟 | 跨城市网络延迟30-100ms | 异步同步 + 最终一致 |
| 数据冲突 | 多地同时写入同一数据 | 用户维度路由(同一用户只在一地写) |
| 流量路由 | 如何将用户分配到正确的机房 | 按地域/userID路由 |
| 切换成本 | 故障时切换流量 | DNS切换 + 预案演练 |
| 数据一致性 | 多地数据如何保持一致 | 单元化 + 全局数据中心 |
单元化架构:
Text Only
单元化 = 将系统按用户维度拆分为独立的单元
用户 → 路由规则(如userID % 3)→ 分配到对应单元
┌──────────── 北京单元 ──────────┐
│ 用户 0,3,6,9,... │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ App │ │Cache│ │ DB │ │
│ └─────┘ └─────┘ └─────┘ │
└────────────────────────────────┘
┌──────────── 上海单元 ──────────┐
│ 用户 1,4,7,10,... │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ App │ │Cache│ │ DB │ │
│ └─────┘ └─────┘ └─────┘ │
└────────────────────────────────┘
┌──────────── 广州单元 ──────────┐
│ 用户 2,5,8,11,... │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ App │ │Cache│ │ DB │ │
│ └─────┘ └─────┘ └─────┘ │
└────────────────────────────────┘
全局数据(如商品信息)→ 全局数据中心 → 同步到各单元
5.4 多活方案对比¶
| 方案 | 距离 | 延迟 | 数据一致性 | 复杂度 | 适用场景 |
|---|---|---|---|---|---|
| 同城双活 | <50km | <2ms | 强一致可行 | 中 | 大部分业务 |
| 异地双活 | 100-2000km | 30-100ms | 最终一致 | 高 | 核心业务 |
| 异地多活 | >1000km | 50-300ms | 最终一致 | 极高 | 超大型系统 |
6. 灾备方案¶
6.1 灾备级别¶
| 级别 | 名称 | 说明 | RPO | RTO | 成本 |
|---|---|---|---|---|---|
| 冷备 | Cold Standby | 只有数据备份,需要时手动恢复 | 小时~天 | 小时~天 | 低 |
| 温备 | Warm Standby | 有备用环境但未运行,需启动 | 分钟~小时 | 分钟~小时 | 中 |
| 热备 | Hot Standby | 备用环境实时同步,随时切换 | 秒~分钟 | 秒~分钟 | 高 |
Text Only
RPO (Recovery Point Objective) = 能容忍丢失多少数据
"数据库2小时前的备份" → RPO = 2小时
RTO (Recovery Time Objective) = 能容忍多长时间不可用
"需要在30分钟内恢复" → RTO = 30分钟
RPO和RTO越小,成本越高!
▲ 成本
│
│ ╱
│ ╱
│ ╱ RPO/RTO越小
│ ╱ 成本指数增长
│ ╱
│ ╱
│ ╱
└──────────────→ RPO/RTO
大 小
6.2 备份策略¶
Text Only
数据备份方案:
1. 全量备份(Full Backup)
每天凌晨备份全量数据
优:恢复简单
劣:耗时长、存储大
2. 增量备份(Incremental Backup)
只备份上次之后变更的数据
优:快速、存储小
劣:恢复需要按顺序重放
3. 差异备份(Differential Backup)
备份上次全量后所有变更
优:恢复较简单
劣:随时间增大
推荐策略:
周日: 全量备份
周一~周六: 增量备份
恢复: 周日全量 + 后续增量按序重放
6.3 容灾演练¶
Text Only
混沌工程(Chaos Engineering):
原则:在生产环境中主动引入故障,验证系统弹性
Netflix Chaos Monkey:
随机终止生产环境中的服务实例
故障注入类型:
├── 进程级:杀死服务进程
├── 网络级:模拟网络延迟/丢包/分区
├── 主机级:关闭服务器
├── 机房级:模拟机房故障
└── 依赖级:模拟第三方服务不可用
演练流程:
1. 定义稳态假设("系统在X故障下,核心功能不受影响")
2. 设计实验(引入什么故障)
3. 在小范围执行(先灰度)
4. 观察结果
5. 发现问题 → 修复 → 重新验证
7. SLA计算¶
7.1 SLA停机时间对照表¶
| SLA等级 | 可用性 | 年停机时间 | 月停机时间 | 周停机时间 | 适用场景 |
|---|---|---|---|---|---|
| 2个9 | 99% | 3.65天 | 7.31小时 | 1.68小时 | 内部系统 |
| 3个9 | 99.9% | 8.76小时 | 43.83分钟 | 10.08分钟 | 一般业务系统 |
| 3.5个9 | 99.95% | 4.38小时 | 21.92分钟 | 5.04分钟 | 重要业务系统 |
| 4个9 | 99.99% | 52.60分钟 | 4.38分钟 | 1.01分钟 | 核心业务系统 |
| 5个9 | 99.999% | 5.26分钟 | 26.30秒 | 6.05秒 | 金融/电信 |
7.2 串联系统SLA计算¶
Text Only
串联系统(所有组件都必须正常):
A(99.9%) → B(99.9%) → C(99.9%)
总SLA = 99.9% × 99.9% × 99.9% = 99.7%
启示:组件越多,总体可用性越低!
10个99.9%的组件串联 = 99.9%^10 = 99.0%
只有2个9了!
7.3 并联系统SLA计算¶
Text Only
并联系统(冗余,任一组件正常即可):
┌─ A(99.9%) ─┐
│ │
├─ B(99.9%) ─┤
│ │
└─ C(99.9%) ─┘
不可用概率 = (1-99.9%)^3 = 0.001^3 = 0.000000001
总SLA = 1 - 0.000000001 = 99.9999999% ≈ 9个9
2个99.9%并联 = 1-(0.001)^2 = 99.9999% (6个9)
3个99.9%并联 = 1-(0.001)^3 = 99.9999999% (9个9)
7.4 混合系统SLA计算¶
Text Only
实际系统是串并联混合:
┌─ Web1 ─┐ ┌─ DB_Master ─┐
├─ Web2 ─┤ → Proxy → ├─ DB_Slave ─┤ → Cache (99.99%)
└─ Web3 ─┘ └──────────────┘
计算:
Web层(并联): 1-(1-0.999)^3 = 99.9999999%
Proxy(单点,但有备份): 99.99%
DB层(主从): 1-(1-0.999)^2 = 99.9999%
Cache: 99.99%
总SLA = 99.9999999% × 99.99% × 99.9999% × 99.99%
≈ 99.98%
≈ 每年停机约1.75小时
瓶颈分析:Proxy和Cache的单点是瓶颈!
7.5 提升SLA的方法¶
| 方法 | 效果 | 成本 | 适用 |
|---|---|---|---|
| 消除单点 | 显著提升 | 中 | 必做 |
| 增加冗余 | 显著提升 | 高 | 核心组件 |
| 故障自动切换 | 减少RTO | 中 | 生产环境 |
| 限流降级 | 保护核心功能 | 低 | 高流量场景 |
| 多活部署 | 极大提升 | 很高 | 核心业务 |
| 混沌工程演练 | 提前发现问题 | 中 | 成熟团队 |
8. 练习与延伸阅读¶
8.1 练习题¶
-
SLA计算: 一个系统包含:LB(99.99%) → 3个App服务器(各99.9%) → 缓存(99.95%) → 数据库主从(主99.9%, 从99.9%) 计算总体SLA
App集群(3个中至少1个可用): 1-(1-0.999)³ = 1-10⁻⁹ ≈ 99.9999999%。数据库主从(至少1个可用): 1-(1-0.999)² = 99.999999%。串联: 99.99% × 99.9999999% × 99.95% × 99.999999% ≈ 99.99% × 99.95% ≈ 99.94%。瓶颈在缓存层(99.95%)和LB层(99.99%)。
-
熔断器设计:为以下场景设计熔断参数:
- 支付服务调用银行接口(P99延迟500ms,失败率通常<0.1%) > 超时:800ms(P99×1.6);连续失败阈值:5次;熔断时长:30s;半开状态放行:1个请求。支付是核心链路,熔断后降级为"支付处理中"异步通知。
-
推荐服务调用ML模型(P99延迟200ms,失败率通常<1%) > 超时:300ms;失败率阈值:5%(窗口期10s内);熔断时长:10s;半开放行:3个请求。推荐是非核心,熔断后降级为热门推荐缓存。
-
多活方案:为一个DAU 5000万的电商系统设计同城双活方案
- 需要考虑:用户数据、订单数据、商品数据的同步策略
-
故障切换流程和时间目标
-
降级方案:为一个社交APP设计三级降级方案
- 列出核心功能和非核心功能
- 定义每个降级级别关闭的功能
-
设计降级触发条件
-
容灾演练:设计一个线上容灾演练方案
- 演练目标
- 故障注入方式
- 回滚方案
- 成功标准
8.2 延伸阅读¶
- Netflix Hystrix Wiki — 熔断器设计原理
- Alibaba Sentinel 官方文档 — 流量治理
- Google SRE Book — 第3,4章 拥抱风险,SLO
- Netflix: "Chaos Engineering — Netflix"
- 阿里技术博客 — "异地多活设计4大原则"
- 美团技术博客 — "美团外卖客户端高可用建设"
📝 本章小结¶
| 知识点 | 关键要点 |
|---|---|
| 高可用模式 | 主从(简单可靠)、主主(高利用率)、集群(高扩展) |
| 故障检测 | 心跳(简单)、Gossip(去中心化)、Phi(自适应) |
| 熔断器 | Closed→Open→Half-Open状态机,保护上游 |
| 限流降级 | 限流保护自身,降级保护核心功能 |
| 多活架构 | 同城双活(低延迟)、异地多活(高可用但复杂) |
| 灾备 | 冷/温/热备,RPO和RTO的权衡 |
| SLA | 串联取最小,并联提升巨大 |
← 上一章:分布式系统基础 | 下一章:经典系统设计案例 →