分布式键值存储系统ETCD调研

分布式键值存储系统ETCD调研 html

简介

etcd是一个开源的分布式键值存储工具——为CoreOS集群提供配置服务、发现服务和协同调度。Etcd运行在集群的每一个coreos节点上,能够保证coreos集群的稳定,可靠的运行。当集群网络出现动荡,或者当前master节点出现异常时,etcd能够进行master节点的选举工做,同时恢复集群中损失的数据。 算法

 

目的: apache

一个高可用的 Key/Value 存储系统,主要用于分享配置和服务发现 安全

接口: 服务器

REST接口(HTTP+JSON)方便集群中每个主机访问 网络

功能: 多线程

提供了key/value存储服务,集群队列同步服务,观察一个key的数值变化,以及查询历史key值信息等 架构

分布式协议: app

Raft一致性协议。提供强一致性保证 负载均衡

部署形态: 

采用小集群(etcd server节点组成一个集群)+大集群(其它节点来直接使用服务)的形式,集群能够达到上千节点

实现语言: 

go 拥有几乎不输于C的效率,特别是go语言自己就是面向多线程,进程通讯的语言。在小规模集群中性能很是突出

 

摘自:http://www.infoq.com/cn/articles/etcd-interpretation-application-scenario-implement-principle

经典应用场景

要问etcd是什么?不少人第一反应多是一个键值存储仓库,却没有重视官方定义的后半句,用于配置共享和服务发现。

A highly-available key value store for shared configuration and service discovery.

实际上,etcd做为一个受到ZooKeeper与doozer启发而催生的项目,除了拥有与之相似的功能外,更专一于如下四点。

简单:基于HTTP+JSON的API让你用curl就能够轻松使用。

安全:可选SSL客户认证机制。

快速:每一个实例每秒支持一千次写操做。

可信:使用Raft算法充分实现了分布式。

随着云计算的不断发展,分布式系统中涉及到的问题愈来愈受到人们重视。受阿里中间件团队对ZooKeeper典型应用场景一览一文的启发,笔者根据本身的理解也总结了一些etcd的经典使用场景。让咱们来看看etcd这个基于Raft强一致性算法的分布式存储仓库能给咱们带来哪些帮助。

值得注意的是,分布式系统中的数据分为控制数据和应用数据。使用etcd的场景默认处理的数据都是控制数据,对于应用数据,只推荐数据量很小,可是更新访问频繁的状况

 

场景一:服务发现(Service Discovery)

服务发现要解决的也是分布式系统中最多见的问题之一,即在同一个分布式集群中的进程或服务,要如何才能找到对方并创建链接。

本质上来讲,服务发现就是想要了解集群中是否有进程在监听udp或tcp端口,而且经过名字就能够查找和链接。

要解决服务发现的问题,须要有下面三大支柱,缺一不可。

  1. 一个强一致性、高可用的服务存储目录。基于Raft算法的etcd天生就是这样一个强一致性高可用的服务存储目录。
  2. 一种注册服务和监控服务健康状态的机制。用户能够在etcd中注册服务,而且对注册的服务设置key TTL,定时保持服务的心跳以达到监控健康状态的效果。
  3. 一种查找和链接服务的机制。经过在etcd指定的主题下注册的服务也能在对应的主题下查找到。为了确保链接,咱们能够在每一个服务机器上都部署一个Proxy模式的etcd,这样就能够确保能访问etcd集群的服务都能互相链接。

图1 服务发现示意图

 

下面咱们来看服务发现对应的具体场景。

微服务协同工做场景

微服务协同工做架构中,服务动态添加。随着Docker容器的流行,多种微服务共同协做,构成一个相对功能强大的架构的案例愈来愈多。透明化的动态添加这些服务的需求也日益强烈。经过服务发现机制,在etcd中注册某个服务名字的目录,在该目录下存储可用的服务节点的IP。在使用服务的过程当中,只要从服务目录下查找可用的服务节点去使用便可。

图2 微服务协同工做

云平台多实例透明化

PaaS平台中应用多实例与实例故障重启透明化。PaaS平台中的应用通常都有多个实例,经过域名,不只能够透明的对这多个实例进行访问,并且还能够作到负载均衡。可是应用的某个实例随时都有可能故障重启,这时就须要动态的配置域名解析(路由)中的信息。经过etcd的服务发现功能就能够轻松解决这个动态配置的问题。

图3 云平台多实例透明化

 

场景二:消息发布与订阅

在分布式系统中,最适用的一种组件间通讯方式就是消息发布与订阅。即构建一个配置共享中心,数据提供者在这个配置中心发布消息,而消息使用者则订阅他们关心的主题,一旦主题有消息发布,就会实时通知订阅者。经过这种方式能够作到分布式系统配置的集中式管理与动态更新。

应用中用到的一些配置信息放到etcd上进行集中管理。这类场景的使用方式一般是这样:应用在启动的时候主动从etcd获取一次配置信息,同时,在etcd节点上注册一个Watcher并等待,之后每次配置有更新的时候,etcd都会实时通知订阅者,以此达到获取最新配置信息的目的。

  • 分布式搜索服务中,索引的元信息和服务器集群机器的节点状态存放在etcd中,供各个客户端订阅使用。使用etcd的key TTL功能能够确保机器状态是实时更新的。
  • 分布式日志收集系统。这个系统的核心工做是收集分布在不一样机器的日志。收集器一般是按照应用(或主题)来分配收集任务单元,所以能够在etcd上建立一个以应用(主题)命名的目录P,并将这个应用(主题相关)的全部机器ip,以子目录的形式存储到目录P上,而后设置一个etcd递归的Watcher,递归式的监控应用(主题)目录下全部信息的变更。这样就实现了机器IP(消息)变更的时候,可以实时通知到收集器调整任务分配。
  • 系统中信息须要动态自动获取与人工干预修改信息请求内容的状况。一般是暴露出接口,例如JMX接口,来获取一些运行时的信息。引入etcd以后,就不用本身实现一套方案了,只要将这些信息存放到指定的etcd目录中便可,etcd的这些目录就能够经过HTTP的接口在外部访问。

图4 消息发布与订阅

场景三:负载均衡

场景一中也提到了负载均衡,本文所指的负载均衡均为软负载均衡。分布式系统中,为了保证服务的高可用以及数据的一致性,一般都会把数据和服务部署多份,以此达到对等服务,即便其中的某一个服务失效了,也不影响使用。由此带来的坏处是数据写入性能降低,而好处则是数据访问时的负载均衡。由于每一个对等服务节点上都存有完整的数据,因此用户的访问流量就能够分流到不一样的机器上。

  • etcd自己分布式架构存储的信息访问支持负载均衡。etcd集群化之后,每一个etcd的核心节点均可以处理用户的请求。因此,把数据量小可是访问频繁的消息数据直接存储到etcd中也是个不错的选择,如业务系统中经常使用的二级代码表(在表中存储代码,在etcd中存储代码所表明的具体含义,业务系统调用查表的过程,就须要查找表中代码的含义)。
  • 利用etcd维护一个负载均衡节点表。etcd能够监控一个集群中多个节点的状态,当有一个请求发过来后,能够轮询式的把请求转发给存活着的多个状态。相似KafkaMQ,经过ZooKeeper来维护生产者和消费者的负载均衡。一样也能够用etcd来作ZooKeeper的工做。

图5 负载均衡

场景四:分布式通知与协调

这里说到的分布式通知与协调,与消息发布和订阅有些类似。都用到了etcd中的Watcher机制,经过注册与异步通知机制,实现分布式环境下不一样系统之间的通知与协调,从而对数据变动作到实时处理。

实现方式一般是这样:不一样系统都在etcd上对同一个目录进行注册,同时设置Watcher观测该目录的变化(若是对子目录的变化也有须要,能够设置递归模式),当某个系统更新了etcd的目录,那么设置了Watcher的系统就会收到通知,并做出相应处理。

  • 经过etcd进行低耦合的心跳检测。检测系统和被检测系统经过etcd上某个目录关联而非直接关联起来,这样能够大大减小系统的耦合性。
  • 经过etcd完成系统调度。某系统有控制台和推送系统两部分组成,控制台的职责是控制推送系统进行相应的推送工做。管理人员在控制台做的一些操做,其实是修改了etcd上某些目录节点的状态,而etcd就把这些变化通知给注册了Watcher的推送系统客户端,推送系统再做出相应的推送任务。
  • 经过etcd完成工做汇报。大部分相似的任务分发系统,子任务启动后,到etcd来注册一个临时工做目录,而且定时将本身的进度进行汇报(将进度写入到这个临时目录),这样任务管理者就可以实时知道任务进度。

图6 分布式协同工做

场景五:分布式锁

由于etcd使用Raft算法保持了数据的强一致性,某次操做存储到集群中的值必然是全局一致的,因此很容易实现分布式锁。锁服务有两种使用方式,一是保持独占,二是控制时序。

  • 保持独占即全部获取锁的用户最终只有一个能够获得。etcd为此提供了一套实现分布式锁原子操做CAS(CompareAndSwap)的API。经过设置prevExist值,能够保证在多个节点同时去建立某个目录时,只有一个成功。而建立成功的用户就能够认为是得到了锁。
  • 控制时序,即全部想要得到锁的用户都会被安排执行,可是得到锁的顺序也是全局惟一的,同时决定了执行顺序。etcd为此也提供了一套API(自动建立有序键),对一个目录建值时指定为POST动做,这样etcd会自动在目录下生成一个当前最大的值为键,存储这个新的值(客户端编号)。同时还可使用API按顺序列出全部当前目录下的键值。此时这些键的值就是客户端的时序,而这些键中存储的值能够是表明客户端的编号。

图7 分布式锁

场景六:分布式队列

分布式队列的常规用法与场景五中所描述的分布式锁的控制时序用法相似,即建立一个先进先出的队列,保证顺序。

另外一种比较有意思的实现是在保证队列达到某个条件时再统一按顺序执行。这种方法的实现能够在/queue这个目录中另外创建一个/queue/condition节点。

  • condition能够表示队列大小。好比一个大的任务须要不少小任务就绪的状况下才能执行,每次有一个小任务就绪,就给这个condition数字加1,直到达到大任务规定的数字,再开始执行队列里的一系列小任务,最终执行大任务。
  • condition能够表示某个任务在不在队列。这个任务能够是全部排序任务的首个执行程序,也能够是拓扑结构中没有依赖的点。一般,必须执行这些任务后才能执行队列中的其余任务。
  • condition还能够表示其它的一类开始执行任务的通知。能够由控制程序指定,当condition出现变化时,开始执行队列任务。

图8 分布式队列

场景七:集群监控与Leader竞选

经过etcd来进行监控实现起来很是简单而且实时性强。

  1. 前面几个场景已经提到Watcher机制,当某个节点消失或有变更时,Watcher会第一时间发现并告知用户。
  2. 节点能够设置TTL key,好比每隔30s发送一次心跳使表明该机器存活的节点继续存在,不然节点消失。

    这样就能够第一时间检测到各节点的健康状态,以完成集群的监控要求。

    另外,使用分布式锁,能够完成Leader竞选。这种场景一般是一些长时间CPU计算或者使用IO操做的机器,只须要竞选出的Leader计算或处理一次,就能够把结果复制给其余的Follower。从而避免重复劳动,节省计算资源。

    这个的经典场景是搜索系统中创建全量索引。若是每一个机器都进行一遍索引的创建,不但耗时并且创建索引的一致性不能保证。经过在etcd的CAS机制同时建立一个节点,建立成功的机器做为Leader,进行索引计算,而后把计算结果分发到其它节点。

    图9 Leader竞选

    场景八:为何用etcd而不用ZooKeeper?

    阅读了"ZooKeeper典型应用场景一览"一文的读者可能会发现,etcd实现的这些功能,ZooKeeper都能实现。那么为何要用etcd而非直接使用ZooKeeper呢?

    相较之下,ZooKeeper有以下缺点:

  3. 复杂。ZooKeeper的部署维护复杂,管理员须要掌握一系列的知识和技能;而Paxos强一致性算法也是素来以复杂难懂而闻名于世;另外,ZooKeeper的使用也比较复杂,须要安装客户端,官方只提供了Java和C两种语言的接口。
  4. Java编写。这里不是对Java有偏见,而是Java自己就偏向于重型应用,它会引入大量的依赖。而运维人员则广泛但愿保持强一致、高可用的机器集群尽量简单,维护起来也不易出错。
  5. 发展缓慢。Apache基金会项目特有的"Apache Way"在开源界饱受争议,其中一大缘由就是因为基金会庞大的结构以及松散的管理致使项目发展缓慢。

    而etcd做为一个后起之秀,其优势也很明显。

  6. 简单。使用Go语言编写部署简单;使用HTTP做为接口使用简单;使用Raft算法保证强一致性让用户易于理解
  7. 数据持久化。etcd默认数据一更新就进行持久化。
  8. 安全。etcd支持SSL客户端安全认证。

    最后,etcd做为一个年轻的项目,真正告诉迭代和开发中,这既是一个优势,也是一个缺点。优势是它的将来具备无限的可能性,缺点是没法获得大项目长时间使用的检验。然而,目前CoreOS、Kubernetes和CloudFoundry等知名项目均在生产环境中使用了etcd,因此总的来讲,etcd值得你去尝试。

     

    etcd实现原理解读

    上一节中,咱们归纳了许多etcd的经典场景,这一节,咱们将从etcd的架构开始,深刻到源码中解析etcd。

    架构

    图10 etcd架构图

    从etcd的架构图中咱们能够看到,etcd主要分为四个部分。

  • HTTP Server: 用于处理用户发送的API请求以及其它etcd节点的同步与心跳信息请求。
  • Store:用于处理etcd支持的各种功能的事务,包括数据索引、节点状态变动、监控与反馈、事件处理与执行等等,是etcd对用户提供的大多数API功能的具体实现。
  • Raft:Raft强一致性算法的具体实现,是etcd的核心。
  • WAL:Write Ahead Log(预写式日志),是etcd的数据存储方式。除了在内存中存有全部数据的状态以及节点的索引之外,etcd就经过WAL进行持久化存储。WAL中,全部的数据提交前都会事先记录日志。Snapshot是为了防止数据过多而进行的状态快照;Entry表示存储的具体日志内容。

一般,一个用户的请求发送过来,会经由HTTP Server转发给Store进行具体的事务处理,若是涉及到节点的修改,则交给Raft模块进行状态的变动、日志的记录,而后再同步给别的etcd节点以确认数据提交,最后进行数据的提交,再次同步。

 

新版etcd重要变动列表

  • 得到了IANA认证的端口,2379用于客户端通讯,2380用于节点通讯,与原先的(4001 peers / 7001 clients)共用。
  • 每一个节点可监听多个广播地址。监听的地址由原来的一个扩展到多个,用户能够根据需求实现更加复杂的集群环境,如一个是公网IP,一个是虚拟机(容器)之类的私有IP。
  • etcd能够代理访问leader节点的请求,因此若是你能够访问任何一个etcd节点,那么你就能够无视网络的拓扑结构对整个集群进行读写操做。
  • etcd集群和集群中的节点都有了本身独特的ID。这样就防止出现配置混淆,不是本集群的其余etcd节点发来的请求将被屏蔽。
  • etcd集群启动时的配置信息目前变为彻底固定,这样有助于用户正确配置和启动。
  • 运行时节点变化(Runtime Reconfiguration)。用户不须要重启 etcd 服务便可实现对 etcd 集群结构进行变动。启动后能够动态变动集群配置。
  • 从新设计和实现了Raft算法,使得运行速度更快,更容易理解,包含更多测试代码。
  • Raft日志如今是严格的只能向后追加、预写式日志系统,而且在每条记录中都加入了CRC校验码。
  • 启动时使用的_etcd/* 关键字再也不暴露给用户
  • 废弃集群自动调整功能的standby模式,这个功能使得用户维护集群更困难。
  • 新增Proxy模式,不加入到etcd一致性集群中,纯粹进行代理转发。
  • ETCD_NAME(-name)参数目前是可选的,再也不用于惟一标识一个节点。
  • 摒弃经过配置文件配置 etcd 属性的方式,你能够用环境变量的方式代替。
  • 经过自发现方式启动集群必需要提供集群大小,这样有助于用户肯定集群实际启动的节点数量。

 

etcd概念词汇表

  • Raft:etcd所采用的保证分布式系统强一致性的算法。
  • Node:一个Raft状态机实例。
  • Member: 一个etcd实例。它管理着一个Node,而且能够为客户端请求提供服务。
  • Cluster:由多个Member构成能够协同工做的etcd集群。
  • Peer:对同一个etcd集群中另一个Member的称呼。
  • Client: 向etcd集群发送HTTP请求的客户端。
  • WAL:预写式日志,etcd用于持久化存储的日志格式。
  • snapshot:etcd防止WAL文件过多而设置的快照,存储etcd数据状态。
  • Proxy:etcd的一种模式,为etcd集群提供反向代理服务。
  • Leader:Raft算法中经过竞选而产生的处理全部数据提交的节点。
  • Follower:竞选失败的节点做为Raft中的从属节点,为算法提供强一致性保证。
  • Candidate:当Follower超过必定时间接收不到Leader的心跳时转变为Candidate开始竞选。
  • Term:某个节点成为Leader到下一次竞选时间,称为一个Term。
  • Index:数据项编号。Raft中经过Term和Index来定位数据。

 

 

 集群启动

etcd做为一个高可用键值存储系统,天生就是为集群化而设计的。因为Raft算法在作决策时须要多数节点的投票,因此etcd通常部署集群推荐奇数个节点,推荐的数量为三、5或者7个节点构成一个集群。

etcd有三种集群化启动的配置方案,分别为静态配置启动、etcd自身服务发现、经过DNS进行服务发现。

经过配置内容的不一样,你能够对不一样的方式进行选择。值得一提的是,这也是新版etcd区别于旧版的一大特性,它摒弃了使用配置文件进行参数配置的作法,转而使用命令行参数或者环境变量的作法来配置参数。

 

静态配置

这种方式比较适用于离线环境,在启动整个集群以前,你就已经预先清楚所要配置的集群大小,以及集群上各节点的地址和端口信息。那么启动时,你就能够经过配置initial-cluster参数进行etcd集群的启动。

若是你所在的网络环境配置了多个etcd集群,为了不意外发生,最好使用-initial-cluster-token参数为每一个集群单独配置一个token认证。这样就能够确保每一个集群和集群的成员都拥有独特的ID。

 

etcd自发现模式

 

 

DNS自发现模式

 

 

Proxy模式

Proxy模式也是新版etcd的一个重要变动,etcd做为一个反向代理把客户的请求转发给可用的etcd集群。这样,就能够在每一台机器都部署一个Proxy模式的etcd做为本地服务,若是这些etcd Proxy都能正常运行,那么服务发现必然是稳定可靠的。

图11 Proxy模式示意图

因此Proxy并非直接加入到符合强一致性的etcd集群中,也一样的,Proxy并无增长集群的可靠性,固然也没有下降集群的写入性能。

Proxy取代Standby模式的缘由

那么,为何要有Proxy模式而不是直接增长etcd核心节点呢?

实际上etcd每增长一个核心节点(peer),都会增长Leader节点必定程度的包括网络、CPU和磁盘的负担,由于每次信息的变化都须要进行同步备份。增长etcd的核心节点可让整个集群具备更高的可靠性,可是当数量达到必定程度之后,增长可靠性带来的好处就变得不那么明显,反却是下降了集群写入同步的性能。所以,增长一个轻量级的Proxy模式etcd节点是对直接增长etcd核心节点的一个有效代替。

熟悉0.4.6这个旧版本etcd的用户会发现,Proxy模式其实是取代了原先的Standby模式。Standby模式除了转发代理的功能之外,还会在核心节点由于故障致使数量不足的时候,从Standby模式转为正常节点模式。而当那个故障的节点恢复时,发现etcd的核心节点数量已经达到的预先设置的值,就会转为Standby模式。

可是新版etcd中,只会在最初启动etcd集群时,发现核心节点的数量已经知足要求时,自动启用Proxy模式,反之则并未实现。主要缘由以下。

  • etcd是用来保证高可用的组件,所以它所须要的系统资源(包括内存、硬盘和CPU等)都应该获得充分保障以保证高可用。任由集群的自动变换随意地改变核心节点,没法让机器保证性能。因此etcd官方鼓励你们在大型集群中为运行etcd准备专有机器集群。
  • 由于etcd集群是支持高可用的,部分机器故障并不会致使功能失效。因此机器发生故障时,管理员有充分的时间对机器进行检查和修复。
  • 自动转换使得etcd集群变得复杂,尤为是现在etcd支持多种网络环境的监听和交互。在不一样网络间进行转换,更容易发生错误,致使集群不稳定。

基于上述缘由,目前Proxy模式有转发代理功能,而不会进行角色转换

 

数据存储

etcd的存储分为内存存储和持久化(硬盘)存储两部分,内存中的存储除了顺序化的记录下全部用户对节点数据变动的记录外,还会对用户数据进行索引、建堆等方便查询的操做。而持久化则使用预写式日志(WAL:Write Ahead Log)进行记录存储。

在WAL的体系中,全部的数据在提交以前都会进行日志记录。

在etcd的持久化存储目录中,有两个子目:一个是WAL,存储着全部事务的变化记录;另外一个则是snapshot,用于存储某一个时刻etcd全部目录的数据。经过WAL和snapshot相结合的方式,etcd能够有效的进行数据存储和节点故障恢复等操做。

既然有了WAL实时存储了全部的变动,为何还须要snapshot呢?随着使用量的增长,WAL存储的数据会暴增,为了防止磁盘很快就爆满,etcd默认每10000条记录作一次snapshot,通过snapshot之后的WAL文件就能够删除。而经过API能够查询的历史etcd操做默认为1000条。

首次启动时,etcd会把启动的配置信息存储到data-dir参数指定的数据目录中。配置信息包括本地节点的ID、集群ID和初始时集群信息。用户须要避免etcd从一个过时的数据目录中从新启动,由于使用过时的数据目录启动的节点会与集群中的其余节点产生不一致(如:以前已经记录并赞成Leader节点存储某个信息,重启后又向Leader节点申请这个信息)。因此,为了最大化集群的安全性,一旦有任何数据损坏或丢失的可能性,你就应该把这个节点从集群中移除,而后加入一个不带数据目录的新节点。

预写式日志(WAL)

WAL(Write Ahead Log)最大的做用是记录了整个数据变化的所有历程。在etcd中,全部数据的修改在提交前,都要先写入到WAL中。使用WAL进行数据的存储使得etcd拥有两个重要功能。

  • 故障快速恢复: 当你的数据遭到破坏时,就能够经过执行全部WAL中记录的修改操做,快速从最原始的数据恢复到数据损坏前的状态。
  • 数据回滚(undo)/重作(redo):由于全部的修改操做都被记录在WAL中,须要回滚或重作,只须要方向或正向执行日志中的操做便可。

 

7Raft

新版etcd中,raft包就是对Raft一致性算法的具体实现。关于Raft算法的讲解,网上已经有不少文章,有兴趣的读者能够去阅读一下Raft算法论文很是精彩。本文则再也不对Raft算法进行详细描述,而是结合etcd,针对算法中一些关键内容以问答的形式进行讲解。有关Raft算法的术语若是不理解,能够参见概念词汇表一节。

Raft常见问答一览

  • Raft中一个Term(任期)是什么意思? Raft算法中,从时间上,一个任期讲即从一次竞选开始到下一次竞选开始。从功能上讲,若是Follower接收不到Leader节点的心跳信息,就会结束当前任期,变为Candidate发起竞选,有助于Leader节点故障时集群的恢复。发起竞选投票时,任期值小的节点不会竞选成功。若是集群不出现故障,那么一个任期将无限延续下去。而投票出现冲突也有可能直接进入下一任再次竞选。

    图12 Term示意图

  • Raft状态机是怎样切换的? Raft刚开始运行时,节点默认进入Follower状态,等待Leader发来心跳信息。若等待超时,则状态由Follower切换到Candidate进入下一轮term发起竞选,等到收到集群多数节点的投票时,该节点转变为Leader。Leader节点有可能出现网络等故障,致使别的节点发起投票成为新term的Leader,此时原先的老Leader节点会切换为Follower。Candidate在等待其它节点投票的过程当中若是发现别的节点已经竞选成功成为Leader了,也会切换为Follower节点。

    图13 Raft状态机

  • 如何保证最短期内竞选出Leader,防止竞选冲突? 在Raft状态机一图中能够看到,在Candidate状态下, 有一个times out,这里的times out时间是个随机值,也就是说,每一个机器成为Candidate之后,超时发起新一轮竞选的时间是各不相同的,这就会出现一个时间差。在时间差内,若是Candidate1收到的竞选信息比本身发起的竞选信息term值大(即对方为新一轮term),而且新一轮想要成为Leader的Candidate2包含了全部提交的数据,那么Candidate1就会投票给Candidate2。这样就保证了只有很小的几率会出现竞选冲突。
  • 如何防止别的Candidate在遗漏部分数据的状况下发起投票成为Leader? Raft竞选的机制中,使用随机值决定超时时间,第一个超时的节点就会提高term编号发起新一轮投票,通常状况下别的节点收到竞选通知就会投票。可是,若是发起竞选的节点在上一个term中保存的已提交数据不完整,节点就会拒绝投票给它。经过这种机制就能够防止遗漏数据的节点成为Leader。
  • Raft某个节点宕机后会如何? 一般状况下,若是是Follower节点宕机,若是剩余可用节点数量超过半数,集群能够几乎没有影响的正常工做。若是是Leader节点宕机,那么Follower就收不到心跳而超时,发起竞选得到投票,成为新一轮term的Leader,继续为集群提供服务。须要注意的是;etcd目前没有任何机制会自动去变化整个集群总共的节点数量,即若是没有人为的调用API,etcd宕机后的节点仍然被计算为总节点数中,任何请求被确认须要得到的投票数都是这个总数的半数以上。

    图14 节点宕机

  • 为何Raft算法在肯定可用节点数量时不须要考虑拜占庭将军问题? 拜占庭问题中提出,容许n个节点宕机还能提供正常服务的分布式架构,须要的总节点数量为3n+1,而Raft只须要2n+1就能够了。其主要缘由在于,拜占庭将军问题中存在数据欺骗的现象,而etcd中假设全部的节点都是诚实的。etcd在竞选前须要告诉别的节点自身的term编号以及前一轮term最终结束时的index值,这些数据都是准确的,其余节点能够根据这些值决定是否投票。另外,etcd严格限制Leader到Follower这样的数据流向保证数据一致不会出错。
  • 用户从集群中哪一个节点读写数据? Raft为了保证数据的强一致性,全部的数据流向都是一个方向,从Leader流向Follower,也就是全部Follower的数据必须与Leader保持一致,若是不一致会被覆盖。即全部用户更新数据的请求都最早由Leader得到,而后存下来通知其余节点也存下来,等到大多数节点反馈时再把数据提交。一个已提交的数据项才是Raft真正稳定存储下来的数据项,再也不被修改,最后再把提交的数据同步给其余Follower。由于每一个节点都有Raft已提交数据准确的备份(最坏的状况也只是已提交数据还未彻底同步),因此读的请求任意一个节点均可以处理。
  • etcd实现的Raft算法性能如何? 单实例节点支持每秒1000次数据写入。节点越多,因为数据同步涉及到网络延迟,会根据实际状况愈来愈慢,而读性能会随之变强,由于每一个节点都能处理用户请求。

     

     

    参考文献

    [01] http://openstack.wiaapp.com/?p=766

    [02] http://www.infoq.com/cn/articles/etcd-interpretation-application-scenario-implement-principle

相关文章
相关标签/搜索