﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-BucketLi</title><link>http://www.blogjava.net/BucketLi/</link><description>every thing come from new!</description><language>zh-cn</language><lastBuildDate>Sat, 09 May 2026 19:16:57 GMT</lastBuildDate><pubDate>Sat, 09 May 2026 19:16:57 GMT</pubDate><ttl>60</ttl><item><title>Google Megastore初探</title><link>http://www.blogjava.net/BucketLi/archive/2011/02/14/344259.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Mon, 14 Feb 2011 04:44:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2011/02/14/344259.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/344259.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2011/02/14/344259.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/344259.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/344259.html</trackback:ping><description><![CDATA[<p><span style="font-size: 10pt"><span style="font-family: 宋体">去年年底</span>,<span style="font-family: 宋体">团队内部成员分享了这篇</span>google<span style="font-family: 宋体">论文</span>,<span style="font-family: 宋体">初读了下</span>,<span style="font-family: 宋体">发现其有蛮多有意思的东西</span>,<span style="font-family: 宋体">就想把他翻译下来</span>,<span style="font-family: 宋体">但是翻译了一小部分</span>,<span style="font-family: 宋体">明显感觉如果这样的翻译发出去</span>,<span style="font-family: 宋体">很可能误人子弟</span>,<span style="font-family: 宋体">所以改成了概要式的博文</span>,<span style="font-family: 宋体">这篇文章会将原论文最核心的几个部分做不完全的翻译和个人理解</span>,<span style="font-family: 宋体">如有不解或者错误的地方</span>,<span style="font-family: 宋体">请查看原论文,并希望能够指正,谢谢</span>.</span></p>
<p><strong><span style="font-family: 宋体"><span style="font-size: 10pt">正文</span></span></strong></p>
<p><span style="font-size: 10pt">Megastore<span style="font-family: 宋体">是谷歌一个内部的存储系统</span>,<span style="font-family: 宋体">它的底层数据存储依赖</span>Bigtable,<span style="font-family: 宋体">也就是基于</span>NoSql<span style="font-family: 宋体">实现的</span>,<span style="font-family: 宋体">但是和传统的</span>NoSql<span style="font-family: 宋体">不同的是</span>,<span style="font-family: 宋体">它实现了类似</span>RDBMS<span style="font-family: 宋体">的数据模型</span>(<span style="font-family: 宋体">便捷性</span>),<span style="font-family: 宋体">同时提供数据的强一致性解决方案</span>(<span style="font-family: 宋体">同一个</span>datacenter,<span style="font-family: 宋体">基于</span>MVCC<span style="font-family: 宋体">的事务实现</span>),<span style="font-family: 宋体">并且将数据进行细颗粒度的分区</span>(<span style="font-family: 宋体">这里的分区是指在同一个</span>datacenter,<span style="font-family: 宋体">所有</span>datacenter<span style="font-family: 宋体">都有相同的分区数据</span>),<span style="font-family: 宋体">然后将数据更新在机房间进行同步复制</span>(<span style="font-family: 宋体">这个保证所有</span>datacenter<span style="font-family: 宋体">中的数据一致</span>).</span></p>
<p><span style="font-size: 10pt">...<br />
</span><span style="color: red"><br />
<span style="font-size: 10pt">中文翻译地址: http://wenku.baidu.com/view/a465cc260722192e4536f671.html#<br />
<br />
原文地址: http://wenku.baidu.com/view/2ddeb1afdd3383c4bb4cd2bb.html</span></span></p>
 <img src ="http://www.blogjava.net/BucketLi/aggbug/344259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2011-02-14 12:44 <a href="http://www.blogjava.net/BucketLi/archive/2011/02/14/344259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>zookeeper使用和原理探究（一）</title><link>http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Tue, 21 Dec 2010 10:58:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/341268.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html#Feedback</comments><slash:comments>15</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/341268.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/341268.html</trackback:ping><description><![CDATA[<p><span style="font: 7pt 'Times New Roman'"><span style="font-size: 10pt"><strong>zookeeper</strong><span style="font-family: 宋体"><strong>介绍<br />
</strong></span>zookeeper<span style="font-family: 宋体">是一个为分布式应用提供一致性服务的软件，它是开源的</span>Hadoop<span style="font-family: 宋体">项目中的一个子项目，并且根据</span>google<span style="font-family: 宋体">发表的</span>&lt;The Chubby lock service for loosely-coupled distributed systems&gt;<span style="font-family: 宋体">论文来实现的，接下来我们首先来安装使用下这个软件，然后再来探索下其中比较重要一致性算法。</span>&nbsp;&nbsp;<br />
</span></span><br />
<strong style="font-size: 10pt">zookeeper<span style="font-family: 宋体">安装和使用<br />
</span></strong><span style="font-size: 10pt">zookeeper<span style="font-family: 宋体">的安装基本上可以按照</span> http://hadoop.apache.org/zookeeper/docs/current/ zookeeperStarted.html <span style="font-family: 宋体">这个页面上的步骤完成安装，这里主要介绍下部署一个集群的步骤，因为这个官方页面似乎讲得并不是非常详细</span>(Running Replicated Zookeeper)<span style="font-family: 宋体">。<br />
</span><span style="font-family: 宋体"><br />
由于手头机器不足，所以在一台机器上部署了</span>3<span style="font-family: 宋体">个</span>server,<span style="font-family: 宋体">如果你手头也比较紧，也可以这么做。那么我建了</span>3<span style="font-family: 宋体">个文件夹，如下<br />
</span></span><strong><span style="font-size: 10pt"><strong>server1&nbsp;&nbsp; server2&nbsp;&nbsp; server3<br />
</strong></span></strong><span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体"><br />
然后每个文件夹里面解压一个</span>zookeeper<span style="font-family: 宋体">的下载包，并且还建了几个文件夹，总体结构如下</span>,<span style="font-family: 宋体">最后那个是下载过来压缩包的解压文件<br />
</span></span></span><strong><span style="font-size: 10pt"><strong>data&nbsp;dataLog&nbsp;logs&nbsp;zookeeper-3.3.2<br />
</strong></span><br />
</strong><span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">那么首先进入</span>data<span style="font-family: 宋体">目录，创建一个</span>myid<span style="font-family: 宋体">的文件，里面写入一个数字，比如我这个是</span>server1,<span style="font-family: 宋体">那么就写一个</span>1<span style="font-family: 宋体">，</span>server2<span style="font-family: 宋体">对应</span>myid<span style="font-family: 宋体">文件就写入</span>2<span style="font-family: 宋体">，</span>server3对应myid文件就<span style="font-family: 宋体">写个</span>3<br />
</span></span><br />
<span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">然后进入</span><strong>zookeeper-3.3.2/conf</strong><span style="font-family: 宋体">目录，那么如果是刚下过来，会有</span>3<span style="font-family: 宋体">个文件，</span><strong>configuration.xml, log4j.properties,zoo_sample.cfg</strong>,<span style="font-family: 宋体">这</span>3<span style="font-family: 宋体">个文件我们首先要做的就是在这个目录创建一个</span>zoo.cfg<span style="font-family: 宋体">的配置文件，当然你可以把</span>zoo_sample.cfg<span style="font-family: 宋体">文件改成</span>zoo.cfg<span style="font-family: 宋体">，配置的内容如下所示：</span></span></span>&nbsp;<br />
<span style="color: red"><span style="font-size: 10pt"><span style="color: red">tickTime=2000<br />
</span><span style="color: red">initLimit=5<br />
</span><span style="color: red">syncLimit=2<br />
</span><span style="color: red">dataDir=xxxx/zookeeper/server1/data<br />
</span><span style="color: red">dataLogDir=xxx/zookeeper/server1/dataLog<br />
</span><span style="color: red">clientPort=2181<br />
</span></span></span><span style="font-size: 10pt">server.1=127.0.0.1:2888:3888<br />
server.2=127.0.0.1:2889:3889<br />
server.3=127.0.0.1:2890:3890<span style="font-family: 宋体"><br />
</span></span><br />
<span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">标红的几个配置应该官网讲得很清楚了，只是需要注意的是</span>clientPort<span style="font-family: 宋体">这个端口如果你是在</span>1<span style="font-family: 宋体">台机器上部署多个</span>server,<span style="font-family: 宋体">那么每台机器都要不同的</span>clientPort<span style="font-family: 宋体">，比如我</span>server1<span style="font-family: 宋体">是</span>2181,server2<span style="font-family: 宋体">是</span>2182<span style="font-family: 宋体">，</span>server3<span style="font-family: 宋体">是</span>2183<span style="font-family: 宋体">，</span>dataDir<span style="font-family: 宋体">和</span>dataLogDir<span style="font-family: 宋体">也需要区分下。</span> <br />
<br />
<span style="font-family: 宋体">最后几行唯一需要注意的地方就是</span> server.X <span style="font-family: 宋体">这个数字就是对应</span> data/myid<span style="font-family: 宋体">中的数字。你在</span>3<span style="font-family: 宋体">个</span>server<span style="font-family: 宋体">的</span>myid<span style="font-family: 宋体">文件中分别写入了</span>1<span style="font-family: 宋体">，</span>2<span style="font-family: 宋体">，</span>3<span style="font-family: 宋体">，那么每个</span>server<span style="font-family: 宋体">中的</span>zoo.cfg<span style="font-family: 宋体">都配</span>server.1,server.2,server.3<span style="font-family: 宋体">就</span>OK<span style="font-family: 宋体">了。因为在同一台机器上，后面连着的</span>2<span style="font-family: 宋体">个端口</span>3<span style="font-family: 宋体">个</span>server<span style="font-family: 宋体">都不要一样，否则端口冲突，其中第一个端口用来集群成员的信息交换，第二个端口是在</span>leader<span style="font-family: 宋体">挂掉时专门用来进行选举</span>leader<span style="font-family: 宋体">所用。<br />
<br />
</span></span></span><span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">进入</span>zookeeper-3.3.2/bin <span style="font-family: 宋体">目录中<span style="font-family: 宋体">，<strong>./</strong></span></span></span></span><span style="font-family: 宋体"><span style="font-size: 10pt"><strong>zkServer.sh start</strong></span></span><span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">启动一个</span>server,<span style="font-family: 宋体">这时会报大量错误？其实没什么关系，因为现在集群只起了</span>1<span style="font-family: 宋体">台</span>server<span style="font-family: 宋体">，</span>zookeeper<span style="font-family: 宋体">服务器端起来会根据</span>zoo.cfg<span style="font-family: 宋体">的服务器列表发起选举</span>leader<span style="font-family: 宋体">的请求，因为连不上其他机器而报错，那么当我们起第二个</span>zookeeper<span style="font-family: 宋体">实例后，</span>leader<span style="font-family: 宋体">将会被选出，从而一致性服务开始可以使用，这是因为</span>3<span style="font-family: 宋体">台机器只要有</span>2<span style="font-family: 宋体">台可用就可以选出</span>leader<span style="font-family: 宋体">并且对外提供服务</span>(2n+1<span style="font-family: 宋体">台机器，可以容</span>n<span style="font-family: 宋体">台机器挂掉</span>)<span style="font-family: 宋体">。<br />
<br />
</span></span></span><span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">接下来就可以使用了，我们可以先通过</span> zookeeper<span style="font-family: 宋体">自带的客户端交互程序来简单感受下</span>zookeeper<span style="font-family: 宋体">到底做一些什么事情。进入</span>zookeeper-3.3.2/bin<span style="font-family: 宋体">（</span>3<span style="font-family: 宋体">个</span>server<span style="font-family: 宋体">中任意一个）下，</span><strong>./zkCli.sh&nbsp;&#8211;server&nbsp;127.0.0.1:2182</strong>,<span style="font-family: 宋体">我连的是开着</span>2182<span style="font-family: 宋体">端口的机器。<br />
<br />
</span><span style="font-family: 宋体">那么，首先我们随便打个命令，因为</span>zookeeper<span style="font-family: 宋体">不认识，他会给出命令的</span>help,<span style="font-family: 宋体">如下图</span></span></span>&nbsp;&nbsp;<br />
&nbsp;&nbsp; <img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/bucketli/dddd.jpg" /><br />
<span style="font-size: 10pt">ls(<span style="font-family: 宋体">查看当前节点数据</span>),<br />
ls2(<span style="font-family: 宋体">查看当前节点数据并能看到更新次数等数据</span>) ,<br />
create(<span style="font-family: 宋体">创建一个节点</span>) ,<br />
get(<span style="font-family: 宋体">得到一个节点，包含数据和更新次数等数据</span>),<br />
set(<span style="font-family: 宋体">修改节点</span>)<br />
delete(<span style="font-family: 宋体">删除一个节点</span>)<br />
</span><span style="font-family: 宋体"><br />
<span style="font-size: 10pt"><span style="font-family: 宋体">通过上述命令实践，我们可以发现，</span>zookeeper<span style="font-family: 宋体">使用了一个类似文件系统的树结构，数据可以挂在某个节点上，可以对这个节点进行删改。另外我们还发现，当改动一个节点的时候，集群中活着的机器都会更新到一致的数据。</span> <br />
</span></span><br />
<span style="font-size: 10pt"><strong>zookeeper</strong><span style="font-family: 宋体"><strong>的数据模型<br />
</strong></span></span><span style="font-family: 宋体"><span style="font-size: 10pt"><span style="font-family: 宋体">在简单使用了</span>zookeeper<span style="font-family: 宋体">之后，我们发现其数据模型有些像操作系统的文件结构，结构如下图所示<br />
</span></span></span><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/bucketli/XX.jpg" /><br />
<br />
<br />
<span style="font-size: 10pt">(1)<span style="line-height: normal; font-variant: normal; font-style: normal; font-family: 'Times New Roman'; font-weight: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">每个节点在</span>zookeeper<span style="font-family: 宋体">中叫做</span>znode,<span style="font-family: 宋体">并且其有一个唯一的路径标识，如</span>/SERVER2<span style="font-family: 宋体">节点的标识就为</span>/APP3/SERVER2<br />
(2)<span style="line-height: normal; font-variant: normal; font-style: normal; font-family: 'Times New Roman'; font-weight: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span>Znode<span style="font-family: 宋体">可以有子</span>znode<span style="font-family: 宋体">，并且</span>znode<span style="font-family: 宋体">里可以存数据，但是</span>EPHEMERAL<span style="font-family: 宋体">类型的节点不能有子节点<br />
</span>(3)<span style="line-height: normal; font-variant: normal; font-style: normal; font-family: 'Times New Roman'; font-weight: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span>Znode<span style="font-family: 宋体">中的数据可以有多个版本，比如某一个路径下存有多个数据版本，那么查询这个路径下的数据就需要带上版本。<br />
</span>(4)<span style="line-height: normal; font-variant: normal; font-style: normal; font-family: 'Times New Roman'; font-weight: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span>znode <span style="font-family: 宋体">可以是临时节点，一旦创建这个</span> znode <span style="font-family: 宋体">的客户端与服务器失去联系，这个</span> znode <span style="font-family: 宋体">也将自动删除，</span>Zookeeper <span style="font-family: 宋体">的客户端和服务器通信采用长连接方式，每个客户端和&nbsp; 服务器通过心跳来保持连接，这个连接状态称为</span> session<span style="font-family: 宋体">，如果</span> znode <span style="font-family: 宋体">是临时节点，这个</span> session <span style="font-family: 宋体">失效，</span>znode <span style="font-family: 宋体">也就删除了<br />
</span>(5)<span style="line-height: normal; font-variant: normal; font-style: normal; font-family: 'Times New Roman'; font-weight: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span>znode <span style="font-family: 宋体">的目录名可以自动编号，如</span> App1 <span style="font-family: 宋体">已经存在，再创建的话，将会自动命名为</span> App2&nbsp;<br />
(6)<span style="line-height: normal; font-variant: normal; font-style: normal; font-family: 'Times New Roman'; font-weight: normal">&nbsp;&nbsp;&nbsp;&nbsp; </span>znode <span style="font-family: 宋体">可以被监控，包括这个目录节点中存储的数据的修改，子节点目录的变化等，一旦变化可以通知设置监控的客户端，这个功能是</span>zookeeper<span style="font-family: 宋体">对于应用最重要的特性，通过这个特性可以实现的功能包括配置的集中管理，集群管理，分布式锁等等。</span></span>&nbsp; <br />
<br />
<span lang="EN-US"><o:p style="font-size: 10pt"><strong><span style="font-family: 宋体">通过</span>java<span style="font-family: 宋体">代码使用</span>zookeeper&nbsp;<br />
</strong></o:p></span><span lang="EN-US"><span style="font-size: 10pt"><span lang="EN-US">Zookeeper</span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的使用主要是通过创建其</span><span lang="EN-US">jar</span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">包下的</span><span lang="EN-US">Zookeeper</span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">实例，并且调用其接口方法进行的，主要的操作就是对</span><span lang="EN-US">znode</span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的增删改操作，监听</span><span lang="EN-US">znode</span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">的变化以及处理。</span></span></span><span lang="EN-US"><o:p>&nbsp;<br />
<br />
</o:p></span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin"><span style="font-size: 10pt"><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">以下为主要的</span><span lang="EN-US">API</span><span style="font-family: 宋体; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin">使用和解释</span></span></span></p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><span style="color: #008000">//</span><span style="color: #008000">创建一个Zookeeper实例，第一个参数为目标服务器地址和端口，第二个参数为Session超时时间，第三个为节点变化时的回调方法</span><span style="color: #008000"><br />
<img id="Codehighlighter1_136_262_Open_Image" onclick="this.style.display='none'; Codehighlighter1_136_262_Open_Text.style.display='none'; Codehighlighter1_136_262_Closed_Image.style.display='inline'; Codehighlighter1_136_262_Closed_Text.style.display='inline';" alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" /><img style="display: none" id="Codehighlighter1_136_262_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_136_262_Closed_Text.style.display='none'; Codehighlighter1_136_262_Open_Image.style.display='inline'; Codehighlighter1_136_262_Open_Text.style.display='inline';" alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" /></span><span style="color: #000000">ZooKeeper&nbsp;zk&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;ZooKeeper(</span><span style="color: #000000">"</span><span style="color: #000000">127.0.0.1:2181</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">500000</span><span style="color: #000000">,</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Watcher()&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_136_262_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_136_262_Open_Text"><span style="color: #000000">{<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;监控所有被触发的事件</span><span style="color: #008000"><br />
<img id="Codehighlighter1_216_254_Open_Image" onclick="this.style.display='none'; Codehighlighter1_216_254_Open_Text.style.display='none'; Codehighlighter1_216_254_Closed_Image.style.display='inline'; Codehighlighter1_216_254_Closed_Text.style.display='inline';" alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" /><img style="display: none" id="Codehighlighter1_216_254_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_216_254_Closed_Text.style.display='none'; Codehighlighter1_216_254_Open_Image.style.display='inline'; Codehighlighter1_216_254_Open_Text.style.display='inline';" alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;process(WatchedEvent&nbsp;event)&nbsp;</span><span style="border-bottom: #808080 1px solid; border-left: #808080 1px solid; background-color: #ffffff; display: none; border-top: #808080 1px solid; border-right: #808080 1px solid" id="Codehighlighter1_216_254_Closed_Text"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_216_254_Open_Text"><span style="color: #000000">{<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">dosomething</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">创建一个节点root，数据是mydata,不进行ACL权限控制，节点为永久性的(即客户端shutdown了也不会消失)</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/root</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">mydata</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),Ids.OPEN_ACL_UNSAFE,&nbsp;CreateMode.PERSISTENT);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">在root下面创建一个childone&nbsp;znode,数据为childone,不进行ACL权限控制，节点为永久性的</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/root/childone</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">childone</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">取得/root节点下的子节点名称,返回List&lt;String&gt;</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.getChildren(</span><span style="color: #000000">"</span><span style="color: #000000">/root</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">取得/root/childone节点下的数据,返回byte[]</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.getData(</span><span style="color: #000000">"</span><span style="color: #000000">/root/childone</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">修改节点/root/childone下的数据，第三个参数为版本，如果是-1，那会无视被修改的数据版本，直接改掉</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.setData(</span><span style="color: #000000">"</span><span style="color: #000000">/root/childone</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">childonemodify</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">删除/root/childone这个节点，第二个参数为版本，－1的话直接删除，无视版本</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.delete(</span><span style="color: #000000">"</span><span style="color: #000000">/root/childone</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">关闭session</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.close();<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span></div>
&nbsp;<br />
<strong><span style="font-family: 'Courier New'; color: black"><span style="font-size: 10pt"><span style="font-family: 'Courier New'; color: black">Zookeeper</span><span style="font-family: 宋体; color: black">的主流应用场景实现思路（除去官方示例）</span></span></span> <br />
</strong><span style="font-size: 10pt"><span style="font-family: 'Courier New'; color: black"><strong><br />
(1)</strong></span><span style="font-family: 宋体; color: black"><strong>配置管理<br />
</strong></span></span><span style="font-family: 宋体; color: black"><span style="font-size: 10pt">集中式的配置管理在应用集群中是非常常见的，一般商业公司内部都会实现一套集中的配置管理中心，应对不同的应用集群对于共享各自配置的需求，并且在配置变更时能够通知到集群中的每一个机器。<br />
</span></span><span style="font-size: 10pt"><span style="font-family: 'Courier New'; color: black"><br />
Zookeeper</span><span style="font-family: 宋体; color: black">很容易实现这种集中式的配置管理，比如将</span><span style="font-family: 'Courier New'; color: black">APP1</span><span style="font-family: 宋体; color: black">的所有配置配置到</span><span style="font-family: 'Courier New'; color: black">/APP1 znode</span><span style="font-family: 宋体; color: black">下，</span><span style="font-family: 'Courier New'; color: black">APP1</span><span style="font-family: 宋体; color: black">所有机器一启动就对</span><span style="font-family: 'Courier New'; color: black">/APP1</span><span style="font-family: 宋体; color: black">这个节点进行监控</span><span style="font-family: 'Courier New'; color: black">(zk.exist(</span><span style="font-family: 'Courier New'; color: #2a00ff">"/APP1"</span><span style="font-family: 'Courier New'; color: black">,true)),</span><span style="font-family: 宋体; color: black">并且实现回调方法</span><span style="font-family: 'Courier New'; color: black">Watcher</span><span style="font-family: 宋体; color: black">，那么在</span><span style="font-family: 'Courier New'; color: black">zookeeper</span><span style="font-family: 宋体; color: black">上</span><span style="font-family: 'Courier New'; color: black">/APP1 znode</span><span style="font-family: 宋体; color: black">节点下数据发生变化的时候，每个机器都会收到通知，</span><span style="font-family: 'Courier New'; color: black">Watcher</span><span style="font-family: 宋体; color: black">方法将会被执行，那么应用再取下数据即可</span><span style="font-family: 'Courier New'; color: black">(zk.getData(</span><span style="font-family: 'Courier New'; color: #2a00ff">"/APP1",false,null</span><span style="font-family: 'Courier New'; color: black">));<br />
</span></span><span style="font-family: 宋体; color: black"><span style="font-size: 10pt"><br />
以上这个例子只是简单的粗颗粒度配置监控，细颗粒度的数据可以进行分层级监控，这一切都是可以设计和控制的。</span></span>&nbsp;&nbsp;&nbsp;&nbsp; <img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/bucketli/ttt.jpg" /><br />
<strong><span style="font-size: 10pt"><span style="font-family: 'Courier New'; color: black">(2)</span><span style="font-family: 宋体; color: black">集群管理</span></span> <br />
</strong><span style="font-family: 宋体; color: black"><span style="font-size: 10pt">应用集群中，我们常常需要让每一个机器知道集群中（或依赖的其他某一个集群）哪些机器是活着的，并且在集群机器因为宕机，网络断链等原因能够不在人工介入的情况下迅速通知到每一个机器。<br />
</span></span><span style="font-size: 10pt"><span style="font-family: 'Courier New'; color: black"><br />
Zookeeper</span><span style="font-family: 宋体; color: black">同样很容易实现这个功能，比如我在</span><span style="font-family: 'Courier New'; color: black">zookeeper</span><span style="font-family: 宋体; color: black">服务器端有一个</span><span style="font-family: 'Courier New'; color: black">znode</span><span style="font-family: 宋体; color: black">叫</span><span style="font-family: 'Courier New'; color: black">/APP1SERVERS,</span><span style="font-family: 宋体; color: black">那么集群中每一个机器启动的时候都去这个节点下创建一个</span><span style="font-family: 'Courier New'; color: black">EPHEMERAL</span><span style="font-family: 宋体; color: black">类型的节点，比如</span><span style="font-family: 'Courier New'; color: black">server1</span><span style="font-family: 宋体; color: black">创建</span><span style="font-family: 'Courier New'; color: black">/APP1SERVERS/SERVER1(</span><span style="font-family: 宋体; color: black">可以使用</span><span style="font-family: 'Courier New'; color: black">ip,</span><span style="font-family: 宋体; color: black">保证不重复</span><span style="font-family: 'Courier New'; color: black">)</span><span style="font-family: 宋体; color: black">，</span><span style="font-family: 'Courier New'; color: black">server2</span><span style="font-family: 宋体; color: black">创建</span><span style="font-family: 'Courier New'; color: black">/APP1SERVERS/SERVER2</span><span style="font-family: 宋体; color: black">，然后</span><span style="font-family: 'Courier New'; color: black">SERVER1</span><span style="font-family: 宋体; color: black">和</span><span style="font-family: 'Courier New'; color: black">SERVER2</span><span style="font-family: 宋体; color: black">都</span><span style="font-family: 'Courier New'; color: black">watch /APP1SERVERS</span><span style="font-family: 宋体; color: black">这个父节点，那么也就是这个父节点下数据或者子节点变化都会通知对该节点进行</span><span style="font-family: 'Courier New'; color: black">watch</span><span style="font-family: 宋体; color: black">的客户端。因为</span><span style="font-family: 'Courier New'; color: black">EPHEMERAL</span><span style="font-family: 宋体; color: black">类型节点有一个很重要的特性，就是客户端和服务器端连接断掉或者</span><span style="font-family: 'Courier New'; color: black">session</span><span style="font-family: 宋体; color: black">过期就会使节点消失，那么在某一个机器挂掉或者断链的时候，其对应的节点就会消失，然后集群中所有对</span><span style="font-family: 'Courier New'; color: black">/APP1SERVERS</span><span style="font-family: 宋体; color: black">进行</span><span style="font-family: 'Courier New'; color: black">watch</span><span style="font-family: 宋体; color: black">的客户端都会收到通知，然后取得最新列表即可。<br />
</span></span><span style="font-size: 10pt"><span style="font-family: 宋体; color: black"><br />
另外有一个应用场景就是集群选</span><span style="font-family: 'Courier New'; color: black">master,</span><span style="font-family: 宋体; color: black">一旦</span><span style="font-family: 'Courier New'; color: black">master</span><span style="font-family: 宋体; color: black">挂掉能够马上能从</span><span style="font-family: 'Courier New'; color: black">slave</span><span style="font-family: 宋体; color: black">中选出一个</span><span style="font-family: 'Courier New'; color: black">master,</span><span style="font-family: 宋体; color: black">实现步骤和前者一样，只是机器在启动的时候在</span><span style="font-family: 'Courier New'; color: black">APP1SERVERS</span><span style="font-family: 宋体; color: black">创建的节点类型变为</span><span style="font-family: 'Courier New'; color: black">EPHEMERAL_SEQUENTIAL</span><span style="font-family: 宋体; color: black">类型，这样每个节点会自动被编号，例如</span></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath1</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">1</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath2</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">2</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath3</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">3</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;创建一个子目录节点</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath4</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">4</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />System.out.println(zk.getChildren(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">));<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span></div>
&nbsp;<span style="font-size: 10pt"><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">打印结果：</span></span><span style="font-family: 'Courier New'; color: black; font-size: 10pt; mso-font-kerning: 0pt" lang="EN-US"><span style="font-size: 10pt">[testChildPath10000000000, testChildPath20000000001, testChildPath40000000003, testChildPath30000000002]<br />
<br />
</span><o:p>
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">testRootData</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),Ids.OPEN_ACL_UNSAFE,&nbsp;CreateMode.PERSISTENT);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;创建一个子目录节点</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath1</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">1</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath2</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">2</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath3</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">3</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;创建一个子目录节点</span><span style="color: #008000"><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span><span style="color: #000000">zk.create(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath/testChildPath4</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">4</span><span style="color: #000000">"</span><span style="color: #000000">.getBytes(),&nbsp;Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /><br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" />System.out.println(zk.getChildren(</span><span style="color: #000000">"</span><span style="color: #000000">/testRootPath</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">));<br />
<img alt="" align="top" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" /></span></div>
<span style="font-family: 宋体; color: black; font-size: 10pt"><span style="font-size: 10pt"><span style="font-family: 宋体; color: black">打印结果:</span><span style="font-family: 'Courier New'; color: black">[testChildPath2, testChildPath1, testChildPath4, testChildPath3]<br />
</span></span></span><span style="font-family: 'Courier New'; color: black; font-size: 10pt"><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt"><br />
我们默认规定编号最小的为</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">master,</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">所以当我们对</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">/APP1SERVERS</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">节点做监控的时候，得到服务器列表，只要所有集群机器逻辑认为最小编号节点为</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">master</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">，那么</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">master</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">就被选出，而这个</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">master</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">宕机的时候，相应的</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">znode</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">会消失，然后新的服务器列表就被推送到客户端，然后每个节点逻辑认为最小编号节点为</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">master</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">，这样就做到动态</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US">master</span><span style="font-family: 宋体; color: black; mso-fareast-font-family: 宋体; mso-fareast-theme-font: minor-fareast; mso-bidi-font-family: 'Courier New'; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt">选举。<br />
</span><span style="font-family: 'Courier New'; color: black; mso-bidi-font-size: 10.5pt; mso-font-kerning: 0pt" lang="EN-US"><o:p></o:p></span><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/bucketli/xxx.jpg" /><br />
<br />
<strong>总结</strong>&nbsp;
<p style="text-indent: -18pt; margin-left: 18pt" class="MsoListParagraph"><span style="font-family: 宋体">我们初步使用了一下</span>zookeeper<span style="font-family: 宋体">并且尝试着描述了几种应用场景的具体实现思路，接下来的文章，我们会尝试着去探究一下</span>zookeeper<span style="font-family: 宋体">的高可用性与</span>leaderElection<span style="font-family: 宋体">算法。</span></p>
<p><span style="font-family: 宋体"><strong>参考</strong>：</span><a href="http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/">http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/</a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://hadoop.apache.org/zookeeper/docs/current/">http://hadoop.apache.org/zookeeper/docs/current/</a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://rdc.taobao.com/team/jm/archives/448">http://rdc.taobao.com/team/jm/archives/448</a><br />
</span></o:p></span></p>
<img src ="http://www.blogjava.net/BucketLi/aggbug/341268.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2010-12-21 18:58 <a href="http://www.blogjava.net/BucketLi/archive/2010/12/21/341268.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA线程池代码浅析</title><link>http://www.blogjava.net/BucketLi/archive/2010/12/16/340295.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Thu, 16 Dec 2010 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2010/12/16/340295.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/340295.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2010/12/16/340295.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/340295.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/340295.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExecutorService&nbsp;Java从1.5开始正式提供了并发包,而这个并发包里面除了原子变量,synchronizer,并发容器,另外一个非常重要的特性就是线程池.对于线程池的意义,我们这边不再多说. 上图是线程池的主体类图,ThreadPoolExecutor是应用最为广泛的一个...&nbsp;&nbsp;<a href='http://www.blogjava.net/BucketLi/archive/2010/12/16/340295.html'>阅读全文</a><img src ="http://www.blogjava.net/BucketLi/aggbug/340295.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2010-12-16 13:57 <a href="http://www.blogjava.net/BucketLi/archive/2010/12/16/340295.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA并发容器代码随读</title><link>http://www.blogjava.net/BucketLi/archive/2010/11/25/335623.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Thu, 25 Nov 2010 05:43:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2010/11/25/335623.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/335623.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2010/11/25/335623.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/335623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/335623.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.concurrent所提供的并发容器java.util.concurrent提供了多种并发容器，总体上来说有4类，队列类型的BlockingQueue和 ConcurrentLinkedQueue,Map类型的ConcurrentMap,Set类型的ConcurrentSkipListSet和Co...&nbsp;&nbsp;<a href='http://www.blogjava.net/BucketLi/archive/2010/11/25/335623.html'>阅读全文</a><img src ="http://www.blogjava.net/BucketLi/aggbug/335623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2010-11-25 13:43 <a href="http://www.blogjava.net/BucketLi/archive/2010/11/25/335623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4j代码随读</title><link>http://www.blogjava.net/BucketLi/archive/2010/10/22/335618.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Fri, 22 Oct 2010 02:40:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2010/10/22/335618.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/335618.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2010/10/22/335618.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/335618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/335618.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最近需要用到log4j动态定制Logger的场景，然后加上以前对于这个日志工具拿来就用而不知其原理的原因，所以决定花点时间看下它的源码，如果你还对log4j如何使用感到困惑，那么请首先简要浏览下它的官网http://logging.apache.org/log4j/Log4j总体来说是一个可定制，支持同时多种形式输出日志，并且高度结构化的日志库。可定制，也就是既可以通过log4j.prop...&nbsp;&nbsp;<a href='http://www.blogjava.net/BucketLi/archive/2010/10/22/335618.html'>阅读全文</a><img src ="http://www.blogjava.net/BucketLi/aggbug/335618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2010-10-22 10:40 <a href="http://www.blogjava.net/BucketLi/archive/2010/10/22/335618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA LOCK代码浅析</title><link>http://www.blogjava.net/BucketLi/archive/2010/09/30/333471.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Thu, 30 Sep 2010 04:05:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2010/09/30/333471.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/333471.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2010/09/30/333471.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/333471.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/333471.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JAVA LOCK总体来说关键要素主要包括3点: 1.unsafe.compareAndSwapXXX(Object o,long offset,int expected,int x)2.unsafe.park() 和 unsafe.unpark()3.单向链表结构或者说存储线程的数据结构第1点主要为了保证锁的原子性，相当于一个锁是否正在被使用的标记，并且比较和设置这个标记的操...&nbsp;&nbsp;<a href='http://www.blogjava.net/BucketLi/archive/2010/09/30/333471.html'>阅读全文</a><img src ="http://www.blogjava.net/BucketLi/aggbug/333471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2010-09-30 12:05 <a href="http://www.blogjava.net/BucketLi/archive/2010/09/30/333471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Netty代码分析</title><link>http://www.blogjava.net/BucketLi/archive/2010/09/25/332462.html</link><dc:creator>BucketLI</dc:creator><author>BucketLI</author><pubDate>Sat, 25 Sep 2010 04:10:00 GMT</pubDate><guid>http://www.blogjava.net/BucketLi/archive/2010/09/25/332462.html</guid><wfw:comment>http://www.blogjava.net/BucketLi/comments/332462.html</wfw:comment><comments>http://www.blogjava.net/BucketLi/archive/2010/09/25/332462.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/BucketLi/comments/commentRss/332462.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BucketLi/services/trackbacks/332462.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Netty提供异步的、事件驱动的网络应用程序框架和工具，用以快速开发高性能、高可靠性的网络服务器和客户端程序[官方定义]，整体来看其包含了以下内容：1.提供了丰富的协议编解码支持，2.实现自有的buffer系统，减少复制所带来的消耗，3.整套channel的实现，4.基于事件的过程流转以及完整的网络事件响应与扩展，5.丰富的example。本文并不对Netty实际使用中可能出现的问题做分析，只是从...&nbsp;&nbsp;<a href='http://www.blogjava.net/BucketLi/archive/2010/09/25/332462.html'>阅读全文</a><img src ="http://www.blogjava.net/BucketLi/aggbug/332462.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BucketLi/" target="_blank">BucketLI</a> 2010-09-25 12:10 <a href="http://www.blogjava.net/BucketLi/archive/2010/09/25/332462.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>