上一篇演示了基于Redis的Redisson分布式锁实现,那今天我要再来说说基于Zookeeper的分布式现实。

Zookeeper分布式锁实现

要用Zookeeper实现分布式锁,我就不得不说说zookeeper的数据存储。首先zookeeper的核心保存结构是一个DataTree数据结构,其实内部是一个Map<String, DataNode> nodes的数据结构,其中key是path,DataNode才是真正保存数据的核心数据结构,DataNode核心字段包括byte data[]用于保存节点内容。

一,Zookeeper的节点

节点是zookeeper(zk)中数据存储的基础结构,zk中万物皆节点,就好比Java中万物皆对象一样。zk的数据模型就是基于节点的树形结构,但zk规定每个节点的引用规则是路径引用。每个节点中包含子节点引用、存储数据、访问权限以及节点元数据等四部分。

 
image

zookeeper中提供了节点类型主要有。

  • 持久节点:节点创建后,就一直存在,直到有删除操作来主动清除。

  • 顺序节点:假如当前有一个父节点为/lock,我们可以在这个父节点下面创建子节点;zk提供了一个可选的有序特性,例如我们可以创建子节点“/lock/test_”并且指明有序,那么zk在生成子节点时会根据当前子节点数量自动添加整数序号,如果第一个子节点为/lock/test_0000000000,下一个节点则为/lock/test_0000000001,依次类推。

  • 临时节点:客户端可以建立一个临时节点,在会话结束或者会话超时后,zookeeper会自动删除该节点。

二,Zookeeper分布式锁实现

Zookeeper实现分布式锁的流程,假设锁空间的根节点为/zklock:

1,客户端连接zookeeper,并在/zklock下创建临时的且有序的子节点。

第一个客户端对应的子节点为:/zklock/test_lock_0000000000,第二个为:/zklock/test_lock_0000000001。以此类推。

2,客户端获取/zklock下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听/zklock的子节点变更消息,获得子节点变更通知后重复此步骤直至获得锁;

3,执行业务代码。

4,完成业务流程后,删除对应的子节点并释放锁。

 
image

实现代码

 
image

加锁实现:

 
image

阻塞等待上一个锁释放

 
image

释放锁

 
image

测试:

 
image

启动了5个线程来进行验证,输出结果如下。

 
image

注意:子节点的创建顺序一定是从小到大的,但是控制台输出结果中显示创建顺序是随机的,是由于创建节点和输出语句不是原子操作导致的。重点是锁的获取和释放,从输出结果中可以看出,每个线程只有在上一个节点被删除后才能执行,一个基于zk的简单的分布式锁就实现了。

三,Curator分布式锁实现

Zookeeper已经红火了这么多年,实际上基于zk的分布式锁目前已经有现成的实现框架,Curator就是Netflix开源的一套ZooKeeper客户端框架,它提供了zk场景的绝大部分实现,使用Curator就不必关心其内部算法,Curator提供了来实现分布式锁,用方法获取锁,以及用方法释放锁,同其他锁一样,方法需要放在finakky代码块中,确保锁能正确释放

Curator提供了四种分布式锁,分别是:

 
image
  • InterProcessMutex:分布式可重入排它锁

  • InterProcessSemaphoreMutex:分布式排它锁

  • InterProcessReadWriteLock:分布式读写锁

  • InterProcessMultiLock:将多个锁作为单个实体管理的容器

首先在pom里依赖引入

 
image

properties配置

 
image

配置中心

 
image

Curator的分布式锁实现

 
image
 
image
 
image

Controller里写测试接口。

 
image

分布式锁实现总结

前面讲了基于Redis的分布式锁实现,为什么这篇文章又要说基于Zookeeper的分布式锁现实呢?让我们先看看Redis和Zookeeper实现分布式锁的区别吧。

区别:

  • 技术层面:Redis 是nosql数据,而Zookeeper是分布式协调工具,主要用于分布式解决方案;

  • 防死锁:Redis是通过对key设置有效期来解决死锁,而Zookeeper使用会话有效期方式解决死锁现象;

  • 效率方面:Redis是NoSQL数据库,在效率上相对来说Redis就要比Zookeeper好很多;

  • 可靠性:Redis有效期不是很好控制,可能会产生有效期延迟,而Zookeeper的临时节点有先天性可控的有效期,所以相对来说Zookeeper比Redis可靠性高;

对比总结:Zookeeper分布式锁可靠性比redis强,但由于需要创建节点删除节点,所有效率相比Redis要低。那我在实际项目中我们如何选用呢?原则上如果并发量不是特别大,追求可靠性,那么首选zookeeper。而redis实现的分布式锁响应更快,对并发的支持性能更好,如果为了效率,首选redis实现。

扫码关注公众号,发送关键词获取相关资料:

  1. 发送“Springboot”领取电商项目实战源码;
  2. 发送“SpringCloud”领取cloud学习实战资料;

SpringBoot电商项目实战 — Zookeeper的分布式锁实现的更多相关文章

  1. SpringBoot电商项目实战 — Redis实现分布式锁

    最近有小伙伴发消息说,在Springboot系列文第二篇,zookeeper是不是漏掉了?关于这个问题,其实我在写第二篇的时候已经考虑过,但基于本次系列文章是实战练习,在项目里你能看到Zookeepe ...

  2. SpringBoot电商项目实战 — 商品的SPU/SKU实现

    最近事情有点多,所以系列文章已停止好多天了.今天我们继续Springboot电商项目实战系列文章.到目前为止,整个项目的架构和基础服务已经全部实现,分布式锁也已经讲过了.那么,现在应该到数据库设计及代 ...

  3. SpringBoot电商项目实战 — ElasticSearch接入实现

    如今在一些中大型网站中,搜索引擎已是必不可少的内容了.首先我们看看搜索引擎到底是什么呢?搜索引擎,就是根据用户需求与一定算法,运用特定策略从互联网检索出制定信息反馈给用户的一门检索技术.搜索引擎依托于 ...

  4. SpringBoot电商项目实战 — 前后端分离后的优雅部署及Nginx部署实现

    在如今的SpringBoot微服务项目中,前后端分离已成为业界标准使用方式,通过使用nginx等代理方式有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务架构.多端化服务(多 ...

  5. Java 18套JAVA企业级大型项目实战分布式架构高并发高可用微服务电商项目实战架构

    Java 开发环境:idea https://www.jianshu.com/p/7a824fea1ce7 从无到有构建大型电商微服务架构三个阶段SpringBoot+SpringCloud+Solr ...

  6. 16套java架构师,高并发,高可用,高性能,集群,大型分布式电商项目实战视频教程

    16套Java架构师,集群,高可用,高可扩展,高性能,高并发,性能优化,设计模式,数据结构,虚拟机,微服务架构,日志分析,工作流,Jvm,Dubbo ,Spring boot,Spring cloud ...

  7. Spark大型电商项目实战-及其改良之番外(1)-将spark前端页面效果高效拷贝至博客

    Spark大型电商项目实战-及其改良这个系列的时间轴展示图一直在变....1-3篇是用图直接表示时间轴,用一段简陋的html代码表示时间表.第4篇开始才是用比较完整的前端效果,能移动.缩放时间轴,鼠标 ...

  8. web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 ☝☝☝

    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 ...

  9. web前端Vue+Django rest framework 框架 生鲜电商项目实战✍✍✍

    web前端Vue+Django rest framework 框架 生鲜电商项目实战  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频 ...

随机推荐

  1. LaravelS - 基于Swoole加速Laravel/Lumen

    LaravelS LaravelS是一个胶水项目,用于快速集成Swoole到Laravel或Lumen,然后赋予它们更好的性能.更多可能性.Github 特性 内置Http/WebSocket服务器 ...

  2. (四)OpenStack---M版---双节点搭建---Glance安装和配置

    ↓↓↓↓↓↓↓↓视频已上线B站↓↓↓↓↓↓↓↓ >>>>>>传送门 1.创建glance数据库 2.获得 admin 凭证来获取只有管理员能执行的命令的访问权限 3 ...

  3. 用CodePush在React Native App中做热更新

    最近在学React Native,学到了CodePush热更新. 老师讲了两种实现的方法,现将其记录一下. 相比较原生开发,使用React Native开发App不仅能节约开发成本,还能做原生开发不能 ...

  4. Java NIO 三大组件之 Channel

    Java NIO 之 Channel 一.什么是Channel Channel用于源节点(例如磁盘)与目的节点的连接,它可以进行读取,写入,映射和读/写文件等操作. 在Java NIO中负责缓冲区中数 ...

  5. Rust 入门 (三)_下

    这部分我们学习 rust 语言的 变量.数据类型.函数.注释.流程控制 这五个方面的内容.前文介绍了前两个内容,本文介绍后三个内容. 函数 函数在 rust 代码普遍存在,我们也已经见过了它的主函数 ...

  6. 程序员的算法课(14)-Hash算法-对海量url判重

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...

  7. 【Android - 控件】之MD - FloatingActionButton的使用

    FloatingActionButton(FAB) 是 Android 5.0 新特性——Material Design 中的一个控件,是一种悬浮的按钮. FloatingActionButton 是 ...

  8. diff()函数的使用

    1.diff():返回略微迭代(lagged)的或滞后的不同(iterated diferences). > x<-cumsum(cumsum(1:10)) > x [1] 1 4 ...

  9. 在可插拔settings的基础上加入类似中间件的设计

    在可插拔settings的基础上加入类似中间件的设计 settings可插拔设计可以看之前的文章 https://www.cnblogs.com/zx125/p/11735505.html 设计思路 ...

  10. C语音I博客作业09

    ------------恢复内容开始------------ 这个作业属于那个课程|C语言程序设计II --|:--:|--: 这个作业要求在哪里|https://edu.cnblogs.com/ca ...