如何系统性地提升系统可用性?

面试场景

面试官:”你之前的项目是如何保证高可用的?”

这是一道开放性问题。如果仅回答”用了限流降级熔断”,只能得到及格分。高分回答需要结构化思维,从全局视角梳理高可用策略。


核心思路:三大策略

构建高可用系统,核心围绕三个策略展开:

  1. 减少故障次数:尽可能让故障不发生
  2. 降低故障时长:一旦发生,快速止血恢复
  3. 缩小故障范围:控制爆炸半径,避免雪崩

本题聚焦减少故障次数的五大方法。


方法一:限流

核心思想

保护系统不被超出其处理能力的请求击垮,通过主动拒绝保障可用性。

关键点

1. 阈值设置

  • 过高形同虚设,过低浪费资源
  • 最佳实践:在业务低峰期使用真实流量回放压测,阈值设为峰值容量的 50%~70%

2. 多级布控

系统整体限流(如600 QPS)
     │
     ├── 接口级别限流(慢接口单独设限)
     │
     └── 来源级别限流(按租户/业务线区分)

3. 主流工具

  • Guava RateLimiter(单机令牌桶)
  • Sentinel(阿里开源,支持集群限流、热点参数限流)
  • Nginx limit_req_zone(网关层限流)

方法二:防刷

与限流的区别

限流针对正常业务洪峰,防刷针对异常请求:DDoS攻击、抢票工具、代码BUG(循环调用)。

防护层级(越上层越好)

层级 方式 说明
WAF IP围栏、DDoS速率限制 云厂商WAF产品
Nginx limit_req_zone + limit_conn IP维度请求速率限制
应用层 Redis计数器 用户ID+接口维度限制

应用层示例

String key = "rateLimit:" + userId + ":" + method;
Long count = redisTemplate.opsForValue().increment(key, 1);
if (count == 1) {
    redisTemplate.expire(key, 1, TimeUnit.SECONDS);
}
if (count > 10) {
    throw new RateLimitException("请求过于频繁");
}

方法三:超时设置

为什么需要超时?

下游服务可能存在长尾请求(TP99=100ms,但TP999=5s),不设超时会导致线程池被占满。

最佳实践

  • 超时时间设置在 TP99 ~ TP999 之间
  • 例如:TP99=100ms,超时可设200ms
  • 配合重试策略(重试次数、退避算法、幂等保障)

超时配置示例(Dubbo)

dubbo:
  consumer:
    timeout: 200
    retries: 2

方法四:系统巡检

巡检时机

  • 代码上线后:检查是否引入性能问题
  • 业务高峰期前:提前发现隐患

巡检内容

┌─ 硬件指标 ─┬─ 应用服务器:CPU、内存、负载、网络
│            └─ 数据库服务器:连接数、磁盘IO、慢SQL
│
├─ 业务指标 ─── QPS/TPS、接口响应时间、错误率
│
└─ 数据库指标 ─ 新增慢SQL、锁等待、主从延迟

方法五:故障复盘

复盘方法论

  • 5 WHYS:连续追问5次”为什么”,找到根因
  • 黄金三问:发生了什么?为什么发生?如何防止再发生?

复盘输出要点

  1. TODO必须可落地,而非”下次多注意”
  2. 区分重要紧急重要不紧急,明确负责人和完成时间
  3. 由点及面:一个故障可能揭示一类问题

面试答题要点

  1. 结构化:先给出”减少故障次数、降低故障时长、缩小故障范围”的框架
  2. 深入细节:限流要讲阈值设置和多级布控,不能只说”加了限流”
  3. 结合场景:最好能举出具体案例,如”压测发现系统峰值3000 QPS,限流阈值设2000”
  4. 工具选型:能说出Sentinel、Hystrix等工具的选型理由

总结

减少故障次数的五大方法:

方法 核心价值
限流 控制入口流量,保护系统
防刷 拦截异常请求,防止恶意攻击
超时设置 防止单点慢导致全局卡死
系统巡检 提前发现隐患,防患于未然
故障复盘 从历史故障中学习,持续改进