最全肝一下ZooKeeper实现分布式锁的方案,附带实例!,淘汰了80%的Java面试者

总结

大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。

麻烦帮忙转发一下这篇文章+关注我

就这一次!拼多多内部架构师培训Kafka源码笔记(现已绝版)

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

private static final int connectionTimeout = 5000;

private static final String lockPath = “/lockPath”;

private ZkClient client;

public ZkTemplateLock() {

client = new ZkClient(zkServers, sessionTimeout, connectionTimeout);

log.info(“zk client 连接成功:{}”,zkServers);

}

@Override

protected void waitLock() {

CountDownLatch latch = new CountDownLatch(1);

IZkDataListener listener = new IZkDataListener() {

@Override

public void handleDataDeleted(String dataPath) throws Exception {

System.out.println(“监听到节点被删除”);

latch.countDown();

}

@Override

public void handleDataChange(String dataPath, Object data) throws Exception {}

};

//完成 watcher 注册

client.subscribeDataChanges(lockPath, listener);

//阻塞自己

if (client.exists(lockPath)) {

try {

latch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//取消watcher注册

client.unsubscribeDataChanges(lockPath, listener);

}

@Override

protected boolean tryLock() {

try {

client.createEphemeral(lockPath);

System.out.println(Thread.currentThread().getName()+“获取到锁”);

} catch (Exception e) {

log.error(“创建失败”);

return false;

}

return true;

}

@Override

public void releaseLock() {

client.delete(this.lockPath);

}

}

缺点

每次去竞争锁,都只会有一个线程拿到锁,当线程数庞大时会发生“惊群”现象,zookeeper节点可能会运行缓慢甚至宕机。这是因为其他线程没获取到锁时都会监听/lockPath节点,当A线程释放完毕,海量的线程都同时停止阻塞,去争抢锁,这种操作十分耗费资源,且性能大打折扣。

基于临时顺序节点方案

临时顺序节点与临时节点不同的是产生的节点是有序的,我们可以利用这一特点,只让当前线程监听上一序号的线程,每次获取锁的时候判断自己的序号是否为最小,最小即获取到锁,执行完毕就删除当前节点继续判断谁为最小序号的节点。

image

序列化节点

image

临时顺序节点

临时顺序节点操作源码

public class ZkSequenTemplateLock extends AbstractTemplateLock {

private static final String zkServers = “127.0.0.1:2181”;

private static final int sessionTimeout = 8000;

private static final int connectionTimeout = 5000;

private static final String lockPath = “/lockPath”;

private String beforePath;

private String currentPath;

private ZkClient client;

public ZkSequenTemplateLock() {

client = new ZkClient(zkServers);

if (!client.exists(lockPath)) {

client.createPersistent(lockPath);

}

log.info(“zk client 连接成功:{}”,zkServers);

}

@Override

protected void waitLock() {

CountDownLatch latch = new CountDownLatch(1);

IZkDataListener listener = new IZkDataListener() {

@Override

public void handleDataDeleted(String dataPath) throws Exception {

System.out.println(“监听到节点被删除”);

latch.countDown();

}

@Override

public void handleDataChange(String dataPath, Object data) throws Exception {}

};

//给排在前面的节点增加数据删除的watcher,本质是启动另一个线程去监听上一个节点

client.subscribeDataChanges(beforePath, listener);

//阻塞自己

if (client.exists(beforePath)) {

try {

System.out.println(“阻塞”+currentPath);

latch.await();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

//取消watcher注册

client.unsubscribeDataChanges(beforePath, listener);

}

@Override

protected boolean tryLock() {

if (currentPath == null) {

//创建一个临时顺序节点

currentPath = client.createEphemeralSequential(lockPath + “/”, “lock-data”);

System.out.println(“current:” + currentPath);

}

//获得所有的子节点并排序。临时节点名称为自增长的字符串

List childrens = client.getChildren(lockPath);

//排序list,按自然顺序排序

Collections.sort(childrens);

if (currentPath.equals(lockPath + “/” + childrens.get(0))) {

return true;

} else {

//如果当前节点不是排第一,则获取前面一个节点信息,赋值给beforePath

int curIndex = childrens.indexOf(currentPath.substring(lockPath.length() + 1));

beforePath = lockPath + “/” + childrens.get(curIndex - 1);

}

System.out.println(“beforePath”+beforePath);

return false;

}

@Override

public void releaseLock() {

System.out.println(“delete:” + currentPath);

client.delete(currentPath);

}

}

Curator分布式锁工具

curator提供了以下种类的锁:

  • 共享可重入锁(Shared Reentrant Lock):全局同步锁,同一时间不会有两个客户端持有一个锁

  • 共享锁:与共享可重入锁类似,但是不可重入(有时候会因为这个原因造成死锁)

  • 共享可重入读写锁

  • 共享信号量

  • Multi Shared Lock:管理多种锁的容器实体

我们采用第一种Shared Reentrant Lock中的InterProcessMutex来完成上锁、释放锁的的操作

public class ZkLockWithCuratorTemplate implements Lock {

// zk host地址

private String host = "localhost";




### 最后

在面试前我整理归纳了一些面试学习资料,文中结合我的朋友同学面试美团滴滴这类大厂的资料及案例
![](https://img-blog.csdnimg.cn/img_convert/f10257b0616e58cbdd4884adb4f6b542.webp?x-oss-process=image/format,png)



![MyBatis答案解析](https://img-blog.csdnimg.cn/img_convert/5054cf0ba8042dea936adf1fc7c70b15.webp?x-oss-process=image/format,png)
**由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!**

大家看完有什么不懂的可以在下方留言讨论也可以关注。

觉得文章对你有帮助的话记得关注我点个赞支持一下!



> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**

**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

-2pyNUVoA-1715612540744)]
**由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!**

大家看完有什么不懂的可以在下方留言讨论也可以关注。

觉得文章对你有帮助的话记得关注我点个赞支持一下!



> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)收录**

**[需要这份系统化的资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值