日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

zookeeper实现分布式锁的原理及具体使用案例

發(fā)布時(shí)間:2025/1/21 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zookeeper实现分布式锁的原理及具体使用案例 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

zookeeper跟redis一樣,也是基于內(nèi)存的。

官網(wǎng):

http://zookeeper.apache.org/

zookeeper是分布式系統(tǒng)的協(xié)調(diào)服務(wù),提供配置管理、分布式協(xié)同、命名的中心化服務(wù)以及服務(wù)注冊(cè)發(fā)現(xiàn)等。

zookeeper分布式鎖的實(shí)現(xiàn)原理:

zookeeper實(shí)現(xiàn)分布式鎖采用其提供的有序臨時(shí)節(jié)點(diǎn)+監(jiān)聽(tīng)來(lái)實(shí)現(xiàn)。臨時(shí)節(jié)點(diǎn)只要客戶(hù)端斷開(kāi)連接就會(huì)被刪除,正好可以利用這一特性實(shí)現(xiàn)鎖。

zookeeper是由java語(yǔ)言開(kāi)發(fā)的。

zookeeper中的節(jié)點(diǎn)類(lèi)型:

節(jié)點(diǎn)就是用于存儲(chǔ)數(shù)據(jù)的,在zookeeper中,節(jié)點(diǎn)是類(lèi)似于文件系統(tǒng)的目錄的結(jié)構(gòu)。

①永久節(jié)點(diǎn)。會(huì)進(jìn)行持久化,重啟不會(huì)丟失。

②臨時(shí)節(jié)點(diǎn)。存儲(chǔ)在內(nèi)存中,不會(huì)持久化,重啟服務(wù)或斷開(kāi)連接數(shù)據(jù)會(huì)丟失。

節(jié)點(diǎn)中存儲(chǔ)的數(shù)據(jù)可以進(jìn)行排序。

當(dāng)節(jié)點(diǎn)中的數(shù)據(jù)有更新或是節(jié)點(diǎn)被刪除時(shí),會(huì)觸發(fā)zookeeper的通知機(jī)制告知客戶(hù)端,因?yàn)閦ookeeper一直在監(jiān)聽(tīng)所有的節(jié)點(diǎn)。

領(lǐng)紅包具體案例:

【具體業(yè)務(wù)邏輯是:先查詢(xún)下數(shù)據(jù)庫(kù),判斷用戶(hù)的紅包數(shù)據(jù)是否為空,是則插入紅包數(shù)據(jù),否則不讓插入】

①引入zkclient依賴(lài):

<!--zookeeper客戶(hù)端zkclient--><!-- https://mvnrepository.com/artifact/com.101tec/zkclient --><dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.11</version></dependency>

②代碼實(shí)現(xiàn):

接口:

package com.zhangxueliang.demo.springbootdemo.zookeeperLock;public interface ZookeeperLock {//加鎖void lock();//解鎖void unlock();}

?抽象類(lèi):

package com.zhangxueliang.demo.springbootdemo.zookeeperLock;import org.I0Itec.zkclient.ZkClient;import java.util.concurrent.CountDownLatch;/*** @ProjectName springbootdemo_src* @ClassName AbstractZookeeperLock* @Desicription tryLock和waitLock方法使用到了模板方法設(shè)計(jì)模式* @Author Zhang Xueliang* @Date 2020/1/13 14:19* @Version 1.0**/ public abstract class AbstractZookeeperLock implements ZookeeperLock {protected String lock;protected CountDownLatch countDownLatch;//門(mén)閂(倒計(jì)數(shù)器)protected String zk_address = "127.0.0.1:2181";protected ZkClient zkClient = new ZkClient(zk_address);/*** 加鎖*/@Overridepublic final void lock() {//嘗試獲取鎖if (tryLock()){//已經(jīng)拿到鎖System.out.println("獲取鎖成功。。。");}else {//嘗試獲取鎖未成功,等待獲取鎖,阻塞,如果此處已經(jīng)不阻塞了,那么可以繼續(xù)往下執(zhí)行代碼waitLock();//上面的阻塞結(jié)束了,那么我可以繼續(xù)獲取鎖,遞歸一下}}/*** 釋放鎖*/@Overridepublic final void unlock() {//關(guān)閉連接就解鎖了if(zkClient!=null){zkClient.close();//此處也可以使用zkClient.delete(臨時(shí)節(jié)點(diǎn))來(lái)實(shí)現(xiàn)解鎖System.out.println("解鎖成功。。。");}}//嘗試獲取鎖protected abstract boolean tryLock();//等待獲取鎖protected abstract void waitLock(); }

鎖實(shí)現(xiàn)類(lèi):

package com.zhangxueliang.demo.springbootdemo.zookeeperLock;import org.I0Itec.zkclient.IZkDataListener;import java.util.concurrent.CountDownLatch;/*** @ProjectName springbootdemo_src* @ClassName ZookeeperDistributedLock* @Desicription TODO* @Author Zhang Xueliang* @Date 2020/1/13 14:32* @Version 1.0**/ public class ZookeeperDistributedLock extends AbstractZookeeperLock {public ZookeeperDistributedLock(String lockName){lock=lockName;}/*** 嘗試獲取鎖* @return*/@Overrideprotected boolean tryLock() {try {//創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn)zkClient.createEphemeral(lock);return true;}catch (Exception e){return false;}}/*** 等待獲取鎖*/@Overrideprotected void waitLock() {//如果已經(jīng)有線程創(chuàng)建了臨時(shí)節(jié)點(diǎn),那么其他線程就只能等待,不能再創(chuàng)建該臨時(shí)節(jié)點(diǎn)//此時(shí)我就監(jiān)聽(tīng)(就是訂閱數(shù)據(jù)的改變)你這個(gè)臨時(shí)節(jié)點(diǎn),如果該節(jié)點(diǎn)被刪除了我就等待結(jié)束,就又可以創(chuàng)建臨時(shí)節(jié)點(diǎn)//1.訂閱數(shù)據(jù)改變,就是指定監(jiān)聽(tīng)參數(shù)中所指定的那個(gè)節(jié)點(diǎn)IZkDataListener listener = new IZkDataListener() {//監(jiān)聽(tīng)改變@Overridepublic void handleDataChange(String s, Object o) throws Exception {}//監(jiān)聽(tīng)刪除@Overridepublic void handleDataDeleted(String s) throws Exception {if (countDownLatch!=null){countDownLatch.countDown();}}};//2.判斷鎖的節(jié)點(diǎn)是否存在if (zkClient.exists(lock)){countDownLatch = new CountDownLatch(1);try {//當(dāng)計(jì)數(shù)器從1變成0之后,等待就會(huì)結(jié)束了countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}}//3.取消訂閱zkClient.unsubscribeDataChanges(lock,listener);}}

zookeeper分布式鎖代碼測(cè)試:

//測(cè)試public static void main(String[] args) {ZookeeperDistributedLock zookeeperDistributedLock = new ZookeeperDistributedLock("/addRedPacket");//一定要帶/ 不然節(jié)點(diǎn)添加不成功try{zookeeperDistributedLock.lock();//TODO 具體要鎖住的業(yè)務(wù)代碼//查詢(xún)用戶(hù)是否已經(jīng)領(lǐng)過(guò)紅包//添加紅包給用戶(hù)}finally {zookeeperDistributedLock.unlock();}}

測(cè)試時(shí)需要將zoo_sample.cfg配置文件中的zookeeper最大連接數(shù)調(diào)大些:

maxClientCnxns=1000 #默認(rèn)60

啟動(dòng)兩個(gè)端口:

配置nginx.conf實(shí)現(xiàn)負(fù)載均衡

使用jmeter測(cè)試時(shí)訪問(wèn)的是nginx的80端口:

使用jmeter模擬高并發(fā)場(chǎng)景:

相關(guān)參數(shù)配置--

總結(jié)

以上是生活随笔為你收集整理的zookeeper实现分布式锁的原理及具体使用案例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。