← 返回因果链

🔗 高可用容错因果链

因为…所以… — 从单点故障到异地多活的完整因果推导

单点故障冗余负载均衡 熔断限流优雅停机容灾

📊 因果链总览图

❓ 单点故障 💡 冗余部署 ⚡ 流量集中 💡 负载均衡
⚡ 上游服务故障级联 💡 熔断降级 ⚡ 流量突增 💡 限流排队
⚡ 发布出错 💡 蓝绿/金丝雀部署 ⚡ 机房故障 💡 异地多活

① 因为:单点故障 → 所以冗余部署

❓ 问题:一台服务器挂了,整个系统不可用
💡 所以:冗余——至少2台,一台挂了另一台顶上
❌ 单点:一台服务器
✅ 冗余:主库+从库 / 多实例
主主模式:两边都能写 vs 主从模式:一写多读

因为一台会挂 → 所以至少两台 → 但是两台之间数据要同步 → 引出主从复制

② 因为:流量集中 → 所以负载均衡

❓ 问题:3台服务器,流量全打到第1台,其他2台闲着
💡 所以:负载均衡——把流量均匀分配
// Nginx 负载均衡 upstream order_service { // 因为:各服务器性能不同 → 所以:权重分配 server 192.168.1.10:8080 weight=3; // 性能好,多分 server 192.168.1.11:8080 weight=1; // 性能差,少分 // 因为:需要会话保持 → 所以:ip_hash // ip_hash; // 同一IP总是到同一服务器 // 因为:某台挂了不能发流量 → 所以:健康检查 // 健康检查:定期探测,不健康自动剔除 } // 负载均衡算法选择(因为…所以): // 因为服务器性能一样 → 轮询(Round Robin) // 因为服务器性能不同 → 加权轮询(Weighted) // 因为需要会话保持 → ip_hash // 因为短连接多 → 最少连接(Least Connections)

③ 因为:上游服务故障级联 → 所以熔断降级

❓ 问题:库存服务宕机 → 订单服务线程全阻塞 → 订单也挂了

因为一个服务挂了会导致整条链路雪崩 → 所以需要熔断器:检测到失败率过高就断开,快速失败而非慢慢等死

💡 熔断三状态
关闭
(正常)
失败率>50% 打开
(快速拒绝)
超时后 半开
(试探性放行)
半开成功→关闭 | 半开失败→打开
// Sentinel 熔断配置——因为要自动熔断 → 所以配规则 @SentinelResource(value = "orderService", fallback = "fallback") public Order getOrder(Long id) { return orderClient.query(id); } // 因为上游故障 → 所以快速降级返回兜底数据 public Order fallback(Long id) { return new Order(id, "服务暂时不可用,请稍后重试"); } // 熔断规则:因为失败率>50% → 所以打开熔断器 // DegradeRule: grade=CIRCUIT_BREAKER, count=0.5, timeWindow=10s

④ 因为:流量突增 → 所以限流

💡 限流——因为资源有限,所以超过容量的请求必须排队或拒绝

类比:地铁限流——人太多就放行慢一点,不能让人全挤进站台

算法原理因为…所以选
计数器固定窗口内计数因为简单 → 但临界点会双倍流量
滑动窗口细粒度窗口因为计数器临界问题 → 所以更精确
令牌桶匀速放令牌,取到才能请求因为允许突发 → 所以API限流常用
漏桶匀速流出因为要严格匀速 → 所以流量整形
// Spring Boot 限流——因为令牌桶最常用 → 所以用Guava RateLimiter @RestController public class OrderController { // 因为秒杀接口QPS上限1000 → 所以限流100/s private final RateLimiter limiter = RateLimiter.create(100); @GetMapping("/seckill") public Result seckill() { if (!limiter.tryAcquire()) { // 因为令牌桶没令牌了 → 所以快速拒绝 return Result.fail("系统繁忙,请稍后重试"); } return orderService.seckill(); } }

⑤ 因为:发布出错 → 所以安全部署策略

💡 部署策略因果链
策略原理因为…所以选
蓝绿部署两套环境,切换因为要秒级回滚 → 所以蓝绿
金丝雀发布先放5%流量到新版本因为不想全量出问题 → 所以逐步放量
滚动更新逐个替换实例因为资源不够两套环境 → 所以滚动

⑥ 因为:停机会丢失进行中的请求 → 所以优雅停机

💡 优雅停机因果链

因为kill -9直接杀进程 → 正在处理的请求断了 → 所以优雅停机:1.停止接收新请求 2.等现有请求处理完 3.关闭

// Spring Boot 优雅停机 server: shutdown: graceful # 开启优雅停机 spring: lifecycle: timeout-per-shutdown-phase: 30s # 最多等30秒 // 因为K8s发SIGTERM → 所以应用接收到后: // 1. 从注册中心注销(不再接收新请求) // 2. 等现有请求处理完(最多30秒) // 3. 关闭线程池、连接池 // 4. 退出

⑦ 因为:机房故障 → 所以容灾

💡 容灾因果链
❓ 机房断电/断网 💡 同城双活 ⚡ 同城也可能一起挂
💡 异地灾备 ⚡ 灾备不能实时 💡 异地多活

类比:Docker=集装箱,把应用打包成标准化单元;K8s=自动化港口,自动调度、扩缩容、自愈

🎯 面试点映射

面试题因为…所以…
高可用设计因为单点故障 → 冗余 → 因为流量集中 → 负载均衡
熔断降级因为上游故障级联 → 熔断快速失败 → 降级返回兜底
限流算法因为资源有限 → 计数器/滑动窗口/令牌桶/漏桶
部署策略因为发布出错 → 蓝绿秒回滚/金丝雀小流量验证
优雅停机因为kill丢失请求 → 所以先注销+等处理完+再关闭
Docker因为环境不一致 → 所以容器化打包应用+依赖
K8s因为手动管理容器太累 → 所以K8s自动调度+自愈
容灾方案因为机房故障 → 同城双活 → 异地灾备 → 异地多活

❓ 常见疑问

熔断和限流有什么区别?
因为上游故障 → 所以熔断(被动,检测到故障才断开);因为自身扛不住 → 所以限流(主动,提前设好上限保护自己)。熔断是保护自己不被别人拖垮,限流是保护自己不被自己撑爆。
蓝绿部署和金丝雀发布怎么选?
因为需要秒级回滚 → 所以蓝绿(两套完整环境随时切);因为资源不够两套环境 → 所以金丝雀(同一套环境,流量灰度切换)。大公司两者结合:金丝雀放量5%→10%→100%,蓝绿兜底。
优雅停机最多等多久?
因为业务请求有长有短 → 所以设超时(通常30s)。超过30s还没处理完的请求强制中断——因为不能永远等下去。K8s默认给30s宽限期(terminationGracePeriodSeconds)。

📌 因果链总结

单点
故障
冗余
部署
流量
集中
负载
均衡
故障
级联
熔断
降级
流量
突增
限流 发布
出错
蓝绿/
金丝雀
机房
故障
异地
多活
全栈资料库 · 因果链板块 · 高可用容错因果链