ZooKeeper API使用之实现分布式队列


使用 maven 构建 zookeeper 源码

  1. clone 源代码

    git clone https://github.com/apache/zookeeper.git
    
    cd zookeeper
  2. 切到相应分支

    git checkout branch-3.5.5
  3. 修改 pom.xml

    如下图所示,修改根 pom.xm 中 git-commit-id-plugin 的version 为 3.0.1,自带的2.2.5在maven中央库里没有的。

  4. 运行mvn install -Dmaven.skip.test=rue 或使用 IDEA 导入zookeeper maven 项目

  5. 运行单元测试文件

    运行 zookeeper-recipes-queue 中的单元测试文件 DistributedQueueTest:

    cd zookeeper-recipes/zookeeper-recipes-queue
    
    mvn test -Dtest=org.apache.zookeeper.recipes.queue.DistributedQueueTest

Queue 的设计

使用Zookeeper来实现一个分布式队列时,Queue 应该怎样设计呢?

我们使用路径为 /queue 的 znode 下的节点表示队列中的元素。/queue 下的节点都是顺序持久化 znode。这些 znode 名字的后缀数字表示了对应队列元素在队列中的位置。znode 名字后缀数字越小,对应队列元素在队列中的位置越靠前。

offer 方法

offer 方法在 /queue 下面创建一个顺序 znode。因为 znode 的后缀数字是/queue 下面现有 znode 最大后缀数字加 1,所以该 znode 对应的队列元素处于队尾。

element 方法

element 方法有以下两种返回的方式,我们下面说明这两种方式都是正确的。

  • throw new NoSuchElementException():因为 element 方法读取到了队列为空的状态,所以抛出 NoSuchElementException 是正确的。
  • return zookeeper.getData(dir+“/”+headNode, false, null)childNames 保存的是队列内容的一个快照。这个 return 语句返回的是快照中还没出队列的值。如果队列快照的元素都出队了,重试。

如下图所示,我们 getData 方法返回的的确是队列的队头,假设/queue下面的子节点是1,2,3,4。第一次调用 getData 时还没有发生出队,则返回1,第二次调用 getData 时发生了一次出队,则返回2,

remove 方法

remove 方法和 element 方法类似,都是从队列的的头部移除一下元素。值得注意的是getData的成功执行不意味着出队成功,原因是该队列元素可能会被其他用户出队。

参考


文章作者: 张权
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张权 !
评论
  目录