- 首页 > 生活百科 > >
zk系列三:zookeeper实战之分布式锁实现( 二 )
提示:代码中注释的代码块可以关注下,原本是直接阻塞式编程,将获取所有子节点并释放锁的操作直接写在getChildren方法的回调里,后来发现当节点被删除时我们还要重新抢锁,那么代码就冗余了,于是结合响应式编程的思想,将这段核心代码放到getChildren方法的回调
里 , 这样代码简洁了并且可以让业务更只关注于getChildren
这件事了
2、测试代码编写线程安全问题复现
package com.darling.service.zookeeper.lock;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import org.junit.Test;/** * @description:开启是个线程给i做递减操作,未加锁的情况下会有线程安全问题 * @author: dll * @date: Created in 2022/11/8 8:32 * @version: * @modified By: */@Slf4jpublic class ZkLockTest02 {private int i = 10;@Testpublic void test() throws InterruptedException {for (int n = 0; n < 10; n++) {new Thread(new Runnable() {@SneakyThrows@Overridepublic void run() {Thread.sleep(100);incre();}}).start();}Thread.sleep(5000);log.info("i = {}",i);}/*** i递减 线程不安全*/public void incre(){//i.incrementAndGet();log.info("当前线程:{},i = {}",Thread.currentThread().getName(),i--);}}
- 上面代码运行结果如下:
文章插图
使用上面封装的
ZkLockHelper
实现的分布式锁
package com.darling.service.zookeeper.lock;import lombok.SneakyThrows;import lombok.extern.slf4j.Slf4j;import org.apache.zookeeper.ZooKeeper;import org.junit.After;import org.junit.Before;import org.junit.Test;/** * @description: 使用zk实现的分布式锁解决线程安全问题 * @author: dll * @date: Created in 2022/11/8 8:32 * @version: * @modified By: */@Slf4jpublic class ZkLockTest03 {ZooKeeper zkClient;@Beforepublic void conn (){zkClient= ZkUtil.getZkClient();}@Afterpublic void close (){try {zkClient.close();} catch (InterruptedException e) {e.printStackTrace();}}private int i = 10;@Testpublic void test() throws InterruptedException {for (int n = 0; n < 10; n++) {new Thread(new Runnable() {@SneakyThrows@Overridepublic void run() {Thread.sleep(100);ZkLockHelper zkHelper = new ZkLockHelper();// 这里给zkHelper设置threadName是为了后续调试的时候日志打?。阌诠鄄齑嬖诘奈侍?String threadName = Thread.currentThread().getName();zkHelper.setThreadName(threadName);zkHelper.setZkClient(zkClient);// tryLock上锁zkHelper.tryLock();incre();log.info("线程{}正在执行业务代码...",threadName);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 释放锁zkHelper.unLock();}}).start();}while (true) {}}/*** i递减 线程不安全*/public void incre(){//i.incrementAndGet();log.info("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆当前线程:{},i = {}",Thread.currentThread().getName(),i--);}}
- 运行结果如下:
文章插图
【zk系列三:zookeeper实战之分布式锁实现】由于日志中掺杂着zk的日志所有此处并未截全,但是也能看到i是在按规律递减的,不会出现通过线程拿到相同值的情况
四、zk实现分布式锁的优缺点优点
- 集群部署不存在单点故障问题
- 统一视图zk集群每个节点对外提供的数据是一致的,数据一致性有所报障
- 临时有序节点zk提供临时有序节点,这样当客户端失去连接时会自动释放锁,不用像其他方案一样当拿到锁的实例服务不可用时,需要定时任务去删除锁;临时节点的特性就是当客户端失去连接会自动删除
- watch能力加持当获取不到锁时,无需客户端定期轮询争抢,只需watch前一节点即可 , 当有变化时会及时通知,比普通方案即及时又高效;注意这里最好只watch前一节点,如果watch整个父目录的话,当客户端并发较大时会不断有请求进出zk,给zk性能带来压力
缺点
- 与单机版redis比较的话性能肯定较差,但是当客户端集群足够庞大且业务量足够多时肯定还是集群更加稳定
好了,zk实现分布式锁的编码实现就到这了 , 后续有时间再写偏redis的,其实思路缕清了,编码实现还是很简单的
推荐阅读
-
-
-
-
2021年瘦西湖夜游 2023瘦西湖夜游有哪些好玩的
-
高速公路快车道停车追尾后谁的责任 死亡 高速公路快车道停车追尾后谁的责任
-
笔记本电脑怎么投屏到投影仪,笔记本电脑怎么投屏到电视
-
excel怎么核对两个表格的名字相同 两个excel表快速核对重复名字
-
北京倡导13日居家办公14日15日居家休息:居家办公细则怎么制定?
-
奥运冠军吴敏霞官宣二胎! 疑 怀胎超4个月,挺孕肚看比赛激动尖叫 ...
-
-
-
-
-
-
-
-
彼岸花的花语是什么可以养家里吗 彼岸花的花语是什么,象征了什么??
-
为什么手机usb连不上电脑 为什么手机usb连不上液晶电视
-
-