分布式复制技术

复制:将数据拷贝一份至目标载体,目的是共享或冗余数据本身。远端的复制会涉及到数据通过网络进行传输,所以业界有不少技术来提升复制传输的性能和可靠性,例如P2P技术、CDN技术等。我们这里讲的分布式复制技术主要关注数据在多个节点之间传输的逻辑,不讨论传输层面上的优化。

分布式复制在两个节点之间可以分为两种复制形式:同步复制和异步复制。

同步复制:数据发送给目标节点后,需要等待节点返回确认成功,整个复制过程结束。

异步复制:数据发送给目标节点后,不需要等待节点返回确认成功,整个复制过程结束。

对一个分布式集群系统来说,一般我们可以将复制技术分为以下三种:

1、链式复制

2、树形复制

3、分发复制

链式复制

Client写入数据后,一个节点完成后转发至下一个节点,直到Tail节点完成写入,然后由Tail节点返回ACK给Client端,最终完成写入,Client端需要读取Tail节点才能保证读写一致性。

如下图所示:

由此可以得出链式复制的整体耗时:

TimeCost = rtt1/2 + io1 + rtt2/2 + io2 + rtt3/2 + io3 + rtt4/2

可以看出,如果某节点下IO卡顿将导致复制过程卡顿。在链式复制的发展过程中,工程化实现时进行了改进和优化,例如在HDFS的复制模型中,每个节点只需要等待下游节点写入成功且本地写入成功后就可以向上游返回,最后又Head节点向Client返回写成功的ACk。

由此可以得出优化的链式复制的整体耗时:

TimeCost = rtt1+ Max(io1, rtt2 + Max(io2, io3+rtt3))

可以看出,虽然这个改进优化了时延,但是依然需要所有节点写入完成才能向Client端返回,仍然会受到单节点下IO慢影响。

小结:在链式复制中,Client端需要读取Head节点才能保证读写一致性。由于链式复制要求所有节点能够写入成功才能返回,所以链式复制的写性能较低,链式复制适用于高吞吐量和强一致性要求的场景(高并发读,牺牲了写性能导致写性能低)。对于一个集群而言,如果最大允许F个节点故障,在链式复制模式中,需要配置F+1个节点。

树形复制

树形复制的出现是为了优化链式复制需要全部节点写入成功后才返回的缺点。Client端先选择一个节点作为主节点,然后向主节点发起写入,主节点再向其他节点转发。所有节点的大多数总计(N+1)/2节点写成功后,主节点即可向Client端返回写成功。但是,为了防止主节点还未写入就已经满足了大多数,此时Client向主节点读取的是老旧数据,一般可以做以下两个方面的改进:

  • 主节点必须写入成功后,集群整体满足大多数才向Client返回;
  • 主节点配置缓存(保证读到新数据),整体写入数量满足大多数后,可以向Client返回,不等待主节点写入完成。

由此可以得出树形复制的整体耗时:

TimeCost = rtt1 + Max(io1, Min(rtt2 + io2,  rtt3 + io3))

可以看出,树形复制解除了等待所有节点写成功的约束,但是必须等待主节点的写入成功(不配置缓存),如果主节点出现卡顿,则整体的写入耗时会较高。

小结:在树形复制中,Client选择一个节点作为主节点,由主节点进行写IO的分发。由于存在异步复制,则可能出现集群中的节点数据不一致的情况,在故障恢复时,需要确认最新的数据所在,并完成节点间的数据同步后才能对外提供新的服务。整个一致性的保障需要引入PAXOS或者RAFT这样的算法的来保障。无论PAXOS还是RAFT均实现了一个复制状态机:

客户端在面对任何一个副本时都具备完全一致的访问行为,每个副本在执行请求时都需要按照完全一致的顺序来进行。

分发复制

所谓分发复制是指参与复制中所有节点都是对等的,Client直接向各个节点直接进行分发写入,节点之间并不进行通信复制,只要写入多数节点成功,就判为写入成功。如下图所示:

分发复制虽然一定程度上可以容忍单节点慢问题,但是引入了下面两个问题:

  • 不能同时有多个Client写入,否则会产生数据不一致问题。通常是选择一个Writer,避免同时写的发生,从而保证数据一致性。
  • 由于仍然存在异步写问题,读操作无法确认那个节点上的数据是最新的,Reader只能读取所有节点,然后通过数据的版本号来区分数据的新旧。

小结:分发复制同样会引入数据不一致问题,需要引入配套技术来解决,例如分发复制通常应用成为NRW模型,关于NRW模型可以参考:https://coolshell.cn/articles/10910.html

总结:

分布式复制技术总体来讲可以概括为上面的三类,但是由于分布式系统流程复杂,网络节点故障等需要作为常态化处理,导致理论在工程化的时候远比想象的复杂,需要做相应的挑战和配套一定的适配,开发过分布式系统人相信对此深有体会。