1.概述

转载:基于Zookeeper实现分布式锁

1.1 为什么使用分布式锁

我们在开发应用的时候,如果需要对某一个共享变量进行多线程同步访问的时候,我们往往采用synchronized或者Lock的方解决多线程的代码同步问题,这时多线程的运行是在同一个JVM之下是没有任何问题的。

但当我们的应用是分布式集群工作的情况下,属于多JVM下的工作环境,跨JVM之间已经无法通过多线程的锁解决同步问题。

那么就需要一种更加高级的锁机制,来处理跨机器的进程之间的数据同步问题——分布式锁。


分布锁的实现方式有三种:

基于数据库实现分布式锁
基于缓存(Redis等)实现分布式锁
基于Zookeeper实现分布式锁

今天我们讨论一下基于Zookeeper实现分布式锁的原理。

1.2 分布式锁应具备的条件

1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
2、高可用的获取锁与释放锁;
3、高性能的获取锁与释放锁;
4、具备可重入特性;
5、具备锁失效机制,防止死锁;
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

1.3 实现过程原理

核心思想:当客户端要获取锁,则创建临时顺序节点,使用完锁,则删除该节点。

1.3.1 获取锁

首先,在Zookeeper当中创建一个持久节点Lock。当第一个客户端想要获得锁时,需要在Lock这个节点下面创建一个临时顺序节点 Lock1


之后,Client1查找Lock下面所有的临时顺序节点并比较排序,判断自己所创建的节点Lock1是不是序号最小的哪一个。如果是,则成功获得锁。

这时候,如果再有一个客户端 Client2 前来获取锁,则在Lock下载再创建一个临时顺序节点Lock2。

Client2查找Lock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock2是不是序号最小的那个,结果发现节点Lock2并不是最小的。

于是,Client2向排序仅比它靠前的节点Lock1注册Watcher事件监听器,监听删除事件,用于监听Lock1节点是否存在。这意味着Client2抢锁失败,进入了等待状态。

这时候,如果又有一个客户端Client3前来获取锁,则在Lock下载再创建一个临时顺序节点Lock3。


Client3查找Lock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock3是不是序号最小的那个,结果同样发现节点Lock3并不是最小的。

于是,Client3向排序仅比它靠前的节点Lock2注册Watcher,用于监听Lock2节点是否存在。这意味着Client3同样抢锁失败,进入了等待状态。


这样一来,Client1得到了锁,Client2监听了Lock1,Client3监听了Lock2。这恰恰形成了一个等待队列,很像是Java当中ReentrantLock所依赖的。

1.3.2 释放锁

释放锁分为两种情况:

  1. 任务完成,客户端显示释放 当任务完成时,Client1会显示调用删除节点Lock1的指令。

2.任务执行过程中,客户端崩溃

获得锁的Client1在任务执行过程中,如果Duang的一声崩溃,则会断开与Zookeeper服务端的链接。根据临时节点的特性,相关联的节点Lock1会随之自动删除。


由于Client2一直监听着Lock1的存在状态,当Lock1节点被删除,Client2会立刻收到通知。这时候Client2会再次查询Lock下面的所有节点,确认自己创建的节点Lock2是不是目前最小的节点。如果是最小,则Client2顺理成章获得了锁。


同理,如果Client2也因为任务完成或者节点崩溃而删除了节点Lock2,那么Client3就会接到通知。


最终,Client3成功得到了锁。

2.方案:

可以直接使用zookeeper第三方库Curator客户端,这个客户端中封装了一个可重入的锁服务

Curator提供的InterProcessMutex是分布式锁的实现。acquire方法用户获取锁,release方法用于释放锁。

提供了一个12306的一个抢票小Demo来了解zookeeper分布式锁的实现。

package cn.itcast.test;import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.util.concurrent.TimeUnit;/*需求:模拟车站售票*/
public class Ticket12306 implements  Runnable {//票数private int num=50;//声明分布式锁private InterProcessMutex lock;public Ticket12306() {//一旦创建线程任务对象的时候就与zookeeper建立连接RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000,2);CuratorFramework client = CuratorFrameworkFactory.builder().connectString("192.168.179.129:2181").retryPolicy(retryPolicy).build();//开启链接client.start();//得到了分布式锁lock = new InterProcessMutex(client,"/lock");}@Overridepublic void run() {while(true){try {//获取锁lock.acquire(3, TimeUnit.SECONDS);//参数一:等待锁的最大超时时间, 参数二;第一个参数的时间单位if(num>0){System.out.println(Thread.currentThread().getName()+"卖出了第"+num+"号票");num--;}else{System.out.println("售罄了..");break;}} catch (Exception e) {e.printStackTrace();}finally {//释放锁try {lock.release();} catch (Exception e) {e.printStackTrace();}}}}public static void main(String[] args) {//创建Runnable实现类对象Ticket12306 ticket = new Ticket12306();//模拟两个窗口售票就是两个线程Thread thread1 = new Thread(ticket,"售票员甲");Thread thread2 = new Thread(ticket,"售票员乙");//开启线程thread1.start();thread2.start();}
}

实际运行效果如下

# 运行前
[zk: localhost:2181(CONNECTED) 16] ls /lock
[]
[zk: localhost:2181(CONNECTED) 17]# 运行中
[zk: localhost:2181(CONNECTED) 5] ls /lock
[_c_53ce1ca4-0732-4337-8778-dca8e570211f-lock-0000000855]
[zk: localhost:2181(CONNECTED) 6] ls /lock
[_c_69ce1f64-84bd-41a4-ab2b-b3dfae3ada0e-lock-0000001120, _c_d5a0c148-75bc-4138-80d5-43908f2222c9-lock-0000001119]
[zk: localhost:2181(CONNECTED) 7] ls /lock
[_c_9be12326-127e-4ef5-96f1-970634772a7d-lock-0000001398]# 结束之后
[zk: localhost:2181(CONNECTED) 16] ls /lock
[]
[zk: localhost:2181(CONNECTED) 17]

M.扩展

ZooKeeper实现分布式锁

【Zookeeper】基于Zookeeper实现分布式锁相关推荐

  1. Zookeeper和Redis实现分布式锁,附我的可靠性分析

    作者:今天你敲代码了吗 链接:https://www.jianshu.com/p/b6953745e341 在分布式系统中,为保证同一时间只有一个客户端可以对共享资源进行操作,需要对共享资源加锁来实现 ...

  2. 什么是分布式锁?redis、zookeeper、etcd实现分布式锁有什么不同之处?

    目录 分布式锁定义 目的 基于redis分布式锁 基于zookeeper实现的分布式锁 edis.zookeeper.etcd实现分布式锁的比较 建议选择etcd实现分布式锁 分布式锁定义 分布式环境 ...

  3. 关于Zookeeper和Redis实现分布式锁的异同

    本文来说下Zookeeper和Redis实现分布式锁的异同 文章目录 概述 Redis单机实现分布式锁 Redis加锁 Redis解锁 Redis加锁过期时间设置问题 Zookeeper单机实现分布式 ...

  4. etcd 笔记(08)— 基于 etcd 实现分布式锁

    1. 为什么需要分布式锁? 在分布式环境下,数据一致性问题一直是个难点.分布式与单机环境最大的不同在于它不是多线程而是多进程.由于多线程可以共享堆内存,因此可以简单地采取内存作为标记存储位置.而多进程 ...

  5. nx set 怎么实现的原子性_基于Redis的分布式锁实现

    前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...

  6. 基于Redis的分布式锁和Redlock算法

    来自:后端技术指南针 1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手 ...

  7. redis系列:基于redis的分布式锁

    一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...

  8. 基于 Redis 的分布式锁到底安全吗?

    [完整版] 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现 ...

  9. js 拉勾网效果_Node.js 中实践基于 Redis 的分布式锁实现

    在一些分布式环境下.多线程并发编程中,如果对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题. 作者简介:五月君,Nodejs Developer ...

  10. java如何保证redis设置过期时间的原子性_redis专题系列22 -- 如何优雅的基于redis实现分布式锁

    几个概念 线程锁:主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比 ...

最新文章

  1. SQL_Server_2005_日期和时间函数(描述及实例)
  2. leetcode - Container With Most Water
  3. python环境变量配置_Python环境变量的配置
  4. Linux 开发板4G转WiFi热点 手机连接热点上网(一 思路)
  5. Animation插值器:解决Android Animation 循环执行的停顿问题
  6. vr降噪器英文是什么_耳机降噪功能这么多,说说什么是ANC、ENC、CV...
  7. ubuntu开机时出现“waiting for network configuration” 问题的解决
  8. 雷达卫星测高原理、最新发展情况
  9. dubbo教程(绝对的入门到入土)
  10. 什么是Kodu---Kodu少儿编程第一天
  11. validity属性返回对象中的属性值
  12. 用户价值VS商业价值
  13. final修饰的变量必须初始化吗?
  14. potplay播放器录制音频
  15. 第九篇论文读后总结-相似森林
  16. PHP 微信 扫码登录 pc网站
  17. Android studio完整安装
  18. 《计算机网络自顶向下方法》读书笔记(一)
  19. 微信小程序使用计时器
  20. 计算机教学论文的主题,计算机英语Web Quest主题教学思路

热门文章

  1. 预装鸿蒙系统!华为MatePad Pro 2或暂定6月2日发布
  2. 消息称荣耀7月发布年度旗舰 或用上旗舰级芯片骁龙 888
  3. 造型奇葩!后置四边角八摄手机曝光:但被吐槽毫无作用
  4. 绝了,为了压低成本,iPhone 12可能不送这两个配件了
  5. 华为上架自主地图应用Here WeGo 或登录HMS系统成为预装应用
  6. 很强势!因拒绝退回用户保证金,知名在线旅游平台成“老赖”,回应...
  7. 滴滴新规则明日起试行:将影响一大波人
  8. 5G牌照提前发放 将对整个产业界带来哪些影响?
  9. 优衣库KAWS联名款遭哄抢 大打出手场面惨烈 是我不懂时尚了吗?
  10. 苹果AirPower总是跳票的原因找到了?或因商标被抢注