能找到的一些zookeeper的资料一上来不是扯一通paxos算法就是一大坨一大坨的代码。很多人对zookeeper更多的是听过,所以这一篇文章就尝试用尽可能用精简的语言科普zookeeper

zookeeper是什么

网上的定义:zookeeper作为一个开源的分布式应用协调系统,作为一个正常人我看完这句话之后是——懵逼。理解一个工具最好的办法是问它解决什么问题的,举个例子:

微服务中每个服务是可以被单独部署的,为了便于Client调用,所有服务都必须在注册中心完成注册。这样Client就可以通过查询注册中心获取有哪些服务可以用(包括服务的调用地址、说明、版本之类的元数据信息)。

无论用什么方式设计注册中心最后我们都要解决一个问题——如何存放服务元数据。

  • 直接JSON序列化后存放在注册中心的硬盘上是最简单的,但是我们的注册中心不应该是单点,它挂了整个系统也就无法正常工作了。所以我们必须集中存储(这样的设计可以让注册中心去中心,变成无状态的服务更容易实现高可用)。

  • 集中存储最好的办法是数据库。比如存放在Mysql或者MongoDB中,如果用Mysql需要使用主从来提高Mysql的可用性;如果是MongoDB我们也需要通过“集群”来提高MongoDB的可用性。这两种技术都增加了系统复杂度——毕竟我只是想存放一些JSON数据而已。

Zookeeper是解决这个问题的一个简单方案,它没有提供像MongoDB的一样的查询、排序功能只提供的简单的数据读写。它的数据结构类似于文件系统,使用API也非常类似读写操作系统的文件系统。比如我们的服务元数据可以设计成这样

app├── app1│ └── metadata└── app2└── metadata

服务注册的时候都会在/app节点下生成以自己服务名称命名的节点(比如 app1)然后把自己的元数据写入到一个名称为metadata的“数据节点”。查询服务的时候只需要获取/app下的所有子节点,需要获取某个服务元数据的时候则直接查询对应目录下的metadata节点。

ZooKeeper zooKeeper = //实例化ZooKeeper//查询服务List<String> appNames = zooKeeper.getChildren("/app", false);for (String appName : appNames) {    String meta = "/app/" + appName + "/meta";     if (zooKeeper.exists(meta, false) != null) {         //查询服务元数据          byte metaBytes[] = zooKeeper.getData(meta, false, null);          //JSON反序列化          AppMetadata metaJava = mapper.readValue(metaBytes, AppMetadata.class);      }}

zookeeper的两把刷子

Zookeeper的一个重要特性是提供了去中心化的数据一致性,在一个Zookeeper集群中我们向任何一台服务器写入数据都会被“同步”到其他服务器上。实现这样的特性必须有两把刷子——选举算法和分布式事务

选举算法

很多人会把zookeeper和paxos算法联系在一起,非常负责任的说——它们没有半毛钱的关系。zookeeper的算法非常简单,比如有3台服务器,(server1的myid=1,server2的myid=2,server3的myid=3)

  • 启动的时候服务器都会向集群中其他服务器发送选举信息(zxid,myid)(相当于选自己做leader)。zxid(ZooKeeper Transaction Id)是最后一次写入的节点数据的事务编号(越大说明数据越新),myid是配置的时候分配的一个编号。比如server1发送的是(0, 1),server2发送(0, 2) 、server3发送(1, 3)

  • 收到选举信息的服务器会做一次比较:1).zxid比较大的一个作为leader(选择最新的数据)2). 如果zxid相同(数据同步)则选择myid比较大的作为leader。3). 把自己选中的leader再次发送出去。比如server1收到server3的信息后选择server3作为leader,server2也选择server3作为leader。二者选择leader之后都会再次发送(1, 3)。

  • 当一台服务器收到(n/2+1)个选举信息的时候就认为leader已经选择成功(n是集群中服务器的数据),停止发送选举信息,进入follower状态。比如3台服务器有2台服务器选择server3作为leader那么选举就成功。

在系统运行过程中如果leader死掉了,所有的follower会重新按照上面的算法选举出新的leader。如果你有过网络相关的经验不难发现这个选举算法其实是OSPF的DB、BDR选举算法。

分布式事务

Zookeeper实现的分布式事务是二两阶段提交算法。Client可以向集群中任何一台服务器发送“写入数据”请求,该请求会被转发给leader,leader会通过两阶段提交协议来保证所有的follower都写入成功。

  • leader发送写入数据命令给所有的follower

  • 所有的follower写入数据,返回leader ack确认

  • leader在收到半数的follower的ack之后向follower广播commit数据包

zookeeper的用途

用作注册中心只能算zookeeper的一个“不误正业”的用途。除此之外它还可以用来实现通知/协调。在使用zookeeper client的时候你可能已经注意到了,无论是getData还是setData你都可以传递一个Watch对象,这个对象用来监视某个节点。当节点发送变化的时候这个Watch对象会被调用。通过这个机制我们可以实现分布式系统中的通知/协调,比如当某个模块已经完成了任务就修改节点,另一个模块就会感知到这个变化,这个动作相当于“任务推送”。(和MQ有异曲同工之妙,区别是zookeeper是一个去中心的分布式系统)除了上面的用途之外zookeeper还可以用来实现心跳(比如hadoop的namenode ha)。无论哪种应用基本上都是利用zookeeper提供的数据一致性Watch这两个特性。

深入浅出Zookeeper的更多相关文章

  1. 深入浅出zookeeper之一:功能及本质

    zookeeper(下文简写为zk)大家都不陌生.但是,看到很多同学对zookeeper的理解过于程式化,有些地方甚至需要背,是大可不必的.把本质理解了,概念性和功能介绍都可以推出来的,而且架构要活学 ...

  2. 转载:深入浅出Zookeeper

    ZAB协议 ZAB协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要是根据ZAB协议是实现分布式系统数据一致性. zookeeper根据ZAB协议建立了主备模型完成zook ...

  3. 转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制

    转载至 http://www.jasongj.com/zookeeper/fastleaderelection/: 原创文章,转载请务必将下面这段话置于文章开头处.本文转发自技术世界,原文链接 htt ...

  4. 图解zookeeper FastLeader选举算法

    zookeeper当配置为群集模式,在启动或异常情况将被选举为的例子Leader.默认选择算法FastLeaderElection. 不知道zookeeper够考虑这样一个问题:某个服务能够配置为多个 ...

  5. 图解zookeeper FastLeader选举算法【转】

    转自:http://codemacro.com/2014/10/19/zk-fastleaderelection/ zookeeper配置为集群模式时,在启动或异常情况时会选举出一个实例作为Leade ...

  6. Zookeeper架构、ZAB协议、选举

    转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制  (nice) ZooKeeper学习第六期---ZooKeeper机制架构 一.Zookee ...

  7. 深入浅出理解基于 Kafka 和 ZooKeeper 的分布式消息队列

    消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩和最终一致性架构,是大型分布式系统不可缺少的中间件. 本场 Chat 主要内容: Kafk ...

  8. 升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)

          Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系 ...

  9. zookeeper 快速入门

    分布式系统简介 在分布式系统中另一个需要解决的重要问题就是数据的复制.我们日常开发中,很多人会碰到一个问题:客户端C1更新了一个值K1由V1更新到V2.但是客户端C2无法立即读取到K的最新值.上面的例 ...

随机推荐

  1. iosUITextField属性

    @property UITextField *caption; caption = [[UITextField alloc] initWithFrame:CGRectMake(, self.frame ...

  2. 预定义的类型“Microsoft.CSharp.RuntimeBinder.Binder”未定义或未导入

    http://www.mzwu.com/article.asp?id=3611 因为新加了Microsoft.CSharp的引用, 只需要重新生成一下项目,就可以消除这个错误提示

  3. python 字符串换行的三种方式

    if __name__ == '__main__': #第一种: 三个单引号 print ''' aaaaaaaaaaaaaaaa         bbbbbbbbbbbbbb''' #第二种: 三个 ...

  4. 结构体TABLE_share

    struct TABLE_share { static inline TABLE **next_ptr(TABLE *l) { return &l->share_next; } stat ...

  5. SharePoint的安装配置

    安装环境 1. Window server 2008 r2(sp2) OS.2. MS SQL Server 2008 r2.3. Office2010.4. IIS7以上.5. 确认服务器已经加入域 ...

  6. UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

    题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi  ...

  7. HDU 2087 (KMP不可重叠的匹配) 花布条

    题意: 用两个字符串分别表示布条和图案,问能从该布条上剪出多少这样的图案. 分析: 毫无疑问这也是用KMP匹配,关键是一次匹配完成后,模式串应该向后滑动多少. 和上一题 HDU 1686 不同,两个图 ...

  8. HNOI2004宠物收养所(平衡树)

    treap! var i,n,x,y,ans,a,b,root,tot,ft:longint; l,r,s,v,hr:..] of longint; procedure r_rotate(var x: ...

  9. ASP.NET MVC Html.BeginForm用法1

    Html.BeginForm():该方法用于构建一个From表单的开始, 他的构造方法为:Html.BeginForm("ActionName","ControllerN ...

  10. 自己遇到的Android虚拟机出现的错误及解决方法【不断更新】

    2012.11.9 第一个: [2012-11-09 13:15:14 - Tesa] Android Launch! [2012-11-09 13:15:14 - Tesa] The connect ...