一致性问题

正如我一直强调的,要解决一个问题,首先要精准的定义问题。现在就让我们先搞清楚一致性问题到底是什么?

在计算机科学领域,分布式一致性问题是一个相当重要,且被广泛论证与探索的问题。通常存在于分布式内存共享,分布式存储(例如:分布式文件系统,数据库,缓存)等分布式系统中。

问题原型,假设有下列场景:

节点n1和n2上存放着数据X的拷贝;

客户端A更新节点n1上的数据X;

一段时间之后,客户端从节点n2上读取数据X;

在这个场景中,客户端B从节点n2上是否可以读取到客户端A在节点n1上的数据更新取决于系统的实现,而这便是分布式一致性问题。

上面的场景就是一致性问题最常见的应用场景,简单概括为主从模型。一个数据中心,假如有5台机器,一主4备。了解数据库系统的同学应该知道,数据库的变化是由一条条SQL执行产生的,也就是说如果最初的5台数据一致,那么按照相同顺序执行相同的SQL,他们最终的数据也应该是一致的。

一致性问题解决的就是让所有机器可以按照一样的顺序执行相同的操作。

问题定义清楚了,接下来我们想想怎么解决这个问题?我们这里就介绍最基本也是最根源的解决方法。使用的例子还是数据库的主从模型。

1.强一致性:最简单粗暴的解决方式。(强同步模式)

如上图C表示Client,【P、S1、S2】构成一个同步组,P表示Primary node,S1,S2是两个secondary node,强同步模型的工作流程为C向P写数据,P向S1,S2转发,只有3个都写成功,才向C返回成功,否则写失败。这种模型对于append操作很容易实现,如果副本没有全部更新成功,向C返回失败即可,不必重新同步P和两个S的数据;但如果是overwrite,则如果在同步过程中部分成功,还要考虑数据的正确性。

同时,P向S1、S2同步的过程,可以进行优化,借鉴GFS的流水线复制方式(P->S1 &S1->S2),以便充分利用每个node的带宽资源。

这种强同步模式,要求主机必须把 Redolog 同步到备机之后,才能应答客户端,一旦主备之间出现网络抖动,或者备机宕机,则主机无法继续提供服务,这种模式实现了数据的强一致,但是牺牲了服务的可用性,且由于跨机房同步延迟过大使得跨机房的主备模式也变得不实用。

2. 最终一致性:在经过一个不一致窗口后,副本最终处于一致的状态。

如上图是一种简单的最终一致性实现模型,通过增加一组U(update)节点来实现。具体做法是,C的每次更新以binlog的方式顺序的追加到Update节点(多台来避免单点),然后Update节点定期(如10ms)的将binlog重放到三个副本上(N1,N2,N3)。三个副本可以同时提供读服务,读到的数据可能不是最新的,这就要求上层业务能容忍或者在上层做一些容错(如上层的业务每次会等待不一致窗口过去后再读取数据)。

如果在最终一致性的基础上要保证每次读能读到最新的数据,可在上述模型上做点小改进。

每次C更新到U上后,必须至少同步到一个group中的P上才能应答客户端,即P上的数据一定是最新的,系统的读请求由P节点来满足以保证每次读到的数据是最新的,付出的代价就是,两个从副本不能分担负载,使得P易成为热点,当P挂掉时,选择一个S成为新的P。

以上2种方式都是最简单的方式,只需要解决服务器之前的通信问题。主服务器按照顺序给从服务器发消息,成功的话接续发送下一个消息,失败的话重新发。(通信失败在这里不展开讨论了)

可是我们想想上面的方式有什么问题吗。对于第一种同步复制模式,互联网企业几乎肯定不会采用,牺牲了可用性,用户等待时间太长,不可接受。对于第二种异步复制模式,主机写本地成功后,就可以立即应答客户端,无需等待备机应答,这样一旦主机宕机无法启动,少量不同步的日志将丢失,这种模式实现了服务持续可用,但是牺牲了数据一致性。这两种方式对应的就是 Oracle 的 Max Protection 和 Max Performance 模式,而 Oracle 另一个最常用的 Max Availability 模式,则是一个折中,在备机无应答时退化为 MaxPerformance 模式,我认为本质上还是异步复制。

主备模式还有一个无法绕过的问题,就是选主,最简单山寨的办法,搞一个单点,定时 Select 一下主机和各个备机。一个改进的方案是使用类似 ZooKeeper 的多点服务替代单点,各个数据库机器上使用一个 Agent 与单点保持 Lease,主机 Lease 过期后,立即置为只读。改进的方案基本可以保证不会出现双主,而缺点是 ZooKeeper 的可维护性问题,以及多级 Lease 的恢复时长问题。(Lease : 租约,租期)

这种主备方式的系统在高可用问题有上述诸多缺陷,要改进这种数据同步方式,我们先来梳理下系统高可用的几个基本需求:

数据不丢失

服务持续可用

自动的主备切换

我们除了上面的主备方式解决一致性问题外,还有其他的方法解决这个问题吗。当然有,因为分布式系统中的每台机器之前都是可以相互通信的,只要相互直接可以通信,我们就可以使用一些算法或者说协议来解决每台机器的一致性问题。目前这种算法有很多,比较著名的有Paxos,gossip协议(redis3.0集群使用的一致性服务核心算法就是gossip)。

基本的系统架构就是下图:

客户端发送一个请求到某台机器,首先会到一致性服务软件提供的接口,一致性服务软件会和分布式系统中的其他机器通信,使用一致性算法的逻辑最终达到一致,然后再进行其他操作(比如这张图中接着进行持久化操作)。

具体流程大致就是上面描述的,好学的同学肯定会问这些一致性算法到底是怎么设计的,因为篇幅限制,关于paxos,gossip协议的具体逻辑我们下几篇再具体介绍。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180615G1CM5U00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券