分布式系统是由 多个 独立的计算机或者节点组成的系统,这些计算机通过网络进行通信和协作,共同完成特定的任务或提供服务。

分布式系统的设计目标是:提高系统的性能、可伸缩性、可靠性和可用性,以及实现系统资源的有效利用。

接下来,主要围绕 如何学习分布式系统 来讨论

分布式系统解决了什么问题?

为什么要引入分布式系统?

在传统单体架构下,存在以下问题:

  • 可用性低:一个机器挂了,整个服务就不可用了
  • 扩展性成本高:单个机器的性能提升是比较有限的,升级成本高

因此,引入分布式系统,来解决单体架构下的 可用性问题扩展成本问题

那么分布式系统是如何解决这两个问题的呢?

简单理解:就是通过网络,将许多物理机连起来,组成一个集群,对外提供服务,并通过在系统中提供冗余来保障可用性

分布式系统带来了什么问题

整个分布式系统具有多个物理节点,那么如何协调这些节点,就是一个比较重要的问题

我们将分布式系统分为两类:

  • 分布式计算
  • 分布式存储

分布式计算带来了什么问题

如何找到服务

在整个分布式系统中,物理节点间的身份可能不同

那么节点间如何发现彼此呢?

常见的解决方案是「服务注册与发现」

实现这个功能,通常需要一个「服务注册中心」

  • 服务注册:当一个服务启动时,它会向服务注册中心注册自己的信息,包括服务名称、IP 地址、端口号等。注册中心会将这些信息保存起来,以便其他服务或客户端查询。
  • 服务发现:当一个服务需要调用其他服务时,它会向服务发现组件发送查询请求,询问特定服务的位置信息。服务发现组件会从注册中心获取服务的信息,并将其返回给请求方,使得请求方能够直接与目标服务通信。

image

如何找到(实例)节点

确定了服务以后,如何确定将当前请求路由到哪个节点上呢?

分两种情况:

  • 无状态:同一个服务之间,每个(实例)节点完全一致,例如 Redis 集群,主从节点存储数据(几乎)一致
  • 有状态:同一个服务之间,(实例)节点不完全一致,例如 Redis 集群,主节点之间存储的数据不一致

对于「无状态」这种情况,做好普通的负载均衡就 ok 了,例如:

  • 简单的轮询机制
  • 一致性哈希
  • fair 公平调度

对于「有状态」这种情况,由于节点间不一致,这种情况通常需要一个「路由服务」,因提前确定要请求的数据在哪个节点上,然后再访问

如何避免服务雪崩

一个服务内,某个节点挂了,那么该节点负责的请求就会打到其它节点上

如果剩余节点中,有一个节点因为承受不了多的请求,挂了,那么该节点负责的请求又会打到其它节点上

如此循环,导致整个服务的节点依次挂掉,就像「雪崩」一样

如何避免?

整体分为两个思路:

  • 快速失败与降级机制:服务降级、熔断机制、限流
  • 弹性扩容:添加新的节点到服务中

快速失败会导致部分请求无法正确响应

而弹性扩容成本较高,并且扩容这个过程本身需要时间

如何监控告警

对于分布式系统,如果我们不知道整个系统的负载情况(状态),那么整个系统的可用性是无法得到保障的

可以监控某个接口的时延、成功响应数

也可以监控整个系统的负载,并在高负载时告警

分布式存储带来了什么问题?

CAP 理论

CAP 理论是分布式系统设计中的一个重要理论,描述了分布式系统中三个核心属性之间的冲突:

  • 一致性(Consistency):即所有的节点在同一时间具有相同的数据视图。在一致性模型中,如果一个操作在一个节点上执行成功后,其他节点上的数据也应该立即变为一致。
  • 可用性(Availability):即系统能够对用户的请求做出响应,即使系统中的一部分组件出现故障。在可用性模型中,系统在出现故障时仍然能够继续对外提供服务。
  • 分区容错性(Partition Tolerance):即系统能够容忍网络分区(分布式系统中节点之间的通信可能出现故障),而不会导致系统的整体性能下降。在分区容错性模型中,系统能够在网络分区的情况下继续运行,并且不会受到太大影响。

一般来说,C 和 A 无法同时保障:

  • 保证强一致性 C,那么在数据同步期间,整个服务无法读取(避免读到过期数据)

  • 保证高可用性 A,那么即使数据未同步完毕,也要对外提供服务,弱一致性保障

  • 对于银行这类系统,一致性非常重要,保障 CP;

  • 对于互联网应用,可能不需要强一致性,最终一致就行,保障 AP

如何做数据分片

随着数据量的增加,单机肯定无法存储所有数据,因此需要将数据分配到多个节点存储

常见分片方式:

  • 范围分片
  • 哈希分片
  • 一致性哈希分片

如何做节点间数据复制

为了保障可用性:即使一个节点挂了,它所负责的数据也要能获取到

可用性的保障,是基于数据的冗余存储的

那么如何将数据复制到其它节点呢?

  • 中心化方案(主从复制、一致性协议比如 Raft)
  • 去中心化方案

这两种方案,对外表现的一致性是不同的

如何实现分布式事务

要实现事务,首先需要有对并发事务进行排序的能力,这样在事务冲突的时候,确认哪个事务提供成功,哪个事务提交失败。

对于单机系统,只需要 时间戳 + TxID 即可

但是分布式系统,每个节点的时间肯定无法完全同步,这种方式就不太行了

不过可以 整体分布式,局部单体 来实现:用一台机器负责生成 时间戳 + TxID

这种方式在节点到中心节点的 距离较短 还可以,但是,如果节点到中心节点的距离较长,那么请求的 TTL 可能就不太能够接受了,时间成本太高

总结

学习分布式系统,可以从以下问题入手:

  • 如何实现服务注册、服务发现
  • 如何将请求路由到正确的节点
  • 如何监控集群状态
  • C、A 如何做权衡(trade-off)
  • 如何做数据分片
  • 数据如何同步(复制)到各个节点
  • 如何实现分布式事务

进一步地,可以:

  • 从实践出发:学习 MySQL(传统关系型数据库)、Redis(分布式缓存)、Kafka(分布式 MQ)的分布式实现方式
  • 从理论出发:学习 MIT-6.824

参考资料