Zookeeper Curator 简单实现;监听Watcher;分布式事务,分布式计数器

应用场景介绍

配置中心 分布式锁 分布式序列生成器

Curator

DistributedLock 
DistributedCounter 
DistributedBarrier 
DistributedQueue 
Transaction Watcher

主要应用:
配置中心
分布式锁
分布式序列生成器

引入jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.cc</groupId>
	<artifactId>springboot-zookeeper-curator</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>pringboot-zookeeper-curator</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.13.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
			<version>2.12.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>2.12.0</version>
		</dependency>



		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

1.简单应用

Curator

         DistributedLock

         DistributedCounter

         DistributedBarrier

         DistributedQueue    

         Transaction Watcher

package com.cc.springbootzookeepercurator;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

import java.nio.charset.Charset;

/**
 * Created by CarlosXiao on 2018/7/29.
 */

@Slf4j
public class CuratorTest {


    public static final String ZK_HOST = "192.168.13.51:2182,192.168.13.51:2183,192.168.13.51:2184,192.168.13.51:2185";

    public static void main(String [] args) throws Exception {
        //1、建立连接
        // 重试5次,每次间隔1秒
        RetryPolicy retry1 = new ExponentialBackoffRetry(1000, 5);
        // 重试5次,每次间隔5秒
        //RetryPolicy retry2 = new RetryNTimes(5, 5000);
        CuratorFramework client = CuratorFrameworkFactory
                .builder()
                .connectString(ZK_HOST)
                .connectionTimeoutMs(5000)
                .retryPolicy(retry1)
                .build();
        client.start();
        log.info(client.getState().name());
        // createNode(client);
        // update(client);
        delete(client);
        client.close();
    }

    /**
     * 创建节点
     * @param client
     */
    public static void createNode(CuratorFramework client) {
        try {
            client.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath("/curator/testcreate", "test_create".getBytes(Charset.defaultCharset()));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void update(CuratorFramework client) throws Exception {
        Stat stat = new Stat();
        String path = "/curator/testcreate";
        byte [] data = client.getData().storingStatIn(stat).forPath(path);
        log.info("修改前的值: {}", new String(data, Charset.defaultCharset()));
        client.setData()
                .withVersion(stat.getVersion())
                .forPath(path, "update".getBytes(Charset.defaultCharset()));
        data = client.getData().forPath(path);
        log.info("修改后的值: {}", new String(data, Charset.defaultCharset()));
    }

    public static void delete(CuratorFramework client) {
        String path = "/curator/testcreate";
        try {
            client.delete()
                    .guaranteed()
                    .deletingChildrenIfNeeded()
                    .withVersion(-1)
                    .forPath(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

2.Zookeeper Curator 高级应用

监听Watcher实现:功能:当一个应用程序节点发生改变通知其他节点改变就是用Watcher机制实现

  对监听的节点进行其他操作,都会进去对应方法,如下对/curator下的子节点进行增加,修改,删除操作时,都能进入对应代码区域再进行相应操作

NodeCache:监听当前节点
PathChildrenCache:监听子节点用法如下:
package com.cc.springbootzookeepercurator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.*;

import java.nio.charset.Charset;


/**
 * 事务操作
 */
public class WatcherExamples {

    private static CuratorFramework client = ClientFactory.newClient();

    public static void main(String[] args) {
        try {
            client.start();
            //节点监听需要用repices包中的NodeCache来完成
            final String path = "/curator/watcher";
            final NodeCache cache = new NodeCache(client,path);
            cache.start();
            cache.getListenable().addListener(() -> {
                byte[] ret = cache.getCurrentData().getData();
                System.out.println("当前节点" + path +"=:"+ new String(ret));
            });
            //在父节点进行监听
            final String pPath = "/curator";
            PathChildrenCache pcCache = new PathChildrenCache(client,pPath,true);
            pcCache.start();
            pcCache.getListenable().addListener((curatorFramework, pathChildrenCacheEvent) -> {
                switch (pathChildrenCacheEvent.getType()){//子节点的事件类型
                    //通过pathChildrenCacheEvent,可以获取到节点相关的数据
                    case CHILD_ADDED:
                        System.out.println("增加节点" + pathChildrenCacheEvent.getData().getPath()
                                + "=" +new String(pathChildrenCacheEvent.getData().getData(),Charset.defaultCharset()) );
                        break;
                    case CHILD_REMOVED:
                        System.out.println("删除节点"+pathChildrenCacheEvent.getData().getPath());
                        break;
                    case CHILD_UPDATED:
                        System.out.println("更新节点" + pathChildrenCacheEvent.getData().getPath()
                                + "=" +new String(pathChildrenCacheEvent.getData().getData(), Charset.defaultCharset()));
                        break;
                    default:
                        break;
                }

            });
            Thread.sleep(Integer.MAX_VALUE);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.cc.springbootzookeepercurator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class ClientFactory {

	public static CuratorFramework newClient() {
		String connectionString = "192.168.13.51:2182,192.168.13.51:2183,192.168.13.51:2184,192.168.13.51:2185";
		ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3);
		return CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
	}
}

3.事务中应用实例

传统的关系型数据库中的事务会非常慢,分布式事务能提升性能

使用CuratorTransaction操作事务:forPath可以继续一直下去,提交后会一起成功或者失败
package com.cc.springbootzookeepercurator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.transaction.CuratorTransaction;
import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
import org.apache.curator.utils.CloseableUtils;

import java.util.Collection;


/**
 * 事务操作
 */
public class TransactionExamples {
    private static CuratorFramework client = ClientFactory.newClient();

    public static void main(String[] args) {
        try {
            client.start();
            // 开启事务
            CuratorTransaction transaction = client.inTransaction();

            Collection<CuratorTransactionResult> results = transaction.create()
                    .forPath("/b", "some data".getBytes()).and().setData()
                    .forPath("/b", "other data".getBytes())
                    .and().commit();

            for (CuratorTransactionResult result : results) {
                System.out.println(result.getForPath() + " - " + result.getType());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            CloseableUtils.closeQuietly(client);
        }

    }
}

4.分布式计数器

   单机版本,及单个服务器jvm使用AtomicInteger实现计数:可以用在分布式系统中订单或者序列生成自增编号等,

分布式中使用DistributedAtomicInteger
package com.cc.springbootzookeepercurator.atomic;

import com.cc.springbootzookeepercurator.ClientFactory;
import com.google.common.collect.Lists;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.atomic.AtomicValue;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicInteger;
import org.apache.curator.framework.recipes.atomic.DistributedAtomicLong;
import org.apache.curator.retry.RetryNTimes;

import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 这个类我没能运行出期待的结果来,谁检查一下我的代码?
 */
public class DistributedAtomicIntegerExample {
	private static CuratorFramework client = ClientFactory.newClient();
	private static final String PATH = "/counter";
	public static DistributedAtomicInteger counter;

	static {
		client.start();
		counter = new DistributedAtomicInteger(client, PATH, new RetryNTimes(3, 1000));
	}

	public static void main(String[] args) {
		final Random rand = new Random();
		List<DistributedAtomicLong> examples = Lists.newArrayList();
		ExecutorService service = Executors.newFixedThreadPool(5);
		for (int i = 0; i < 5; ++i)
		{
			final DistributedAtomicLong count = new DistributedAtomicLong(client, PATH, new RetryNTimes(10, 10));
			examples.add(count);
			Callable<Void> task = () -> {
                try
                {
                    Thread.sleep(1000 + rand.nextInt(10000));
                    AtomicValue<Long> value = count.increment();
                    System.out.println("修改成功: " + value.succeeded());
                    if (value.succeeded())
                    {
                        System.out.println("修改之前的值:" + value.preValue() + " | 修改之后的值:" + value.postValue());
                    }
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
                return null;
            };
			service.submit(task);
		}
		service.shutdown();
		try {
			service.awaitTermination(10, TimeUnit.MINUTES);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		client.close();
	}
}

5.分布式锁

InterProcessReadWriteLock:读写锁

    读写锁,排他锁,互斥锁,

package com.cc.springbootzookeepercurator.lock;

import com.cc.springbootzookeepercurator.ClientFactory;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;

/**
 * Created by CarlosXiao on 2018/7/29.
 */
public class DistributedLockTest {


    static CuratorFramework client = ClientFactory.newClient();

    public static void main(String[] args) throws Exception {

        client.start();
        InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/read-write-lock");

        //读锁
        final InterProcessMutex readLock = readWriteLock.readLock();
        //写锁
        final InterProcessMutex writeLock = readWriteLock.writeLock();

        try {
            readLock.acquire();
            System.out.println(Thread.currentThread() + "获取到读锁");

            new Thread(() -> {
                try {
                    //在读锁没释放之前不能读取写锁。
                    writeLock.acquire();
                    System.out.println(Thread.currentThread() + "获取到写锁");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        writeLock.release();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //停顿3000毫秒不释放锁,这时其它线程可以获取读锁,却不能获取写锁。
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            readLock.release();
        }

        Thread.sleep(10000);
        client.close();
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

择业

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值