Zookeeper-Zookeeper应用场景实战(二)

1. Zookeeper 分布式锁实战

1.1 什么是分布式锁

        在单体的应用开发场景中涉及并发同步的时候,大家往往采用Synchronized(同步)或者其他同一个 JVM内Lock机制来解决多线程间的同步问题。在分布式集群工作的开发场景中,就需要 一种更加高级的锁机制来处理跨机器的进程之间的数据同步问题,这种跨机器的锁就是分布式锁。
目前分布式锁,比较成熟、主流的方案:
        (1)基于数据库的分布式锁。这种方案使用数据库的事务和锁机制来实现分布式锁。虽然在某些场景 下可以实现简单的分布式锁,但由于数据库操作的性能相对较低,并且可能面临锁表的风险,所以一 般不是首选方案。
        (2)基于Redis的分布式锁。Redis分布式锁是一种常见且成熟的方案,适用于高并发、性能要求高且 可靠性问题可以通过其他方案弥补的场景。Redis提供了高效的内存存储和原子操作,可以快速获取和 释放锁。它在大规模的分布式系统中得到广泛应用。
        (3)基于ZooKeeper的分布式锁。 这种方案适用于对高可靠性和一致性要求较高,而并发量不是太高 的场景。 由于ZooKeeper的选举机制和强一致性保证,它可以处理更复杂的分布式锁场景,但相对于 Redis而言,性能可能较低。
基于Redis实现分布式锁
https://vip.tulingxueyuan.cn/detail/p_602e53b3e4b035d3cdb8f856/6
1.2 基于数据库设计思路
        可以利用数据库的唯一索引来实现,唯一索引天然具有排他性
思考:基于数据库实现分布式锁存在什么问题?

1.3 基于Zookeeper设计思路一

        使用临时 znode 来表示获取锁的请求,创建 znode成功的用户拿到锁。
思考:上述设计存在什么问题?
        如果所有的锁请求者都 watch 锁持有者,当代表锁持有者的 znode 被删除以后,所有的锁请求者都会通知到,但是只有一个锁请求者能拿到锁。 这就是羊群效应。

1.4 基于Zookeeper设计思路二

使用临时有序znode来表示获取锁的请求,创建最小后缀数字 znode 的用户成功拿到锁。
公平锁的实现

 

        在实际的开发中,如果需要使用到分布式锁,不建议去自己“重复造轮子”,而建议直接使用Curator客户端中的各种官方实现的分布式锁,例如其中的InterProcessMutex可重入锁。

1.5 Curator 可重入分布式锁工作流程

https://www.processon.com/view/link/5cadacd1e4b0375afbef4320

1.6 总结

优点:ZooKeeper分布式锁(如InterProcessMutex), 具备高可用、可重入、阻塞锁特性,可解决失效死锁问题 ,使用起来也较为简单。
缺点: 因为需要频繁的创建和删除节点,性能上不如 Redis
在高性能、高并发的应用场景下,不建议使用ZooKeeper的分布式锁。而由于ZooKeeper的高可靠
性,因此在并发量不是太高的应用场景中,还是推荐使用ZooKeeper的分布式锁。

2. 基于Zookeeper实现服务的注册与发现

基于 ZooKeeper 本身的特性可以实现服务注册中心

2.1 设计思路

2.2 Zookeeper实现注册中心的优缺点

优点:
        高可用性: ZooKeeper是一个高可用的分布式系统,可以通过配置多个服务器实例来提供容错能力。如果其中一 个实例出现故障,其他实例仍然可以继续提供服务。
        强一致性: ZooKeeper保证了数据的强一致性。当一个更新操作完成时,所有的服务器都将具有相同的数据视 图。这使得ZooKeeper非常适合作为服务注册中心,因为可以确保所有客户端看到的服务状态是一致的。
        实时性: ZooKeeper的监视器(Watcher)机制允许客户端监听节点的变化。当服务提供者的状态发生变化时 (例如,上线或下线),客户端会实时收到通知。这使得服务消费者能够快速响应服务的变化,从而实现动态服 务发现。
缺点:
        性能限制 ZooKeeper的性能可能不如一些专为服务注册中心设计的解决方案,如nacos或Consul。尤其是在大 量的读写操作或大规模集群的情况下,ZooKeeper可能会遇到性能瓶颈。

2.3 整合Spring Cloud Zookeeper实现微服务注册中心

https://spring.io/projects/spring-cloud-zookeeper#learn
第一步:在父pom文件中指定Spring Cloud版本
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>1.8</java.version><spring-cloud.version>Hoxton.SR8</spring-cloud.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
注意: springboot和springcloud的版本兼容问题
第二步:微服务pom文件中引入Spring Cloud Zookeeper注册中心依赖
<!-- zookeeper服务注册与发现 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zookeeper-discovery</artifactId><exclusions><exclusion><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId></exclusion></exclusions></dependency><!-- zookeeper client --><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.8.0</version></dependency>
注意: zookeeper客户端依赖和zookeeper sever的版本兼容问题
Spring Cloud整合Zookeeper注册中心核心源码入口: ZookeeperDiscoveryClientConfiguration
第三步: 微服务配置文件application.yml中配置zookeeper注册中心地址
spring:cloud:zookeeper: connect-string: localhost:2181discovery:instance-host: 127.0.0.1
注册到zookeeper的服务实例元数据信息如下:
注意:如果address有问题,会出现找不到服务的情况,可以通过instance-host配置指定
第四步:整合feign进行服务调用
 @RequestMapping(value = "/findOrderByUserId/{id}")public R findOrderByUserId(@PathVariable("id") Integer id) {log.info("根据userId:"+id+"查询订单信息");//feign调用 R result = orderFeignService.findOrderByUserId(id);return result;}
测试: http://localhost:8040/user/findOrderByUserId/1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/311867.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CloneNotSupportedException的解决方案 + Object的clone方法分析

CloneNotSupportedException的解决方案 引入问题&#xff1a; 在一次测试clone方法时&#xff0c;D类Override了Object类的clone方法 public class D {private Integer A1;private Integer A2;public D() {}public D(Integer a1, Integer a2 {A1 a1;A2 a2;}Overrideprotec…

Docker:Docker集群配置与应用(Docker Swarm)

Docker集群配置与应用 前言学习目标 1. 建立Docker Swarm集群1.1 为什么要使用容器集群1.2 什么是Swarm集群1.3 Docker Swarm特性1.4 Swarm节点1.5 Swarm 集群管理命令Swarm 集群节点管理命令 1.6 Docker Swarm 集群搭建 前言 可以认为Docker Swarm(Go语言开发)将一个Docker主…

Powermill各版本安装指南

下载链接 https://pan.baidu.com/s/1CsrYEUQNmDa820RxDV2G6Q?pwd0531 1.鼠标右击【PowerMill2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 PowerMill2024(64bit)】。 2.打开解压后的文件夹&#xff0c;双击打开【Setup】文…

CorelDRAW 2024最新版本功能介绍含注册机序列号

始于1989年并不断推陈出新,致力为设计工作者提供更高效的设计工具&#xff01;CorelDRAW滋养并见证了一代设计师的成长&#xff01;在最短的时间内交付作品&#xff0c;CorelDRAW的智能高效会让你一见钟情&#xff01;CorelDRAW 全称“CorelDRAW Graphics Suite“&#xff0c;也…

JUC Lock 锁入门

文章目录 死锁&#xff08;Deadlock&#xff09;通过 Visualvm 等工具排查死锁 活锁park & unpark与 wait & notify 的区别park & unpark 实现&#xff1a;点外卖 Lock 对象ReentrantLock 可重入锁可重入lockInterruptibly 方法上锁&#xff08;可打断&#xff09;…

语义分割的应用及发展

语义分割(Semantic Segmentation)是一种计算机视觉领域的任务&#xff0c;旨在将一张图像中的每一个像素都分配一个语义标签&#xff0c;即将图像中的每个物体区域进行精确的分类划分。例如&#xff0c;在一张街景图中&#xff0c;语义分割可以将人、车、路、天空等每个像素分别…

十大排序算法归纳

目录 排序算法的分类 插入排序算法模板 选择排序算法模板 冒泡排序算法模板 希尔排序算法模板 快速排序算法模板 归并排序算法模板 堆排序算法模板 基数排序算法模板 计算排序算法模板 桶排序算法模板 排序算法的分类 插入&#xff1a;插入&#xff0c;折半插入&am…

非科班,培训出身,怎么进大厂?

今天分享一下我是怎么进大厂的经历&#xff0c;希望能给大家带来一点点启发&#xff01; 阿七毕业于上海一所大学的管理学院&#xff0c;在读期间没写过一行 Java 代码。毕业之后二战考研失利。 回过头来看&#xff0c;也很庆幸这次考研失利&#xff0c;因为这个时候对社会一…

linux go环境安装 swag

下载依赖包 go get -u github.com/swaggo/swag编译 移动到下载的go-swagger包目录,一般在$GOPATH/pkg/mod下 查看 GOPATH echo $GOPATHcd /root/GolangProjects/pkg/mod/github.com/swaggo/swagv1.16.2go install ./cmd/swag/不出意外&#xff0c;$GOPATH/bin下 已经有了sw…

基于CMake的大型C++工程组织

此文适合大型C工程&#xff0c;涉及到多个自定义库&#xff0c;多个第三方库&#xff0c;以及还有给第三方用户进行二次开发的需求下&#xff0c;应对这种复杂编译环境下的工程组织方式的一些经验介绍&#xff0c;希望给大型工业软件的开发者一些参考 一个大型工程&#xff0c…

数据结构—树的应用

文章目录 11.树的应用(1).Huffman树#1.加权外部路径长度#2.Huffman算法#3.Huffman编码 (2).二叉搜索树#1.基本定义#2.查找#3.插入结点#4.构建树#5.查找最小值和最大值#6.删除结点#7.一个问题 (3).平衡搜索树#1.满二叉树、完全二叉树和丰满二叉树#2.平衡因子和平衡树#3.左旋与右…

图像中的傅里叶变换及低通与高通滤波

傅里叶变换 高频&#xff1a;在图像中变化剧烈的灰度分量&#xff0c;如边界。 低频&#xff1a;在图像中变化缓慢的灰度分量。 OpenCV中函数为cv2.dft()和cv2.idft()&#xff0c;输入图像要先转换成np.float32格式。得到的结果频率为0的部分会在左上角&#xff0c;为方便处理…