分布式计数器的思路是:指定一个Zookeeper数据节点作为计数器,多个应用实例在分布式锁的控制下,通过更新该数据节点的内容来实现计数功能。

Curator中封装了实现,例如 DistributedAtomicInteger 和 DistributedAtomicLong。

以下是我写的一个测试用例:

  1. package com.my.CuratorTest;
  2. import org.apache.curator.framework.CuratorFramework;
  3. import org.apache.curator.framework.CuratorFrameworkFactory;
  4. import org.apache.curator.framework.recipes.atomic.AtomicValue;
  5. import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
  6. import org.apache.curator.retry.ExponentialBackoffRetry;
  7. import org.apache.curator.retry.RetryNTimes;
  8. import java.util.concurrent.CyclicBarrier;
  9. import java.util.concurrent.ExecutorService;
  10. import java.util.concurrent.Executors;
  11. /**
  12. * Title: 分布式计数器演示<br/>
  13. * Intention: <br/>
  14. * <p>
  15. * Class Name: com.my.CuratorTest.RecipesDisAutomicLong<br/>
  16. * Create Date: 2017/8/20 22:48 <br/>
  17. * Project Name: MyTest <br/>
  18. * Company:  All Rights Reserved. <br/>
  19. * Copyright © 2017 <br/>
  20. * </p>
  21. * <p>
  22. * author: GaoWei <br/>
  23. * 1st_examiner: <br/>
  24. * 2nd_examiner: <br/>
  25. * </p>
  26. *
  27. * @version 1.0
  28. * @since JDK 1.7
  29. */
  30. public class RecipesDisAutomicLong {
  31. static String disAutomicIntPath = "/curator_recipes_distatomicint_path3";
  32. static CuratorFramework client = CuratorFrameworkFactory.builder()
  33. .connectString("127.0.0.1:2181")
  34. .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
  35. static  DistributedAtomicLong atomicLong =
  36. new DistributedAtomicLong(client, disAutomicIntPath, new RetryNTimes(10, 500),
  37. null);
  38. public static void main(String[] args) throws Exception{
  39. client.start();
  40. Long[] nums = {1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L};
  41. ExecutorService executor = Executors.newFixedThreadPool(nums.length);
  42. CyclicBarrier barrier = new CyclicBarrier(nums.length);
  43. atomicLong.compareAndSet(atomicLong.get().postValue(), new Long(0));
  44. for (int i=0;i<nums.length;i++) {
  45. final int k = i;
  46. executor.execute(new Runnable() {
  47. @Override
  48. public void run() {
  49. try {
  50. barrier.await();
  51. System.out.println(Thread.currentThread().getName()+" " + System.nanoTime()+ " , 开始执行");
  52. AtomicValue<Long> av = atomicLong.add(nums[k]);
  53. System.out.println("to add value=" + nums[k] + ", Result=" + av.succeeded() + " preValue=" + av.preValue()
  54. + " postValue=" + av.postValue());
  55. } catch (Exception e) {
  56. e.printStackTrace();
  57. }
  58. }
  59. });
  60. }
  61. executor.shutdown();
  62. }
  63. }

运行结果:

pool-3-thread-10 89586635189009 , 开始执行
pool-3-thread-8 89586635508120 , 开始执行
pool-3-thread-9 89586635501453 , 开始执行
pool-3-thread-7 89586635493898 , 开始执行
pool-3-thread-6 89586635480564 , 开始执行
pool-3-thread-5 89586635470342 , 开始执行
pool-3-thread-4 89586635427231 , 开始执行
pool-3-thread-3 89586635410787 , 开始执行
pool-3-thread-2 89586635360564 , 开始执行
pool-3-thread-1 89586635236564 , 开始执行
to add value=10, Result=true preValue=0 postValue=10
to add value=2, Result=true preValue=10 postValue=12
to add value=6, Result=true preValue=12 postValue=18
to add value=1, Result=true preValue=18 postValue=19
to add value=7, Result=true preValue=19 postValue=26
to add value=3, Result=true preValue=26 postValue=29
to add value=4, Result=true preValue=29 postValue=33
to add value=8, Result=true preValue=33 postValue=41
to add value=9, Result=true preValue=41 postValue=50
to add value=5, Result=true preValue=50 postValue=55

如果在DistributedAtomicLong的构造方法参数中,RetryNTimes重试次数不够,比如是3,你会发现并不一定每次加数都会成功。显然这里是用了乐观锁机制,它并不保证操作一定成功(它在重试这么多次中都没有成功获得锁,导致操作没有执行),所以我们有必要通过调用 av.succeeded() 来查看此次加数是否成功。

下面是RetryNTimes为3时的某一次运行结果:

pool-3-thread-1 89922027531135 , 开始执行
pool-3-thread-5 89922027681802 , 开始执行
pool-3-thread-8 89922027737357 , 开始执行
pool-3-thread-4 89922027673802 , 开始执行
pool-3-thread-9 89922028120024 , 开始执行
pool-3-thread-10 89922027531580 , 开始执行
pool-3-thread-2 89922027616024 , 开始执行
pool-3-thread-3 89922027606246 , 开始执行
pool-3-thread-7 89922027722691 , 开始执行
pool-3-thread-6 89922027699580 , 开始执行
to add value=9, Result=true preValue=0 postValue=9
to add value=10, Result=true preValue=9 postValue=19
to add value=4, Result=true preValue=19 postValue=23
to add value=7, Result=true preValue=23 postValue=30
to add value=3, Result=true preValue=30 postValue=33
to add value=2, Result=true preValue=33 postValue=35
to add value=5, Result=true preValue=35 postValue=40
to add value=1, Result=false preValue=35 postValue=0
to add value=6, Result=false preValue=35 postValue=0
to add value=8, Result=false preValue=35 postValue=0

参考:

1、从PAXOS到ZOOKEEPER分布式一致性原理与实践

zookeeper 分布式计数器的更多相关文章

  1. zookeeper之分布式锁以及分布式计数器(通过curator框架实现)

    有人可能会问zookeeper我知道,但是curator是什么呢? 其实curator是apachede针对zookeeper开发的一个api框架是apache的顶级项目 他与zookeeper原生a ...

  2. ZooKeeper 分布式锁

    在Redis分布式锁一文中, 作者介绍了如何使用Redis开发分布式锁. Redis分布式锁具有轻量高吞吐量的特点,但是一致性保证较弱.我们可以使用Zookeeper开发分布式锁,来满足对高一致性的要 ...

  3. Zookeeper分布式过程协同技术 - 群首选举

    Zookeeper分布式过程协同技术 - 群首选举 群首概念 群首为集群中服务器选择出来的一个服务器,并被集群认可.设置群首目的在与对客户端所发起的状态变更请求进行排序,包括:create.setDa ...

  4. Zookeeper 分布式锁 (图解+秒懂+史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  5. Curator Zookeeper分布式锁

    Curator Zookeeper分布式锁 pom.xml中添加如下配置 <!-- https://mvnrepository.com/artifact/org.apache.curator/c ...

  6. Zookeeper分布式集群搭建

    实验条件:3台安装linux的机子,配置好Java环境. 步骤1:下载并分别解包到每台机子的/home/iHge2k目录下,附上下载地址:http://mirrors.cnnic.cn/apache/ ...

  7. ZooKeeper 分布式锁实现

    1 场景描述 在分布式应用, 往往存在多个进程提供同一服务. 这些进程有可能在相同的机器上, 也有可能分布在不同的机器上. 如果这些进程共享了一些资源, 可能就需要分布式锁来锁定对这些资源的访问. 2 ...

  8. ZooKeeper分布式锁浅谈(一)

    一.概述 清明节的时候写了一篇分布式锁概述,里面介绍了分布式锁实现的几种方式,其实那时候我一直沉迷于使用redis的悲观锁和乐观锁来实现分布式锁,直到一个血案的引发才让我重新认识了redis分布式锁的 ...

  9. [转载] zookeeper 分布式锁服务

    转载自http://www.cnblogs.com/shanyou/archive/2012/09/22/2697818.html 分布式锁服务在大家的项目中或许用的不多,因为大家都把排他放在数据库那 ...

随机推荐

  1. 黑暗世界的搜索引擎 https://fofa.so/ https://www.shodan.io https://www.zoomeye.org 查找设备漏洞

    from:http://www.freebuf.com/sectool/121339.html 什么是 Shodan? 首先,Shodan 是一个搜索引擎,但它与 Google 这种搜索网址的搜索引擎 ...

  2. 转载:【Oracle 集群】RAC知识图文详细教程(九)--RAC基本测试与使用

    文章导航 集群概念介绍(一) ORACLE集群概念和原理(二) RAC 工作原理和相关组件(三) 缓存融合技术(四) RAC 特殊问题和实战经验(五) ORACLE 11 G版本2 RAC在LINUX ...

  3. 适配器 STL

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  4. junit里面Test Case的执行顺序

    这里讨论的是junit在ant运行的情况,其他build工具应该也适用,但具体没试验过. 首先运行junit时是按照脚本中文件夹的顺序执行,如下脚本会先执行test1目录下的测试,其实是test2目录 ...

  5. 由于BOM头导致的Json解析出错

    上周五改完一些BUG后,测试通过就安心在家过了个周末.结果周一回来一看,整个安卓APP所有的接口都挂掉了1.查找bug 首先想到的是客户端代码有问题,然后想起来上周五还能运行得好好的手机也是同样的错误 ...

  6. Monkey测试练习

    1.下载Android SDK 2.打开SDK Manager.exe自动下载 3.配置环境变量 将platform-tools的路径(如: C:\001myWorkspace\eclipse(MAV ...

  7. Spring map注入

    类test.Configurations定义如下 @Getter @Setter public class Configurations { private Map<AnswerSourceTy ...

  8. bootstrap class sr-only 什么意思?

    bootstrap class sr-only 什么意思? 在看 bootstrap 内联表单时,label 有一个 class 是 sr-only. sr-only 是给屏幕阅读器用的,是给视力不方 ...

  9. Ubuntu14.04下Sublime Text 3解决无法输入中文

    在Ubuntu 14.04中安装了SublimeText 3之后发现既然不支持输入中文,于是在网上搜罗一下,发现很多人遇到了同样的问题,但是解决办法大该就只有一个.下面根据自身的安装及解决办法总结如下 ...

  10. 建立SSH隧道从外网访问内网服务器

    http://blog.trackets.com/2014/05/17/ssh-tunnel-local-and-remote-port-forwarding-explained-with-examp ...