QuXiao's Blog

Life && Tech && Thoughts

利用ETCD进行多Mater模块容灾

Written on

在进行模块线上部署的时候,为了增加服务的可用性、以及减少单个模块的响应压力,我们一般都会进行冗余部署。这些模块大多都是无状态的,只需要接收请求、业务处理、然后返回结果即可。但是,会有这样一些模块,他们需要进行一些『全局管理』的逻辑,例如周期性的任务执行,我们就暂且把这些模块叫做『Master模块』吧。他们不需要接收请求、又是逻辑上全局唯一的,那么因此线上有一套这样的模块运行着就行了。

那么,问题来了:如果这个模块异常退出了,或者所在的机器、网络出问题了,该怎么办?

如果有比较完善、及时的监控的话,能够尽早发现问题,修复并重启模块,或者在其它机器重新再部署一套,这样也是可以的。只不过需要人工介入,不够自动化、智能化。如果还是还是深夜发生了问题,难免还要爬起来处理,太伤了!于是乎就想到了用ETCD进行多个模块的选举,从而达到容灾的目的。

虽说ETCD的主要作用是进行多分布式的配置管理,各个接入放根据不同路径watch到路径下面的变化,以此进行配置的同步。另外,ETCD还提供了其它的一些操作,让我们可以进行多Master的选举,其中一个核心的操作就是 Atomic Compare-and-Swap (CAS)

简单的来说, Atomic Compare-and-Swap 就是:在判断ETCD客户端提供的数据符合某些条件的情况下,对某个key设置一个value。客户端所提供的条件包括:

  • key目前的值
  • key目前的Index
  • key是否存在

这边用到的 key目前的值 以及 key是否存在 这2个条件,那么,模块操作ETCD的流程就如下:

  • 启动时生成一个value,用于唯一标识自己
  • 对于一个实现设计好的key,尝试cas create kv ,并设置好过期时间TTL
    • 如果create不成功,则表明其它的Master模块已经抢占到了这个key(可以理解为这个模块的令牌),循环等待
    • 如果create成功,则自身抢占到了令牌,开始周期维护这个key
  • 每隔 TTL/2 时间,去cas update kv ,prevValue填写为自己的value,这样才能确保上一次也是自己去update的,否则会失败

就是这么简单。如果模块中途异常退出了, kv 会自动过期,然后被其它模块抢到。自己在维护这个kv的过程中,也能保证不会被其它模块抢占。

这种方案,实际上就是将Master模块对应的服务的可用性转嫁到了ETCD这个基础组件上面,只要ETCD集群能够正常工作,Master模块也就能正常工作,只需要将模块多地多机房的冗余部署,就可以大大降低服务不可用的概率,还是十分实用的,目前已经在团队的一些Master模块应用了这种方法。

comments powered by Disqus