枫叶居

桃李春风一杯酒,江湖夜雨十年灯

0%

Raft协议

前言

分布式,很多初学者对这个词的第一印象——高大上技术范儿。抛开技术细节不谈,纵观后台技术的发展,存在着普遍适用的规律,一项新技术的诞生,总是解决一些现有架构无法解决的问题。如果读者凭空去学习分布式,便容易坠入云里雾里。本文作为笔者自己学习的一个梳理,以实际问题出发阐述了笔者对Raft协议的理解。本文并不对Raft协议的实现机制做详细的描述,只是从一个新手解决问题的角度去阐述Raft协议做了些什么,不正确的地方请读者指正(邮箱:dreamcatchwang1991@gmail.com)。

思考

以经典单数据库实例架构(这也是很多企业级应用的典型架构)为例,所有的业务数据均存储于单机数据库,当数据库实例Crash了以后,业务便受到影响,在大多数情况下,这种Crash对企业业务的影响是可控范的。然而在互联网应用中,哪怕是一分钟的Crash对企业来说也是致命的,比如前段时间,美团的外卖系统出现崩溃,整个服务停摆几个小时,造成大量用户流失到饿了么平台。

笔者尝试根据自己的经验去解决该问题,为了让单机数据库实例在Crash了以后,整个系统仍然保持可用,我们很容易想到的一个策略——冗余(比如你在单位请假了需要有人代替你继续工作而不影响业务)。我们增加了一台数据库实例B(原来的数据库实例用A表示),在实例A挂掉了之后,我们期望B可以代替A继续提供服务,*所以BA必须具备一样的数据**,在分布式里面这个称作一致性*Raft协议为**分布式一致性协议的一种实现,主要目标就是解决上述这类问题。

脱离现有的MySQLRedisKafka等高可用方案(因为这些系统为了性能而做出一些折中),我们根据自己的诉求,去设计一个高可用的存储系统,需要注意哪些问题呢?假设我们的存储系统有A,B,C等3个节点用来保持高可用,那我们该怎么保持A,B,C3个节点内数据的一致性呢?

  • 一致性由客户端保证还是服务端保证
  • 如何保证A,B,C或更多节点的数据一致性

首先分析第一个问题,假设一致性工作是由客户端保证的(客户端向A写入数据的同时向BC写入数据,为保证A,B,C的一致性,需A,B,C3个节点全部写入成功,客户端回才判定写入成功),我们可能会遇到如下情况:

  • B下线了一段时间又重新上线,因为客户端未保存B处于下线状态这段时间的数据,所以B中就会缺失这部分数据,因而B中数据会与AC中数据不一致。
  • 客户端向AC中写入数据成功,但向B中写入数据失败,这次写入应当被认定为失败(因为A,B,C中数据不一致,也无法通过其他途径达到一致),我们期望整个系统可以表现的犹如一个**事务**,要么全部成功,要么全部失败回滚修改,客户端无法提供这种机制。

综上,**由客户端保证数据的一致性是不可取的**。 

我们将一致性保证工作放在服务端实现,那么我们如何保证A,B,C三节点数据的一致性呢?首先我们思考一个问题,**我们无法预知A,B,C三个节点中哪个节点会意外挂掉,所以客户端不应该至同单一节点建立联系**,也就是说——A,B,C3个节点对外应当表现为一个整体,也就是集群Cluster。那么客户端该如何向A,B,C组成的集群写入数据?以下是笔者想到的实现方式:

  • 所有客户端均向A,B,C中某一节点(比如A)写入数据,由该节点将数据拷贝至其它节点以达到一致性。
  • 向建立连接的节点写入数据,比如客户端1A建立连接,客户端1A写入数据,客户端2B建立连接,客户端2B写入数据,以此类推。

读者是否觉得以上两种实现方式似曾相识——这和*并发编程**下的并发更改共享变量问题相似,由经验我们可知,我们最好是将对共享的操作串行,有序的***执行。同样,如果多个客户端通过多个节点向集群写入数据,为了达到每个节点都有一份完整数据的目的,多个节点间会进行通讯,数据合并,而这其中又牵扯了数据的顺序等许多问题,工程实现起来比较复杂。
当然不是说不可以,笔者没见过这么做的~ ~)

方式一为目前流行的一致性解决思路,Raft协议采用了该思路,Raft协议解决了方式一面临的两大问题:

  • 集群启动(或者写入节点下线)时,如何选举出一个节点作为写入节点
  • 写入节点如何与其它节点通讯,复制数据,保持数据在各节点的一致性

以上两大问题便是Raft协议的两大功能:

  • Leader Election
  • Log Replication

分布式中任何环节都是不可靠的,实际问题比本人论述的复杂的多,但明确了上述问题,再去研究Raft Paper时,读者便可以快速掌握Raft协议。

建议大家观看Raft协议动画,简单明了生动:http://thesecretlivesofdata.com/raft/

参考

[1] Raft Pager

坚持原创技术分享,您的支持将鼓励我继续创作!