java+分布式+计数_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: 分布式计数器演示

* Intention: 

* Class Name: com.my.CuratorTest.RecipesDisAutomicLong

* Create Date: 2017/8/20 22:48 

* Project Name: MyTest 

* Company:  All Rights Reserved. 

* Copyright © 2017 

* author: GaoWei 

* 1st_examiner: 

* 2nd_examiner: 

*

* @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

final int k = i;

executor.execute(new Runnable() {

@Override

public void run() {

try {

barrier.await();

System.out.println(Thread.currentThread().getName()+" " + System.nanoTime()+ " , 开始执行");

AtomicValue 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分布式一致性原理与实践

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值