dister的介绍及设计

一、dister的介绍

dister(Distribution Cluster)是一款轻量级高性能的分布式集群管理软件,实现了分布式软件架构中的常用核心组件,包括:
1、服务配置管理中心
2、服务注册与发现
3、服务健康检查
4、服务负载均衡
dister的灵感来源于ZooKeeper及Consul,它们都实现了类似的分布式组件,但是dister更加的轻量级、低成本、易维护、架构清晰、简单实用、性能高效,这也是dister设计的初衷。

二、dister的特点

1、开源、免费、跨平台;
2、使用RAFT算法实现分布式一致性;
3、使用通用的REST协议提供API操作;
4、使用分布式KV键值存储实现服务的配置管理;
5、超高读写性能,适合各种高并发的应用场景;
6、支持集群分组,不同的集群之间数据相互隔离;
7、配置管理简单,且仅提供实用的API接口以及终端管理命令,轻量级、低成本、易维护;

三、dister的设计

简要介绍一下dister的一些设计的要点。

1、网络拓扑
在去中心化、分布式集群的网络拓扑设计中,需要注意的是,同一集群以内的各节点之间需要保证连通性,这是保证集群可靠性的前提。
这并不是dister的特点,所有去中心化、分布式集群网络拓扑设计都应当如此。

 

2、集群角色
dister集群有两种角色的概念,一种是集群角色,一种是RAFT角色。
集群角色主要用于区分集群节点的行使职能,RAFT角色主要用于RAFT算法处理数据一致性。
集群角色目前有两种:client和server。

  • client :可以看做一个独立进程的SDK,仅作API操作,不会参与RAFT的Leader选举、也不会存储任何的集群数据;
  • server:集群的关键节点,参与Leader选举,每个server节点保持数据同步与数据的强一致性,保证整个集群的高可用;

一个dister集群中至少应当有一个server节点,当集群中的leader节点出现故障后,其他的server就会按照既定的election算法执行选举,选举成功后新的leader将会接替故障的leader继续行使leader职能。
dister集群随时保持每个节点的数据同步,需要使用集群功能的应用端,本地需要运行一个client或者server节点。

 

3、RAFT一致性
dister使用了RAFT算法来保证一致性,并且对其中的某些部分做了改进,最明显的地方在于两处:

1)、Leader选举
dister与RAFT一样,有三种角色:follower、candidate和leader。

a. 传统的RAFT有一套选举机制,在同一Term内一个节点只能投票给一个cadidate,并且保证 n/2+1 个节点构成多数派选举出一个节点作为leader。缺点是,在实践中,这种选举过程其实非常缓慢,且集群的节点越多,耗费的时间也越多,极易出现split vote的情况。因此这种机制在leader节点出现故障之后,重新完成选举并恢复集群正常运行相对来说耗费的时间会比较长,稳定性和可靠性相对来说要差一些。

b. dister按照 投票+比分 两个机制来进行leader选举,允许一个节点投票给多个candidate,并且保证至少 n/2+1 个节点票数作为选举前提,经过一轮节点之间的对比,谁获得的投票多,并且耗费的时间最短(通过请求投票的响应时间差计算比分,响应越快比分越高),那么该节点即可被选举为leader,其他节点在对比中被淘汰为follower。这样的选举非常快,它只需要经过一轮各节点的对比便能选举出leader,不会出现spit vote的情况,并且选举出的leader往往是集群中网络吞吐比较快速的节点。集群故障恢复也会更加迅速,稳定性和可靠性相对RAFT的机制要好。

在dister选举中,影响选举的因素除了选票和比分外,还包括数据版本,即整个dister集群中数据集最新的节点优先成为leader。

当然,此外dister的选举和RAFT的选举都有先发优势这一说,也就是首先发起选举的节点成为leader的概率越高。

 

2)、数据同步
dister针对数据同步的思想与RAFT是一致的。改进的地方主要在于dister的集群角色处理上(因为RAFT算法并未有集群角色这层概念)。

a. 在数据的请求处理中,dister将RAFT的UncommittedLogEntry + AppendLogEntry两次请求合并为一次请求,即直接将请求的数据并行发往其他的server节点执行写入。dister保证leader和至少另外一个server节点处理成功,那么才能判断为成功,反之即为失败,失败情况下应用端可以选择重试,也可以选择放弃。dister的这种处理机制在保证数据一致性的同时也提供了良好的写入性能。并且,即使在处理过程中leader挂掉,只要有另外一个server节点有最新的请求数据,那么就算重新进行选举,也会选举到数据最新的server节点作为leader,这里的机制类似于主从备份的原理(当然不仅仅是备份概念,dister保证了数据的强一致性)。此外,由于采用了异步并发请求的机制,如果集群存在多个其他server节点,出现仅有一个节点成功的概念很小,出现所有节点都失败的概率更小。

b. 有一点需要指出的是,在一个仅含有一个server的dister集群中(当然该server节点毫无疑问地被选举为leader,dister支持这种单server的集群,类似于zookeeper的standalone模式,但不推荐),一个写入请求仅保证leader成功即为成功,因此,读写性能会更加高效,但是容易产生单点故障(这也是不推荐的原因)。

c. 在数据同步的比较方面,同一集群采用的是增量同步,如果出现两个不同集群(数据完全不一致)的节点组合成一个新的集群(这种情况要尽量避免,属于操作问题),那么dister不会合并,只会按照数据的新旧程度一个将另一个节点数据进行覆盖。 

d. client节点不做数据同步,不存储任何的集群数据,任何的写入及查询请求都是直接转发给leader节点,但是,对于查询请求,本地节点会做一定的缓存处理,降低对leader节点的请求压力;

 

4、分区及脑裂问题
分区和脑裂是分布式算法中难以避免且必须被有效处理的问题。
依靠RAFT的一致性算法,分区和脑裂的问题已经被有效解决,具体可见RAFT PAPER,这里仅说明一下内部的几个设计细节:
1)、集群的选举成功,必须保证节点拥有 n/2+1 节点构成的多数派投票作为前提,因此,一个网络分区的环境,有且仅有一个leader产生,被分区的少数派节点任何API操作都将会失败;
2)、在同一个分组的dister集群中,如果出现脑裂问题,两个leader将会自行按照数据集新旧以及选举投票比分进行比较,最终保证集群只会留下一个leader行使管理职能,另一个降级为follower;

 

5、REST接口设计

为保证接口的通用性,dister的接口采用了REST设计方式,这是和开发语言无关的,也无需提供SDK,只需要向本地的接口地址发送HTTP请求即可。

dister的接口仅对本地开放,即接口地址都是监听的 127.0.0.1,因此,一个新加入的应用端想要使用dister集群功能,在应用端本地需要运行dister的节点。

dister提供的接口模块目前有4种:

1)、集群节点管理

2)、KV数据管理

3)、服务管理

4)、负载均衡管理

每个模块的API接口说明可查看dister的使用说明章节。

 

6、服务负载均衡

dister提供了独立的负载均衡接口来实现服务的负载均衡访问,由于应用端与dister的集群通信采用的是本地进程间通信实现,因此,这种机制会比远程RPC的执行效率更加高效。

dister并没有提供服务节点DNS的负载均衡方式,实用DNS其实也是一种对于接口API的一层封装,对于使用者来说,他需要配置本地网络的DNS才能使用。

然而这有点违背dister设计的初衷,就是dister希望尽可能的简单实用,无需用户进行过多的配置即可使用。

因此,dister仅提供了通用的REST接口这么一种方式来访问所有的API。

此外,使用者可以选择性地对负载均衡结果进行缓存,减少请求数。

 

下一节:dister的安装及实用

 

 

 

Leave a Reply

Your email address will not be published.