Zk跨中心分布式协调

前言

要了解zk跨数据中心解决方案,先要了解以下几个问题:

  • 什么是顺序一致性
  • zk如何实现顺序一致性
  • 分布式协调服务常见的跨中心方案有哪些?如何在跨数据中心中保证顺序一致性?及各自的优缺点?

顺序一致性

任意一种可能的执行的结果在某一种所有处理器的操作按照顺序排列执行的结果一致,并且每个独立的处理器的操作都会按照程序指定的顺序出现在操作队列中。

ZK

zk是一个分布式协调服务组件,类似的有Chubby,Etcd等,zk实现的顺序一致性,依赖它可以实现锁逻辑。

zk如何保证顺序一致性呢?

  • write:实现了线性一致性write,通过zab实现了update的原子广播
  • read:实现了顺序一致性,一个client无论其链接到哪个节点(即使中间切换了链接节点),其读取的数据永远都不会比之前读到的旧,简单点说就是如果一个client看到版本数据为3的,就不会再读到比版本3数据更低的数据了。

zk的一致性操作流程:

  • zk的每个client和节点建立链接之后,实际上就是创建了一个session,每次read都会从此节点read数据,由于zab保证了各个副本操作复制的顺序一致性,一旦client发现某个节点可能下线,会尝试去链接其他节点,但会携带上已经最新的事务id:zxid,如果对端的最新zxid比client已知的新,那么建立链接,否则拒绝,这样保证了client不会链接到比自己状态旧的节点上。实际上每次server返回client请求的时候,都会将自己最新的zkid携带返回给client

  • follower在收到write请求之后,会转发给leader处理,为了保证顺序一致性,write返回之后read才能读到,follower server会等到这个write完成之后返回给client,这样保证即使update转发了leader完成,但仍然能在follower被read到,且之前的write也能被读到,从而保证了顺序一致性read

  • zk实现了线性读取,通过增加一个sync操作来保证follower read的时候会去leader上read最新的数据然后返回给follower,在返回给client。这里其实就是相当于将read转发给了leader处理,和etcd的follower read处理方法一致

raft实现的线性一致性read,要不只能从leader read,如果read request发送到了follower,但还是需要到leader来查最新commit index,然后read返回,实际上也是leader read。 就zk来说,write使用zab保持线性一致性,但是read就可以直接从folloewer read,而不需要任何leader参与,read性能就会比线性一致性好。

跨数据中心

单数据中心zk是顺序一致性的,如果跨数据中心呢?

Single Coordination Service

扩数据中心部署单个协调服务,每个数据中心都有协调服务的一个或多个副本。

协调服务的5个副本分别在3个数据中心部署,缺点是update会很慢,每次update都需要获取数据中心的多个副本的大多数投票同意,read可以很快,因为读取本地的副本即可,正确性没有问题,可用性很好,没有单点问题。

Learners

将所有的acceptors副本都部署在一个数据中心,其他的数据中心仅仅部署learner副本,仅仅接受数据复制,没有投票权,这种做法优点明显,部署accepeor的数据中心update很快,但是部署learner的数据中心update就需要通过learner转发给DC1的leader处理,是跨数据中心的,会比较慢,不过投票是数据中心内部的,相比第一种部署方式还是会快一些,正确性也没有问题,不过会存在单点问题,一旦部署acceptors的数据中心挂了,那么update服务就不可用了,或者DC1和DC2的网络被隔离了,那么DC2上的update也不可用了。

Multiple Coordination Services

每个数据中心部署自己的独立协调器,会将协调服务的数据切成不同的partition,存放在不同的数据中心,将数据按照一定的规则切分成两部分,每个数据中心仅仅负责自己partition数据的update操作,关于致部分的数据所有accepeors副本部署在本地数据中心,并且为了保证另外一个数据中心可以读到自己的数据,会在另外一个数据中心中部署一个自己的learner节点,另外一个数据中心从这个learner上读取数据。

自己负责的partition的update的投票在本地数据中心完成,性能会很好,不是自己负责partition通过learner转发到相应partition的数据中心的leader处理。 read操作,如果是自己负责的partition数据,任意acceptors副本都可以read,如果不是自己负责的partition数据,则从部署在自己数据的leaner去read,都在数据中心内完成,性能会很好。 任何一个数据中心挂掉,都只会影响这个数据中心负责的那部分数据,其他不会受到影响,但正确性不能得到保证,如: client1 操作DC1的zk,client2操作DC2的zk,初始化x=0,y=0,则显示的操作序列是不满足顺序一致性的,因为对client1和client2来说,看到x,y的value的顺序是不一致的:

client 1: x=0 -> x=5 -> y=0 -> y=3 client 2: y=0 -> y=3 -> x=0 -> x=5

client1看到x=5之后,才看到y=3,但是client2看到y=3之后才看到x=5,所以不满足顺序一致性。

Modular Composition

Multiple Coordination Services方案的问题在于,当client1 set(x,5)之后,执行get(y->0)(非本partition的数据),没能获取最新的y值,对于client2同理,get(x)->0没能获取x最新值,如果能够有什么方法拿到最新值,就可以解决问题。

看下Modular Composition的方案:

如果read的数据不是自己parititon负责的,会在read之前插入一个sync操作,和read一组一起组成sync read,其中sync操作会去相应partition的数据中心拉取最新的到当前数据中心learner,然后再从learner read,这样可以保证read的数据是最新的了。 这样可以保证client1还是client2看到的顺序是相同的了。 如果出现sync(x)和set(x)并发问题,比如set(x)在DC1上生效瞬间可能先于sync(x)或者晚于sync(x)都是可能的。

Modular Composition通过对Multiple Coordination Services简单的修改,实现了跨数据中心协调服务部署的正确性,基本延续了Multiple Coordination Services思想,自己负责partition数据,read/write都直接在数据中心内部完成,其他partition数据,read/write都是需要发送给其他数据中心处理,任何数据中心挂了,仅仅影响自己负责的partition的数据可用性。

总结

文中方案简单的讨论了跨数据中心的方案,但是在实际应用当中相信会有不同的解决方案会更适合自己的业务场景。

转载于:https://my.oschina.net/u/1000241/blog/3048553

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值