分布式系统 - 复制(二)

457 阅读6分钟

我们将对上一节各种数据复制架构存在的问题进行深入探讨,如果不清楚上一节的朋友请 “ 传送 ”了解下~ 分布式系统 - 复制(一)

同步复制与异步复制

如何进行数据复制,同步还是异步?这是一个值得考究的问题。

同步复制

上图中,Follower 1 是同步复制,也就意味着,当 Leader 接收到写入操作时会等待Follower 1 确认后才会向用户返回成功。

其优点是从节点保证与主节点一致的最新数据副本。如果主节点突然失效,我们可以确信这些数据仍能在从节点上找到。但缺点也很明显,如果在进行同步时,从节点由于各种异常状况( 宕机、网络延时等 )没有响应,主节点则需一直等待从节点恢复并阻止所有的写入。

异步复制

上图中,Follower 2 是异步复制,当主节点接收到用户请求,执行完则会直接返回。

其优点显而易见,即使所有的从节点都落后了,主节点也可以继续处理写入。但异步复制也会带来关于数据一致性的挑战。例如当主节点失效且不可恢复,则任何尚未复制给从节点的写入都会丢失。 这意味着即使已经向客户端确认成功,写入也不能保证持久 。稍后我们将会对持久性问题进行探讨。

同步与异步各有优点和缺点。在现有的大部分系统中,复制架构基本使用半同步,即如 paxos 算法的大多数同意法则,我们仅需大多数节点同步,其他则异步。来保证数据的可靠性与服务的高性能。

复制延迟问题

当从节点使用异步复制,如果从节点落后,则用户访问时可能会看到过时的信息。同时对主节点和从节点执行相同的查询,可能得到不同的结果。但等待一段时间后,从节点最终会赶上并与主节点保持一致。这种短暂的延迟称为**“ 最终一致性 ”**

紧接上文,由于现在系统中采用异步复制,则会由于最终一致性导致一些问题。接下来我们将深入探讨由它引起的三个复制延迟的问题。

一、读已之写 ( Reading Your Own Writes )

想象你刚在某网购买东西,当你支付完后,立马查看订单。但是由于某网内部从节点还未复制主节点的数据,导致你什么也没查到。钱花了,但没看到订单,你是不是很气愤。

在这种情况下,我们需要读写一致性来保证问题不会发生,也就是用户总能看到自己修改过的东西,但其他用户可能需要等一等。

那么,如何实现呢这种机制?

  • 在主节点读取用户自己的档案,在从节点读取其他用户的档案。
  • 如果大部分内容都可能被用户自己编辑,那上一条方法就没用了。在这种情况可以使用跟踪上次更新的时间,在上次更新后的一分钟内,从主节点读。另外,还可以监控从节点的复制延迟,防止对任意比主节点落后超过一分钟的从节点发出查询。
  • 可以让客户端记住最后一次写入的标记,系统需要确保从节点为该用户提供任何查询时,从节点内的标记和客户端的标记相同。如果当前从节点不够新,则可以从另一个从节点读,或者等待从节点追赶上来。如果用户跨平台( 手机、电脑 ) 同时访问,则事情变得复杂多了。我们可以可以为用户建立一个唯一Id 来标记哪些设备是一个用户。

二、单调读 ( Monotonic Reads )

想象有人给你转账,对方告诉你钱已经打给你了。然后你去查询,看到了余额 500,但是你点了一下刷新,余额变成 0,又刷新,余额又变成500。这时候你是不是就很抓狂。

为了解决这种“ 时光倒流 ”的问题。我们需要使用单调读-比强一致性弱,但比最终一致性强。来保证每个用户在顺序读取时只会从同一个节点中读取。

我们可以依靠对用户Id 进行哈希散列化等算法进行解决,但是要处理节点故障引发的无法访问问题。

三、一致性前缀读( Consistent Prefix Reads )

想象你在某聊天群内聊天,

你:A,你可以预测未来多久?

A: 大约10秒钟

但是由于网络原因,C看到的顺序为:

A: 大约10秒钟

你:A,你可以预测未来多久?

为了解决这种 “ 预测未来 ”的超能力,我们需要使用一致性前缀读来保障如果一系列写入按某个顺序发生,那么任何人读取这些写入时,也会看见它们以同样的顺序出现。这是分区数据库中的一个特殊问题,在分布式数据库中,不同的分区独立运行,因此不存在全局写入顺序:当用户从节点读取数据时,可能会看到节点的某些部分处于较旧的状态,而某些处于较新的状态。

我们可以确保任何因果相关的写入都写入相同的分区。对于某些无法高效完成这种操作的应用,还有一些显式跟踪因果依赖关系的算法。

如何处理宕机节点?

在这个纷杂的网络环境里,夸张来说可能由于自然灾害( 火山爆发、泥石流等 ),又或是停电,断网等故障导致服务宕机。我们如何处理集群中宕机的节点呢?

如何确认节点宕机

由于分布式环境的复杂,所以大多数系统只能使用发送心跳和超时来判断节点是否处于故障状态。

从节点宕机

这是一个比较好解决的问题,当一个从节点宕机后,主节点可以把从节点踢出正常集群,直到从节点完成数据同步后通知主节点。

主节点宕机

这个就比较复杂与棘手了。需要利用一致性共识算法(例如 Paxos,Raft)来推举一个从节点担任主节点,并且让所有节点达成共识。我们将在以后专门讲解。

总结

本次我们讲解了一下分布式复制机制中几个问题:

  • 是同步复制还是异步复制
  • 关于异步复制的三个延迟问题及解决办法
  • 如何处理宕机的节点

下节我们将会讲解有关分布式分区的相关知识。例如 Apache Kafka 就利用该理念解决水平扩展问题。