现在的系统架构设计中,基本所有的业务服务( 例如 Spring Boot 等构建的服务 )都是无状态( Stateless Service )的,由于服务不进行状态存储,所以我们可以简单的水平或垂直扩展,继而演变成微服务化等。
但是当我们需要对有状态的服务( 例如数据库等 )进行扩展时,就会面临许许多多的问题,这次我们将讨论分布式系统所需要的复制机制。
为什么需要复制数据?
参考上图,想象一下,如果你部署了多个数据库,他们互相不通信,会发生什么?
不可以容忍的错乱数据
通过Nginx的负载均衡使得用户请求被路由至不同的业务服务,但由于每个数据库内的数据都是不相同的,导致用户每次访问数据时可能不相同。
复制数据进行分布式部署的好处?
- 使你的数据离用户更近,从而降低延迟
- 在一个节点崩溃后可以由其他节点担负职责,实现高可用
- 多节点部署可提升服务吞吐量
- ...
状态转移??复制状态机??
接下来我们讲解下现在主流的复制机制的实现:
状态转移
状态转移是最简单和易于理解的。就是把节点 A 的所有状态直接复制一份传输给节点 B ,从而实现复制机制。
但是现实应用中,一个服务的状态数据可能是 GB, TB 级别的,想实现状态转移非常困难。
复制状态机
因此,大家就想到了复制状态机。想要理解复制状态机,就要先了解什么是内部操作和外部操作。
当一个服务只执行内部操作的时候,他们的状态是确定的,只有当外部干涉时才会产生不同的结果,复制状态机的思想就是同步所有的外部操作来实现复制机制。
领导者和追随者复制 ( Leader-Follower replication )
- 节点中的一位被指定为领导者(leader),客户端只能将请求发送给领导者,领导者会将新数据写入其本地存储。
- 其余节点被称为追随者(followers)。每当领导者将新数据写入本地存储时,它也会将数据变更发送给所有的追随者。每个跟随者从领导者拉取日志,并相应更新其本地数据库副本,方法是按照领导者处理的相同顺序应用所有写入。
- 当客户想要从节点中读取数据时,它可以向领导者或追随者查询。 但只有领导者才能接受写操作(从客户端的角度来看从节点都是只读的)。
多领导者复制( Multi-Leader Replication )
虽然现在最常用的方法是单领导者架构,但领导者可能出于任何原因(例如和主节点之间的网络连接中断)无法连接到主节点, 导致无法向领导节点写入。
日后我们我讲解通过 Leader 选举解决这个问题
有趣的选择是你可以选择多领导者的架构。
- 在多领导者的架构中,每个领导者要同时扮演领导者和追随者的角色向其他领导者同步数据。
无领导者复制 (Leaderless Replication)
打破传统复制机制的限制,放弃领导者概念,并且允许任何副本直接接受来自客户端的写入。实现 Dynamic 机制( 可以根据侧重读或写来调整法定人数中的 w 和 r的值 )
我想大概该思想基于 Paxos algorithm 提出的大多数决议和版本号来进行控制。
quorum-write or quorum-read: 在一个有 n 个节点的数据库集群中,我们把读写请求同时发往所有节点。我们定义“w”为写操作成功的节点数,“r”为读操作成功的节点数;只要 w + r > n,我们就能确定集群中至少有1个节点是在读操作时返回了最新数据的,因为读操作的节点集合和写操作的节点集合必然有交集。
-
客户端写入或读取时进行并发写入或读取并等待节点返回确认后进行统计,如果确认人数超过法定人数( quorum-write or quorum-read),则认定此次操作成功
-
读操作发现有低版本的值将会对其进行更新。
总结
此次我们初窥分布式的复制机制。状态转移和复制状态机的概念,了解了领导者和追随者复制,多领导者复制,无领导者复制的架构模式。
但是这次过于乐观的没有提起由于分布式系统导致的各种一致性和错误问题。我们将在下次深入了解上述复制机制,并且解决或避免可能出现的各种问题。