Paxos是分布式应用中解决同步问题的核心。作为应用研发工程师,我们总是倾向于使用一种相对简洁的方式实现复杂的算法。ZooKeeper leader election实现就是一个非常好的参考。



其实现比标准Paxos算法简单,基本过程是:

1                                                                                          


收票->

2

判断是否是本轮投票->如是本轮开始查票;如是新一轮投票,清空本轮投票;如是上轮投票,抛弃->

3                                                         

更新最大的leader id和提案id;如无更新,沉默;->

4

通知其他peer->

5

检查收到选票是否来自全部投票人/来自大多数投票人->

6

检查自己是否被选为leader



(投票轮次在code里是:n.epoch +"|"+ logicalclock,在log里叫:n.round;round看起来比epoch要清楚。)



大致就是这样,ZooKeeper leader election代码写的很漂亮。我给出一个election状态图,结合上面6步的解释,可以看清楚。











下面再给出一个时序图。但主要是收发notification逻辑,和election无关。属于基本socket通信。

第三步是向所有配置文件中的所有Server发election notification,default proposal leader id一定是自己;

第12步根据自己的状态和notification的状态处理,

self.getPeerState() == QuorumPeer.ServerState.LOOKING -> 继续election

(self.getPeerState() == QuorumPeer.ServerState.LOOKING && notification.state == QuorumPeer.ServerState.LOOKING && 自己轮次大) || notification.state == QuorumPeer.ServerState.LOOKING

-> Send notification

简而言之就是,如果你找他也找,如果你轮次大,你就说话,否则沉默;如果只有别人找,直接告诉他你的状态;







最后再以The peer who is looking为例,看看Fast Paxos的过程







Notification数据结构是



static public class Notification {

long leader;  //所推荐的Server id



long zxid;      //所推荐的Server的zxid(zookeeper transtion id)



long epoch;   //描述leader是否变化(每一个Server启动时都有一个logicalclock,初始值为0)



QuorumPeer.ServerState state;   //发送者当前的状态

InetSocketAddress addr;            //发送者的ip地址

}



相关的ZooKeeper log是







2011-07-07 21:39:46,591 - INFO  [QuorumPeer:/0:0:0:0:0:0:0:0:2181:FastLeaderElection@663] - New election. My id =  3, Proposed zxid = 64424509440



2011-07-07 21:39:46,593 - DEBUG [WorkerSender Thread:QuorumCnxManager@367] - Opening channel to server 2



2011-07-07 21:39:46,598 - DEBUG [WorkerSender Thread:QuorumCnxManager$SendWorker@541] - Address of remote peer: 2



2011-07-07 21:39:46,601 - DEBUG [WorkerSender Thread:QuorumCnxManager@367] - Opening channel to server 4



...







2011-07-07 21:39:46,602 - INFO  [WorkerReceiver Thread:FastLeaderElection@496] - Notification: 3 (n.leader), 64424509440 (n.zxid), 1 (n.round), LOOKING (n.state), 3 (n.sid), LOOKING (my state)



2011-07-07 21:39:46,606 - INFO  [WorkerReceiver Thread:FastLeaderElection@496] - Notification: 4 (n.leader), 60129542144 (n.zxid), 16 (n.round), FOLLOWING (n.state), 2 (n.sid), LOOKING (my state)



2011-07-07 21:39:46,607 - INFO  [WorkerReceiver Thread:FastLeaderElection@496] - Notification: 4 (n.leader), 60129542144 (n.zxid), 16 (n.round), FOLLOWING (n.state), 2 (n.sid), LOOKING (my state)



2011-07-07 21:39:46,608 - INFO  [WorkerReceiver Thread:FastLeaderElection@496] - Notification: 4 (n.leader), 60129542144 (n.zxid), 16 (n.round), LEADING (n.state), 4 (n.sid), LOOKING (my state)



2011-07-07 21:39:46,609 - INFO  [WorkerReceiver Thread:FastLeaderElection@496] - Notification: 4 (n.leader), 60129542144 (n.zxid), 16 (n.round), LEADING (n.state), 4 (n.sid), LOOKING (my state)



2011-07-07 21:39:46,611 - INFO  [QuorumPeer:/0:0:0:0:0:0:0:0:2181:QuorumPeer@643] - FOLLOWING





使用leader node是一个很好的设计。我是很赞成使用一个Leader Node去处理所有写request。这非常有助于session ID等global unique资源的分配。选举Leader确保了cluster中leader node的健壮,但是在实际情况中,Leader Node Machine是否应该比Follower Node Machine更强大?



另一个很好的设计是对node进行角色的划分。其实几乎所有cluster设计都需要在对等和差异角色的设计上取舍。如果全是对等角色,则cluster健壮性最佳。但是状态可能需要同步到全cluster,会降低性能。如果是有单一node承担角色,则健壮性下降。以角色区分,在cluster内部选取一部分node作为一种角色的小集群,是非常聪明的。



具体到ZooKeeper,每个participate node相互之间都是socket连接,显然如果cluster node过多,会很糟糕。比如一个500个node的cluster,会要求participate node仅仅为leader election就维护499个socket。但通过角色设置,只有10%的node参与leader election,即设置为participate node。就可有效的解决以上问题。



参考,

ZK Paxos算法描述的清晰易懂的是:http://www.spnguru.com/?p=232

代码描述的另一详文是:http://rdc.taobao.com/blog/cs/?p=162

ZooKeeper leader election的更多相关文章

  1. Zookeeper 学习笔记之 Leader Election

    ZooKeeper四种节点类型: Persist Persist_Sequential Ephemeral Ephemeral_Sequential 在节点上可注册的Watch,客户端先得到通知再得到 ...

  2. [译]ZOOKEEPER RECIPES-Leader Election

    选主 使用ZooKeeper选主的一个简单方法是,在创建znode时使用Sequence和Ephemeral标志.主要思想是,使用一个znode,比如"/election",每个客 ...

  3. Leader Election 选举算法

    今天讲一讲分布式系统中必不可少的选举算法. leader 就是一堆服务器中的协调者,某一个时刻只能有一个leader且所有服务器都承认这个leader. leader election就是在一组进程中 ...

  4. Leader Election

    Leader Election Zookeeper的基本操作 Zookeeper虽然是分布式系统,但它并不是为文件存储而设计的,Zookeeper里存储的一般是配置信息和源信息.实际上,Zookeep ...

  5. Kafka学习笔记(4)----Kafka的Leader Election

    1. Zookeeper的基本操作 zookeeper中的节点可以持久化/有序的两个维度分为四种类型: PERSIST:持久化无序(保存在磁盘中) PERSIST_SEQUENTIAL:持久化有序递增 ...

  6. Kafka配置项unclean.leader.election.enable造成consumer出现offset重置现象

    消费端出现offset重置为latest, earliest现象,类似log: (org.apache.kafka.clients.consumer.internals.Fetcher.handleF ...

  7. zookeeper leader选举算法源码

    服务器状态 在QuorumPeer中有定义,这个类是一个线程. LOOKING:寻找Leader状态.处于该状态时,它会认为当前集群中没有Leader,进入选举流程. FOLLOWING: LEADI ...

  8. Zookeeper——分布式一致性协议及Zookeeper Leader选举原理

    文章目录 一.引言 二.从ACID到CAP/BASE 三.分布式一致性协议 1. 2PC和3PC 2PC 发起事务请求 事务提交/回滚 3PC canCommit preCommit doCommit ...

  9. zookeeper leader作用

    一个zookeeper 集群 只有一个leader: 类似master/slave模式 客户端提交请求之后,先发送到leader,leader作为接收者,广播到每个server 在folloer上创建 ...

随机推荐

  1. Java学习之继承中的执行顺序详解

    代码块(理解) (1)用{}括起来的代码. (2)分类: A:局部代码块 用于限定变量的生命周期,及早释放,提高内存利用率. B:构造代码块 把多个构造方法中相同的代码可以放到这里,每个构造方法执行前 ...

  2. 自守数算法----C语言实现

    #include <stdio.h> //自守数算法 //ep : 25 ^ 2 = 625 76 ^ 2 = 5776 9376 ^ 2 = 87909376 /*ep : * 376 ...

  3. javascript命名规则

    javascript对大小写敏感(关键字.函数名.变量名等),标识符的首字符必须是字母.下划线或者$符,其后的字符可以含数字 如果之声明了变量,并未对其赋值,默认为undefined javascri ...

  4. Java之恋

    初次见面那是一个河北的夏天风随沙散落天涯蝴蝶依旧恋着花回首走过的日子手指和键盘之间的梦想之光已恍如昨日 那年我还是一个刚踏进这个曾经只在地理课本上狂念南稻北麦,南油北花的土地那年你只是我必须要学的编程 ...

  5. 浅谈C语言 extern 指针与数组

    /* * d.c * * Created on: Nov 15, 2011 * Author: root */ #include "apue.h" int a[] = {3,2}; ...

  6. 【C++知识点】单例模式的简单实现

    单例模式是最常见,也是使用最广泛的一种设计模式,其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享. 单例模式的实现方法有很多种,本文只给出一个最简单的实现,如下: ...

  7. SDL2源代码分析4:纹理(SDL_Texture)

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

  8. 【Unity Shaders】Lighting Models —— 衣服着色器

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  9. Java-Io之文件File

    File是"文件"和"目录路径名"的抽象表示形式.File之间继承Object,实现了Serializable和Comparable接口,因此文件支持File对 ...

  10. Android进阶(八)Can't create handler inside thread that has not called Looper.prepare()

    Error:Can't create handler inside thread that has not called Looper.prepare() 原代码: //利用Handler消息传递机制 ...