深入浅出Zookeeper
能找到的一些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的更多相关文章
- 深入浅出zookeeper之一:功能及本质
zookeeper(下文简写为zk)大家都不陌生.但是,看到很多同学对zookeeper的理解过于程式化,有些地方甚至需要背,是大可不必的.把本质理解了,概念性和功能介绍都可以推出来的,而且架构要活学 ...
- 转载:深入浅出Zookeeper
ZAB协议 ZAB协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要是根据ZAB协议是实现分布式系统数据一致性. zookeeper根据ZAB协议建立了主备模型完成zook ...
- 转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制
转载至 http://www.jasongj.com/zookeeper/fastleaderelection/: 原创文章,转载请务必将下面这段话置于文章开头处.本文转发自技术世界,原文链接 htt ...
- 图解zookeeper FastLeader选举算法
zookeeper当配置为群集模式,在启动或异常情况将被选举为的例子Leader.默认选择算法FastLeaderElection. 不知道zookeeper够考虑这样一个问题:某个服务能够配置为多个 ...
- 图解zookeeper FastLeader选举算法【转】
转自:http://codemacro.com/2014/10/19/zk-fastleaderelection/ zookeeper配置为集群模式时,在启动或异常情况时会选举出一个实例作为Leade ...
- Zookeeper架构、ZAB协议、选举
转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制 (nice) ZooKeeper学习第六期---ZooKeeper机制架构 一.Zookee ...
- 深入浅出理解基于 Kafka 和 ZooKeeper 的分布式消息队列
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩和最终一致性架构,是大型分布式系统不可缺少的中间件. 本场 Chat 主要内容: Kafk ...
- 升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)
Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系 ...
- zookeeper 快速入门
分布式系统简介 在分布式系统中另一个需要解决的重要问题就是数据的复制.我们日常开发中,很多人会碰到一个问题:客户端C1更新了一个值K1由V1更新到V2.但是客户端C2无法立即读取到K的最新值.上面的例 ...
随机推荐
- 自定义View(3)关于canas.drawText
本文以Canvas类的下面这个函数为基础,它用来在画布上绘制文本. public void drawText(String text, float x, float y, Paint paint) 效 ...
- oracle 11g SQL Developer instead of isqlplus
Oracle11g的新工具SQL DEVELOPER,替代了 isqlplus 1.创建连接方式 2.SQL输入窗口 3.表的结构及其他信息查阅 4.SQL语句测试 5.创建表 6.用户授权 7.数据 ...
- Python中模拟enum枚举类型的5种方法分享
这篇文章主要介绍了Python中模拟enum枚举类型的5种方法分享,本文直接给出实现代码,需要的朋友可以参考下 以下几种方法来模拟enum:(感觉方法一简单实用) 复制代码代码如下: # way1 ...
- Hibernate学习笔记之EHCache的配置
Hibernate默认二级缓存是不启动的,启动二级缓存(以EHCache为例)需要以下步骤: 1.添加相关的包: Ehcache.jar和commons-logging.jar,如果hibernate ...
- bzoj1927: [Sdoi2010]星际竞速
跟上一题几乎一样... #include<cstdio> #include<cstring> #include<iostream> #include<algo ...
- 页面多个Jquery版本共存的冲突问题,解决方法!
示例如下: <script type="text/javascript" src="jquery.js"></script> <s ...
- 64位SqlServer通过链接服务器与32位oracle通讯
在SQL SERVER里只安装了32位的oracle客户端的情况下,添加链接服务器然后执行查询会报如下信息: 原因:在64位的SQL Engine中已经不提供MSDAORA 的驱动了,可以使用Ora ...
- Mac终端编译运行C++
1.在编辑器中写好C++代码 2.打开终端打开文件对应的地址 3.用g++命令来编译.cpp文件 4.用./文件名来运行 观察文件的目录可发现 g++ 源文件名 编译源文件,产生a.out ./文件名 ...
- 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)
[概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识 ...
- Android 工程目录结构简介
一般来说,一个Android工程的目录结构如下图所示. 1:src JAVA源代码都放在这里面. 2:gen 编译器自动生成的一些JAVA代码 3:Android 4.2 Android平台(本工程用 ...