zookeeper 分布式计数器
分布式计数器的思路是:指定一个Zookeeper数据节点作为计数器,多个应用实例在分布式锁的控制下,通过更新该数据节点的内容来实现计数功能。
Curator中封装了实现,例如 DistributedAtomicInteger 和 DistributedAtomicLong。
以下是我写的一个测试用例:
- package com.my.CuratorTest;
- import org.apache.curator.framework.CuratorFramework;
- import org.apache.curator.framework.CuratorFrameworkFactory;
- import org.apache.curator.framework.recipes.atomic.AtomicValue;
- import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
- import org.apache.curator.retry.ExponentialBackoffRetry;
- import org.apache.curator.retry.RetryNTimes;
- import java.util.concurrent.CyclicBarrier;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- /**
- * Title: 分布式计数器演示<br/>
- * Intention: <br/>
- * <p>
- * Class Name: com.my.CuratorTest.RecipesDisAutomicLong<br/>
- * Create Date: 2017/8/20 22:48 <br/>
- * Project Name: MyTest <br/>
- * Company: All Rights Reserved. <br/>
- * Copyright © 2017 <br/>
- * </p>
- * <p>
- * author: GaoWei <br/>
- * 1st_examiner: <br/>
- * 2nd_examiner: <br/>
- * </p>
- *
- * @version 1.0
- * @since JDK 1.7
- */
- public class RecipesDisAutomicLong {
- static String disAutomicIntPath = "/curator_recipes_distatomicint_path3";
- static CuratorFramework client = CuratorFrameworkFactory.builder()
- .connectString("127.0.0.1:2181")
- .retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();
- static DistributedAtomicLong atomicLong =
- new DistributedAtomicLong(client, disAutomicIntPath, new RetryNTimes(10, 500),
- null);
- public static void main(String[] args) throws Exception{
- client.start();
- Long[] nums = {1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L};
- ExecutorService executor = Executors.newFixedThreadPool(nums.length);
- CyclicBarrier barrier = new CyclicBarrier(nums.length);
- atomicLong.compareAndSet(atomicLong.get().postValue(), new Long(0));
- for (int i=0;i<nums.length;i++) {
- final int k = i;
- executor.execute(new Runnable() {
- @Override
- public void run() {
- try {
- barrier.await();
- System.out.println(Thread.currentThread().getName()+" " + System.nanoTime()+ " , 开始执行");
- AtomicValue<Long> av = atomicLong.add(nums[k]);
- System.out.println("to add value=" + nums[k] + ", Result=" + av.succeeded() + " preValue=" + av.preValue()
- + " postValue=" + av.postValue());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- }
- executor.shutdown();
- }
- }
运行结果:
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 分布式计数器的更多相关文章
- zookeeper之分布式锁以及分布式计数器(通过curator框架实现)
有人可能会问zookeeper我知道,但是curator是什么呢? 其实curator是apachede针对zookeeper开发的一个api框架是apache的顶级项目 他与zookeeper原生a ...
- ZooKeeper 分布式锁
在Redis分布式锁一文中, 作者介绍了如何使用Redis开发分布式锁. Redis分布式锁具有轻量高吞吐量的特点,但是一致性保证较弱.我们可以使用Zookeeper开发分布式锁,来满足对高一致性的要 ...
- Zookeeper分布式过程协同技术 - 群首选举
Zookeeper分布式过程协同技术 - 群首选举 群首概念 群首为集群中服务器选择出来的一个服务器,并被集群认可.设置群首目的在与对客户端所发起的状态变更请求进行排序,包括:create.setDa ...
- Zookeeper 分布式锁 (图解+秒懂+史上最全)
文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...
- Curator Zookeeper分布式锁
Curator Zookeeper分布式锁 pom.xml中添加如下配置 <!-- https://mvnrepository.com/artifact/org.apache.curator/c ...
- Zookeeper分布式集群搭建
实验条件:3台安装linux的机子,配置好Java环境. 步骤1:下载并分别解包到每台机子的/home/iHge2k目录下,附上下载地址:http://mirrors.cnnic.cn/apache/ ...
- ZooKeeper 分布式锁实现
1 场景描述 在分布式应用, 往往存在多个进程提供同一服务. 这些进程有可能在相同的机器上, 也有可能分布在不同的机器上. 如果这些进程共享了一些资源, 可能就需要分布式锁来锁定对这些资源的访问. 2 ...
- ZooKeeper分布式锁浅谈(一)
一.概述 清明节的时候写了一篇分布式锁概述,里面介绍了分布式锁实现的几种方式,其实那时候我一直沉迷于使用redis的悲观锁和乐观锁来实现分布式锁,直到一个血案的引发才让我重新认识了redis分布式锁的 ...
- [转载] zookeeper 分布式锁服务
转载自http://www.cnblogs.com/shanyou/archive/2012/09/22/2697818.html 分布式锁服务在大家的项目中或许用的不多,因为大家都把排他放在数据库那 ...
随机推荐
- Java中如何读写cookie (二)
Java中删除cookie Cookie[] cookies=request.getCookies(); //cookies不为空,则清除 if(cookies!=null ...
- vue.js利用vue.router创建前端路由
node.js方式: 利用node.js安装vue-router模块 cnpm install vue-router 安装完成后我们引入这个模板! 下载vue-router利用script引入方式: ...
- STL标准库-容器-deque
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. deque双向开口可进可出的容器 我们知道连续内存的容器不能随意扩充,因为这样容易扩充别人那去 deque却可以,它创造了内存 ...
- 配置java环境变量,实现一条命令自由切java7 或java8
在多个java编译环境中,有时需要java 7,有时又需要java 8,怎么配置java 环境,可以快速自动切换呢?下面用mac演示在 /etc/bashrc 中配置的环境变量 # 设置 JDK ex ...
- java日常知识点积累
java类型中的普通非static方法 示例代码: package com.lvzhi; /** * Created by lvzhi on 2017/9/3 */ public class MyTh ...
- Centos 中扩展 软件源 的安装 之 Remi ( 为yum 扩展软件源 )
平时一般都是使用Ubuntu的,最近用起来Centos 发现软件安装方便不是很方便, 在安装过程中接触到了这么一个概念, 就是为yum 安装 扩展源, 这里下面要说的就是其中的 Remi ...
- nginx 只容许域名访问禁止掉 ip 访问
在原有 nginx server 的基础上再加上相同端口的配置 server { listen 80 default_server; server_name ...
- 《DSP using MATLAB》Problem 2.4
生成并用stem函数画出这几个序列. 1.代码: %% ------------------------------------------------------------------------ ...
- AngularJS资源大集锦
AngularJS最近貌似很火,前段时间,CSDN的编辑专访了AngularJS创始人Misko Hevery.这不,Tuts+网站编辑Rey Bango应广大读者需要,把各种极好的AngularJS ...
- 【linux】Linux系统信息查看命令大全
系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat /proc/cpuinfo # 查看CPU信息 # ho ...