Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

10.4 分布式系统基础

随着业务的发展,单台服务器的性能和容量已经无法满足需求,分布式系统已经成为现代大型应用的标准架构。理解分布式系统的基础原理,是后端工程师进阶的必备技能。

分布式系统基本概念

什么是分布式系统

分布式系统是指将多个独立的计算机通过网络连接,共同协作完成同一任务的系统。对用户来说,就像在使用一个单独的系统一样,不需要关心背后的多个节点。

  • 优点:高性能、高可用、可扩展、容量大
  • 缺点:复杂度高、需要处理网络问题、一致性问题、运维复杂

分布式系统的设计目标

  1. 高性能(Performance):响应时间短、吞吐量高,比单系统性能更好
  2. 高可用(Availability):全年无故障,服务可用时间占比高,通常用几个9来衡量,比如99.9%可用性意味着年 downtime 小于8.76小时
  3. 可扩展性(Scalability):通过增加服务器节点就能线性提升系统的性能和容量,支持业务增长
  4. 一致性(Consistency):多个节点的数据保持一致,用户不管访问哪个节点都能看到相同的数据
  5. 分区容错性(Partition Tolerance):网络分区故障时,系统仍然能正常提供服务

这些目标之间往往是冲突的,需要根据业务场景权衡取舍。

分布式架构的演进

1. 单体架构

所有功能都在一个应用中,部署在一台服务器上。

  • 优点:开发简单,部署方便,适合初期小团队小业务
  • 缺点:耦合度高,迭代慢,无法水平扩展,单台服务器有性能瓶颈

2. 垂直拆分架构

按照业务垂直拆分成多个独立的应用,每个应用部署在独立的服务器上,比如电商系统拆分成用户、商品、订单等应用。

  • 优点:业务解耦,独立开发部署,不同业务可以独立扩容
  • 缺点:公共功能重复开发,跨业务调用复杂,单个业务还是单体架构,仍有单点问题

3. 分布式服务架构(SOA/微服务)

将系统拆分成多个独立的服务,每个服务负责单一功能,服务之间通过网络通信调用,是现在大型应用的主流架构。

  • 优点:服务独立迭代、独立扩容,技术栈灵活,能支撑超大规模业务
  • 缺点:架构复杂度高,需要处理分布式带来的各种问题,运维成本高

分布式核心组件

1. 负载均衡

负载均衡是分布式系统的入口,将请求均匀分发到后端多个服务器节点,避免单节点压力过大,提升系统整体吞吐量和可用性。

  • 常见负载均衡方式
    • DNS负载均衡:域名解析到多个IP,实现简单,但是调度粒度粗,无法感知后端节点状态
    • 硬件负载均衡:F5、A10等硬件设备,性能高,但是价格昂贵
    • 软件负载均衡:Nginx、LVS、HAProxy等,成本低,灵活可配置,是现在的主流
  • 常见调度算法:轮询、加权轮询、随机、最少连接、IP哈希、一致性哈希
  • 高可用:负载均衡本身不能是单点,通常要做主从部署,避免单点故障

2. 分布式缓存

缓存是提升系统性能的核心组件,将热点数据放在内存中,减少数据库查询压力,提升响应速度。

  • 常见缓存产品:Redis、Memcached,现在Redis是主流,支持丰富的数据结构、持久化、集群模式
  • 缓存典型问题
    • 缓存穿透:查询不存在的数据,请求穿透到数据库,解决方案:缓存空值、布隆过滤器
    • 缓存击穿:热点key过期,大量请求同时打到数据库,解决方案:加锁、热点key永不过期
    • 缓存雪崩:大量key同时过期,大量请求打到数据库,解决方案:过期时间加随机值、多级缓存
  • 缓存更新策略:先更数据库再删缓存,保证数据一致性,避免脏读
  • 缓存架构:本地缓存(Caffeine、Guava Cache) + 分布式缓存(Redis)的多级缓存架构,性能更高

3. 消息队列

消息队列是分布式系统中实现异步解耦、削峰填谷的核心组件。

  • 核心作用
    • 异步解耦:非核心流程异步处理,降低响应时间,模块之间解耦
    • 削峰填谷:缓冲突增的流量,保护后端服务不被打垮
    • 最终一致性:通过消息保证多个服务的数据最终一致
    • 广播通知:一条消息可以被多个消费者消费,实现一对多通信
  • 常见消息队列产品
    • Kafka:高吞吐量、高可用,适合大数据、日志收集、流式处理场景
    • RabbitMQ:功能丰富,可靠性高,适合对可靠性要求高的业务场景
    • RocketMQ:阿里开源,高性能、高可靠,适合电商等金融业务场景
    • Pulsar:新一代云原生消息队列,支持多租户、无限存储空间
  • 消息可靠性保证:生产者确认、持久化、消费者确认、重试机制,保证消息不丢失
  • 常见问题:消息重复消费(要保证消费幂等)、消息顺序性、消息堆积

4. 分布式存储

单台服务器的存储容量有限,分布式存储将数据分散存储在多个节点上,提供大容量、高可用、高可靠的存储服务。

  • 分布式文件存储:FastDFS、MinIO、HDFS,存储图片、视频等非结构化数据
  • 分布式数据库:MySQL分库分表、TiDB、Spanner,解决单库容量和性能瓶颈
  • 分布式对象存储:阿里云OSS、AWS S3,现在云原生场景的主流存储方式

分布式一致性问题

分布式系统中,多个节点之间通过网络通信,网络是不可靠的,会有延迟、丢包、分区等问题,如何保证多个节点之间的数据一致性,是分布式系统最核心的难点。

CAP定理

CAP定理是分布式系统的基础定理,指出分布式系统不可能同时满足三个特性:

  • 一致性(Consistency):所有节点在同一时间看到的数据是一致的
  • 可用性(Availability):每个请求都能得到正常的响应,不会超时或者错误
  • 分区容错性(Partition Tolerance):发生网络分区(节点之间网络不通)时,系统仍然能正常提供服务

CAP定理告诉我们,在分布式系统中,P是必须满足的,因为网络分区是不可避免的,所以我们只能在C和A之间权衡:

  • CP系统:优先保证一致性,牺牲可用性,比如分布式数据库、金融系统,要求数据强一致
  • AP系统:优先保证可用性,牺牲一致性,比如大多数互联网应用,保证高可用,允许短暂的数据不一致

BASE理论

BASE理论是对CAP的折中,是现在互联网分布式系统的事实标准:

  • 基本可用(Basically Available):出现故障时,允许损失部分可用性,比如降级、限流,保证核心功能可用
  • 软状态(Soft State):允许系统存在中间状态,数据同步有延迟,不影响系统整体可用性
  • 最终一致性(Eventually Consistent):不需要保证实时强一致,经过一段时间后,数据最终会达到一致状态

BASE理论牺牲强一致性来获得高可用性,适合大多数互联网业务场景,用户体验影响很小,但系统可用性大大提升。

一致性级别

分布式系统的一致性分为多个级别,根据业务需求选择合适的级别:

  1. 强一致性:任何时刻所有节点的数据都是一致的,任何读请求都能返回最新写入的值,实现成本高,性能低,比如银行转账系统
  2. 顺序一致性:所有进程看到的操作顺序和实际发生的顺序一致
  3. 最终一致性:不需要实时一致,经过一段时间后数据最终一致,实现成本低,性能高,适合大多数互联网场景,比如电商的商品库存、用户信息等

常见一致性算法

为了实现分布式一致性,人们设计了很多一致性算法:

  1. Paxos:经典的强一致性算法,比较复杂,难实现
  2. Raft:更容易理解和实现的强一致性算法,现在被广泛使用,比如Etcd、Consul都是基于Raft算法
  3. ZAB:Zookeeper使用的一致性算法,保证数据的一致性
  4. Gossip协议:最终一致性算法,通过节点之间随机通信同步数据,实现简单,高可用,比如Redis Cluster、Consul都是用Gossip协议

这些算法的核心目标是在不可靠的网络环境下,保证多个节点之间的数据一致性。

微服务架构基础

微服务是现在分布式架构的主流实践,将单体应用拆分为多个小型服务,每个服务独立开发、独立部署、独立扩容,服务之间通过轻量级的HTTP/RPC通信。

微服务的优势

  1. 服务独立迭代,开发效率高,小团队可以独立负责一个服务
  2. 技术栈灵活,不同服务可以选择合适的技术栈
  3. 高可用,单个服务故障不会影响整个系统
  4. 弹性伸缩,不同服务可以根据流量独立扩容,节省资源

微服务的核心问题

  1. 服务发现:服务上线下线动态感知,客户端不需要硬编码服务地址,常见服务发现组件:Nacos、Consul、Eureka
  2. 服务治理:限流、降级、熔断,防止服务雪崩,常见组件:Sentinel、Hystrix、Resilience4j
  3. 分布式追踪:全链路追踪,排查分布式系统中的请求慢、错误问题,常见组件:SkyWalking、Jaeger、Zipkin
  4. 分布式事务:跨服务调用时保证数据一致性,常见解决方案:TCC、可靠消息最终一致性、Saga模式
  5. API网关:统一流量入口,做认证、鉴权、限流、监控、路由等,常见组件:Spring Cloud Gateway、Kong、APISIX

微服务最佳实践

  1. 服务拆分合理,按照领域边界拆分,避免拆分过细导致复杂度太高
  2. 服务自治,每个服务独立存储、独立部署,减少服务之间的耦合
  3. 接口兼容性,服务接口升级要向下兼容,避免影响消费者
  4. 完善的监控告警,分布式系统复杂度高,必须要有完善的可观测性,及时发现问题
  5. 自动化CICD,微服务数量多,必须要有自动化的构建、测试、部署流程,提升效率

分布式系统常见问题和应对

  1. 网络问题:网络延迟、丢包、分区是常态,必须做好重试、超时、熔断等容错机制,假设网络一定会出问题
  2. 一致性问题:优先使用最终一致性,只有必要的场景才用强一致,降低复杂度
  3. 幂等性:所有接口都要设计成幂等的,因为网络重试、消息重复是不可避免的
  4. 可观测性:完善的监控、日志、链路追踪是分布式系统排障的基础,没有观测性的分布式系统就是黑盒
  5. 故障演练:定期做故障注入演练,验证系统的容错能力,提前发现问题

分布式系统没有银弹,需要根据业务场景在性能、可用性、一致性、复杂度之间权衡,选择最合适的架构,不要为了分布式而分布式,适合业务的才是最好的。

思考问题

  1. 为什么分布式系统中优先保证AP而不是CP?什么场景下需要CP?
  2. 消息队列有什么作用?什么场景下需要使用消息队列?
  3. 缓存穿透、击穿、雪崩分别是什么?怎么解决?
  4. 微服务架构相比单体架构有什么优缺点?什么业务场景适合微服务?