系统高可用的 10 条军规

大家好,我是苏三,又跟大家见面了。

前言

系统高可用是非常经典的问题,无论在面试,还是实际工作中,都经常会遇到。

这篇文章跟大家一起聊聊,保证系统高可用的10条军规,希望对你会有所帮助。

最近准备面试的小伙伴,可以看一下这个宝藏网站:www.susan.net.cn,里面:面试八股文、面试真题、工作内推什么都有

1 冗余部署

场景:某电商大促期间,数据库主节点突然宕机,导致全站交易瘫痪。

问题:单节点部署的系统,一旦关键组件(如数据库、消息队列)故障,业务直接归零。

解决方案:通过主从复制、集群化部署实现冗余。例如MySQL主从同步,Redis Sentinel哨兵机制。

MySQL主从配置如下:

ini 复制代码
-- 主库配置
CHANGE MASTER TO 
MASTER_HOST='master_host',
MASTER_USER='replica_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;

-- 从库启动复制
START SLAVE;

效果:主库宕机时,从库自动切换为可读写状态,业务无感知。

2 服务熔断

场景:支付服务响应延迟,导致订单服务线程池耗尽,引发连锁故障。

问题:服务依赖链中某个环节异常,会像多米诺骨牌一样拖垮整个系统。

解决方案:引入熔断器模式,例如Hystrix或Resilience4j。

Resilience4j熔断配置如下:

ini 复制代码
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
    .failureRateThreshold(50)  // 失败率超过50%触发熔断
    .waitDurationInOpenState(Duration.ofMillis(1000))
    .build();
CircuitBreaker circuitBreaker = CircuitBreaker.of("paymentService", config);

// 调用支付服务
Supplier<String> supplier = () -> paymentService.call();
Supplier<String> decoratedSupplier = CircuitBreaker
    .decorateSupplier(circuitBreaker, supplier);

效果:当支付服务失败率飙升时,自动熔断并返回降级结果(如"系统繁忙,稍后重试")。

3 流量削峰

场景:秒杀活动开始瞬间,10万QPS直接击穿数据库连接池。

问题:突发流量超过系统处理能力,导致资源耗尽。

解决方案:引入消息队列(如Kafka、RocketMQ)做异步缓冲。

用户下单的系统流程图如下:

RocketMQ生产者的示例代码:

ini 复制代码
DefaultMQProducer producer = new DefaultMQProducer("seckill_producer");
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
Message msg = new Message("seckill_topic", "订单数据".getBytes());
producer.send(msg);

效果:将瞬时10万QPS的请求平滑处理为数据库可承受的2000 TPS。

4 动态扩容

场景:日常流量100台服务器足够,但大促时需要快速扩容到500台。

问题:固定资源无法应对业务波动,手动扩容效率低下。

解决方案:基于Kubernetes的HPA(Horizontal Pod Autoscaler)。

K8s HPA 的配置如下:

less 复制代码
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60

效果:CPU利用率超过60%时自动扩容,低于30%时自动缩容。

5 灰度发布

场景:新版本代码存在内存泄漏,全量发布导致线上服务崩溃。

问题:一次性全量发布风险极高,可能引发全局故障。

解决方案:基于流量比例的灰度发布策略。

Istio流量染色配置如下:

yaml 复制代码
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - bookinfo.com
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 90  # 90%流量走老版本
    - destination:
        host: reviews
        subset: v2
      weight: 10  # 10%流量走新版本

效果:新版本异常时,仅影响10%的用户,快速回滚无压力。

6 降级开关

场景:推荐服务超时导致商品详情页加载时间从200ms飙升到5秒。

问题:非核心功能异常影响核心链路用户体验。

解决方案:配置中心增加降级开关,如果遇到紧急情况,能 动态降级非关键服务。

Apollo配置中心的示例代码如下:

arduino 复制代码
@ApolloConfig
private Config config;

public ProductDetail getDetail(String productId) {
    if(config.getBooleanProperty("recommend.switch", true)) {
        // 调用推荐服务
    }
    // 返回基础商品信息
}

效果:关闭推荐服务后,详情页响应时间恢复至200ms以内。

最近就业形势比较困难,为了感谢各位小伙伴对苏三一直以来的支持,我特地创建了一些工作内推群, 看看能不能帮助到大家。

你可以在群里发布招聘信息,也可以内推工作,也可以在群里投递简历找工作,也可以在群里交流面试或者工作的话题。

添加苏三的私人微信 :li_su223,备注:掘金+所在城市,即可加入。

7 全链路压测

场景:某金融系统在真实流量下暴露出数据库死锁问题。

问题:测试环境无法模拟真实流量特征,线上隐患难以发现。

解决方案:基于流量录制的全链路压测。

实施步骤

  1. 线上流量录制(如Jmeter+TCPCopy)
  2. 影子库隔离(压测数据写入隔离存储)
  3. 压测数据脱敏
  4. 执行压测并监控系统瓶颈

效果:提前发现数据库连接池不足、缓存穿透等问题。

8 数据分片

场景:用户表达到10亿行,查询性能断崖式下降。

问题:单库单表成为性能瓶颈。

解决方案:基于ShardingSphere的分库分表。

分库分表的配置如下:

yaml 复制代码
sharding:
  tables:
    user:
      actualDataNodes: ds_${0..1}.user_${0..15}
      tableStrategy:
        standard:
          shardingColumn: user_id
          preciseAlgorithmClassName: HashModShardingAlgorithm
          preciseAlgorithmType: HASH_MOD
          shardingCount: 16

效果:10亿数据分散到16个物理表,查询性能提升20倍。

9 混沌工程

场景:某次机房网络抖动导致服务不可用3小时。

问题:系统健壮性不足,故障恢复能力弱。

解决方案:使用ChaosBlade模拟故障。

示例命令

lua 复制代码
# 模拟网络延迟
blade create network delay --time 3000 --interface eth0

# 模拟数据库节点宕机
blade create docker kill --container-id mysql-node-1

效果:提前发现缓存穿透导致DB负载过高的问题,优化缓存击穿防护策略。

10 立体化监控

场景:磁盘IOPS突增导致订单超时,但运维人员2小时后才发现。

问题:监控维度单一,无法快速定位根因。

解决方案:构建Metrics-Log-Trace三位一体监控体系。

技术栈组合

  • Metrics:Prometheus + Grafana(资源指标)
  • Log:ELK(日志分析)
  • Trace:SkyWalking(调用链追踪)

定位问题流程如下 :

sql 复制代码
CPU利用率 > 80% → 关联日志检索 → 定位到GC频繁 → 
追踪调用链 → 发现某个DAO层SQL未走索引

效果:故障定位时间从小时级缩短到分钟级。

总结

系统高可用建设就像打造一艘远洋巨轮。

冗余部署是双发动机,熔断降级是救生艇,监控体系是雷达系统。

但真正的关键在于:

  1. 故障预防比故障处理更重要(如混沌工程)
  2. 自动化是应对复杂性的唯一出路(如K8s弹性扩缩)
  3. 数据驱动的优化才是王道(全链路压测+立体监控)

没有100%可用的系统,但通过这10个实战技巧,我们可以让系统的可用性从99%提升到99.99%。

这0.99%的提升,可能意味着每年减少8小时的故障时间------而这,正是架构师价值的体现。

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的50万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

相关推荐
涡能增压发动积2 分钟前
SpringAI-MCP技术初探
人工智能·后端·架构
thePLJ29 分钟前
SpringBoot-已添加并下载的依赖,reload和mvn clean 后还是提示找不到jar包问题
java·spring boot·后端
余华余华32 分钟前
输入输出 数组 冒泡排序举例
java·后端
俞嫦曦43 分钟前
R语言的回归测试
开发语言·后端·golang
JalenYan44 分钟前
Ruby on Rails 中的 Delegated Types(委托类型)
后端·ruby on rails·ruby
hxung1 小时前
spring bean的生命周期和循环依赖
java·后端·spring
油丶酸萝卜别吃1 小时前
springBoot中不添加依赖 , 手动生成一个token ,并校验token (使用简单 , 但是安全会低一点)
spring boot·后端·安全
皮皮的江山1 小时前
基于AI Text2SQL的数据可视化方案
后端·aigc·数据可视化
4dm1n1 小时前
kubectl exec 实现的原理
后端
四七伵1 小时前
高性能 MySQL 必备:COUNT(*)、COUNT(1)、COUNT(字段) 的选择法则
后端·mysql