1. Zookeeper简述

我们要了解一样技术,首先应该要到它的官网,因为官网的信息一般都是最准确的,如下图是Zookeeper官网对它的介绍。

从官网的介绍中,可以总结出,Zookeeper是一个集中式服务,它能够实现高度可靠的分布式协调,可用于开发和维护开源服务器。

除了官网的解释外,我的观点是还可以这样理解。它也相当于是一个数据库,具有数据同步和选举功能,能够用来存储一些信息,可用于解决大数据集群的单点故障问题。Zookeeper有leader和follow两种角色,当leader的节点宕掉之后,会自动选举出新的leader,如果只剩一个节点活着,就是standalone状态。Zookeeper各个节点之间的数据会自动同步,比如在Zookeeper集群的A节点存储数据,那么这份数据也会自动拷贝到集群中另外的节点上。在Hadoop、Storm、Spark集群都可以使用Zookeeper实现高可用(HA),防止出现单点故障。

2. 为什么要加锁

在多线程编程中,必须要考虑到线程安全问题,当共享数据被高并发访问时,会破坏数据的一致性。比如抢购商品,商品数量为1,有两个用户(线程)同时对它进行访问,当第一个线程拿到数据,还没有对数量执行减1操作的这段时间,第二个线程在这个时间段也拿到了数据,两个线程都对商品数量进行减1操作的话,就会出现商品数量是 -1 的数据,就违背了实际原则。

    因此,在程序中引入了锁,在线程访问共享数据之前,首先要请求锁,当得到这把锁的时候,才能够访问共享数据,使用完以后再归还这把锁。如果锁已经被一个线程获取,其它线程就请求不到锁,就执行重试策略,进入等待状态,不会访问共享数据,也就保证了数据的一致性。

3. 编程实战

3.1 原理

3.2 实现

3.2.1 代码

(1) 创建Maven项目,并在pom文件中加入以下依赖

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.apache.curator</groupId><artifactId>curator-client</artifactId><version>4.0.0</version></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.6</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>16.0.1</version></dependency>
</dependencies>

        (2) Product.java

package com.nova;
/*** * @author Supernova* @date 2018/06/16**/
public class Product {// 商品数量,这里默认共有8件商品private static int number = 5;public static int getNumber() {return number;}public static void setNumber(int number) {Product.number = number;}}

        (2) Client.java

package com.nova;import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
/*** * @author Supernova* @date 2018/06/16**/
public class Client {/** 抢购商品的方法 * 作用:访问共享资源,获取并更新商品数量*/public static void buy() {System.out.println("--------【"+Thread.currentThread().getName()+"】开始购买-------");//获取商品数量int currentNumber = Product.getNumber();/** 如果商品数量为0,则不能购买* 如果还有商品,则执行购买操作*/if(currentNumber == 0 ) {System.out.println("商品已被抢空!!!");}else {System.out.println("当前商品数量:"+currentNumber);//购买后商品数量减1currentNumber--;Product.setNumber(currentNumber);//为了便于观察程序的运行结果,这里使线程在执行购买操作后,停顿3秒try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("--------【"+Thread.currentThread().getName()+"】  购买结束-------");}public static void main(String[] args) {/** 定义重试策略:等待2秒,重试10次* 第一个参数:等待时间* 第二个参数:重试次数*/RetryPolicy policy = new ExponentialBackoffRetry(2000, 10);/** 创建客户端向zookeeper请求锁* connectString() : zookeeper地址* retryPolicy() : 重试策略*/CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString("192.168.243.11").retryPolicy(policy).build();//启用
        curatorFramework.start();//获取zookeeper锁的信息final InterProcessMutex mutex = new InterProcessMutex(curatorFramework, "/myMutex");/** 创建8个线程模拟8个客户端并发访问* */for (int i = 0; i < 8; i++) {new Thread(new Runnable() {public void run() {try {//请求锁资源,如果没有得到锁资源,就会执行重试策略
                        mutex.acquire();//开始访问共享资源,这里是访问商品信息
                        buy();} catch (Exception e) {e.printStackTrace();}finally {try {//将锁归还
                            mutex.release();} catch (Exception e) {e.printStackTrace();}}}}).start();}}
}

3.2.2 运行测试

 (1) 启动Zookeeper。通过Putty连接VM的Linux系统,我是在Hadoop伪分布的机器上启动的Zookeeper,只启动一个Zookeeper节点,因此是standalone的状态。 

        (2) 运行Java程序,程序运行结果如下图

可以看到运行的结果是线程安全的,只有在一个线程购买商品操作结束后,另一个线程才能接着购买。保证了数据的一致性。那么,如果去掉锁的情况是如何的呢?

  (3) 将请求锁的代码mutex.acquire();和mutex.release();注释掉之后。运行结果如下:

    从运行结果可以看出,如果没有锁的限制,程序运行的结果将会混乱。

 

转载于:https://www.cnblogs.com/snova/p/9195689.html

【Zookeeper】编程实战之Zookeeper分布式锁实现秒杀相关推荐

  1. relation does not exist报错是什么意思_为什么Zookeeper天生就是一副分布式锁的胚子?...

    " 什么是分布式锁?分布式锁是控制分布式系统之间同步访问共享资源的一种方式.在分布式系统中,常常需要协调他们的动作. 图片来自 Pexels 如果不同的系统或是同一个系统的不同主机之间共享了 ...

  2. ZooKeeper : Curator框架之分布式锁InterProcessReadWriteLock

    InterProcessReadWriteLock 跨JVM工作的可重入读/写互斥锁,使用Zookeeper来持有锁,所有JVM中使用相同锁路径的所有进程都将实现进程间临界区.这个互斥锁是公平的,每个 ...

  3. Zookeeper命令操作(初始Zookeeper、JavaAPI操作、分布式锁实现、模拟12306售票分布式锁、Zookeeper集群搭建、选举投票)

    Zookeeper命令操作(初始Zookeeper.JavaAPI操作.分布式锁实现.模拟12306售票分布式锁.Zookeeper集群搭建.选举投票) 1.初始Zookeeper Zookeeper ...

  4. ieee39节点系统介绍_Java秒杀系统实战系列-基于ZooKeeper的分布式锁优化秒杀逻辑...

    本文是"Java秒杀系统实战系列文章"的第十六篇,本文我们将继续秒杀系统的优化之路,采用统一协调调度中心中间件ZooKeeper控制秒杀系统中高并发多线程对于共享资源~代码块的并发 ...

  5. zookeeper操作封装——curator使用分布式锁使用

    文章目录 1. 基本操作 1.1 建立连接 1.2 建立结点 1.3 查询结点 查询数据 查询子结点 查看结点信息 1.4 修改结点 普通修改 带乐观锁的修改 1.5 删除 删除单个结点 删除带子结点 ...

  6. ZooKeeper(五) 使用Zookeeper有序临时节点实现分布式锁

    当使用zookeeper实现分布式锁时,当有新的请求需要进入需要同步加锁代码时,在zookeeper加锁代码中会在加锁的共同父节点下创建一个新的临时有需节点.创建完成后会获取加锁父节点下所有子节点.判 ...

  7. 基于zookeeper的瞬时节点实现分布式锁

    zookeeper的数据结构 zookeeper的观察器 可设置观察器的3个方法:getData();getChildren();exists(); 节点数据发生变化,发送给客户端 观察器只能监控一次 ...

  8. java设计前期工作基础和存在的困难_Java秒杀系统实战系列-基于Redisson的分布式锁优化秒杀逻辑...

    本文是"Java秒杀系统实战系列文章"的第十五篇,本文我们将借助综合中间件Redisson优化"秒杀系统中秒杀的核心业务逻辑",解决Redis的原子操作在优化秒 ...

  9. Java秒杀系统实战系列~基于Redisson的分布式锁优化秒杀逻辑

    摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十五篇,本文我们将借助综合中间件Redisson优化"秒杀系统中秒杀的核心业务逻辑",解决Redis的原子 ...

最新文章

  1. 什么是HTTP Headers?
  2. 对话院士成果转化基地-丰收节交易会·李喜贵:谋定精准对接
  3. iPhone开发中的一些小技巧
  4. 程序员必收藏的五个网站
  5. Java Spring研究之initHandlerMappings - MavenSandbox debug
  6. LeetCode 840. 矩阵中的幻方(数学)
  7. 安装向导因错误而提前结束_【软件安装】SIMATIC STEP7 V5.6中文版安装教程及错误解决方法...
  8. MySQL 参数设置
  9. L3_08——图中所有边都是相等的常数
  10. php查netstat,Netstat命令详解
  11. JsonView用法
  12. android屏幕投屏QT,QtScrcpy - 安卓手机轻松投屏到电脑
  13. Unity通用计时器
  14. 汉朝时期皇室家谱记载的基本内容有哪些?皇室家谱有谁能列入?
  15. matplotlib中的imshow()绘图长宽比例失调,调整长宽比(备忘)
  16. 不使用循环,求二进制中1的个数
  17. Spring Boot Web应用程序中注册 Servlet 的方法实例
  18. 软件接口设计 六大原则
  19. Android Framework 包管理子系统(03)应用安装
  20. 美国计算机有读一年的学校吗,美国哪些学校的计算机专业值得读?

热门文章

  1. 1046:判断一个数能否同时被3和5整除
  2. 【前端3】jquary:页面加载,选择器,隔行换色,Dom,全选,动画,遍历,广告/抽奖,表单校验插件
  3. linux下常用快捷键
  4. 【C语言】C语言实现面向对象编程之封装
  5. 【Linux系统编程】线程栈大小
  6. 【Protocol Buffer】Protocol Buffer入门教程(三):proto3与proto2的区别
  7. java基本数据类型与封装类 示例_Java零基础系列教程10Java抽象与封装
  8. Qt--qss(暗橙色)
  9. Codeforces 987C. Three displays(o(n^2))
  10. n皇后问题java版