分布式锁的产生以及使用

日常开发中,针对一些需要锁定资源的操作,例如商城的订单超卖问题、订单重复提交问题等。

都是为了解决在资源有限的情况限制客户端的访问,对应的是限流。

单节点锁问题

目前针对这种锁资源的情况采取的往往是互斥锁,例如 java 里的 synchronized 锁以及 ReentrantLock,其中 synchronized 的加锁操作在 jvm 层面实现,会有一个锁升级(偏向锁、轻量级锁、重量级锁)的问题,ReentrantLock 需要手写代码实现,底层是 AQS。但是 java 层面的锁有一个问题,就是只能在一个进程中使用,如果跨进程就无能为力了,例如应用的集群部署,客户端请求过来后通过负载均衡策略转发到对应的实例上。

分布式锁

鉴于以上单节点锁的问题,就需要通过一个中间介质来实现针对需要访问的资源进行一个资源加锁和释放操作的问题,目前有如下方式

数据库

将需要访问的数据可以放到数据库的表中,一般存储的是确保唯一性的业务主键,在访问资源时可将业务主键插入到表中,每次访问资源前先查询数据库判断数据是否存在,如果存在表明资源在被访问,否则就正常处理。

zookeeper

https://zookeeper.apache.org/doc/r3.9.1/recipes.html#sc_recipes_Locks

通过临时顺序节点(EPHEMERAL_SEQUENTIAL )来实现,这种类型的节点的好处是会话级别,如果会话结束节点会删除掉。

官方提供的是 curator 组件库,在项目的 pom.xml 中引入如下依赖

		<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>5.5.0</version></dependency>

https://curator.apache.org/docs/getting-started#distributed-lock

内部提供了一个分布式锁接口 InterProcessLock,通过对应的实现类 InterProcessMutex 进行加锁和释放锁操作。

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;import java.util.concurrent.TimeUnit;public class DistributedLock {public static void main(String[] args) throws InterruptedException {RetryPolicy retryPolicy = new ExponentialBackoffRetry(10000, 3);for (int i = 1; i <= 1; i++) {new Thread(() -> {try (CuratorFramework client = CuratorFrameworkFactory.newClient(Constants.CONNECTION_URL, retryPolicy);){client.start();InterProcessLock lock1 = new InterProcessMutex(client, "/dlock");try {lock1.acquire(5, TimeUnit.SECONDS);System.out.println("lock1获取");TimeUnit.SECONDS.sleep(5);lock1.release();System.out.println("lock1释放");} catch (Throwable e) {e.printStackTrace();}}}).start();}}
}

锁的组成如下

/父节点/_c_+UUID+-lock-+10位数(从0开始自增,不足10位用0补足)

如果在执行过程中进行了多次加锁,具体如下

/dlock/_c_0d4db7a9-5c21-4a57-9904-e42cd970d774-lock-0000000000
/dlock/_c_d3588ec1-981a-41aa-a420-89f7949f94d6-lock-0000000001

这样就会有一个问题,前面的前缀 PROTECTED_PREFIX 和 UUID 会对节点产生干扰。

https://github.com/apache/curator/blob/apache-curator-5.5.0/curator-framework/src/main/java/org/apache/curator/framework/imps/ProtectedUtils.java#L65

可以将 ProtectedUtils 整个类复制一遍在项目中,将 getProtectedPrefix() 的内容进行修改,如下

修改前

public static String getProtectedPrefix(final String protectedId)
{return PROTECTED_PREFIX + protectedId + PROTECTED_SEPARATOR;
}

修改后

public static String getProtectedPrefix(final String protectedId)
{return protectedId;
}

这样生成的节点格式为

/父节点/lock-+10位数(从0开始自增,不足10位用0补足)

最终生成的节点如下

/dlock/lock-0000000000

其中对应的节点值为当前请求的 ip

[zk: localhost:2181(CONNECTED) 2] get /dlock/lock-0000000000
192.168.106.109

如果有多个客户端针对同一个节点进行加锁请求,会按序创建多个节点,但是持有锁的只是最小的节点,后面的节点会向获取锁的节点注册 Watcher 来监听持有锁的节点是否存在。

redis

作为一个在内存层次的数据库,用处多多,其中可以用于分布式锁。

redis 提供了 lua 脚本支持,lua 脚本可以做到将操作进行打包,确保整个操作的原子性。其中分布式锁就用到了 lua 脚本。

redis 官方介绍

https://redis.io/docs/manual/patterns/distributed-locks/

该锁被命名为 Redlock,在不同的语言中有对应的实现,在 java 中对应的是 redisson。

在项目的 pom.xml 中引入如下依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.26.0</version>
</dependency>  

github 项目链接

https://github.com/redisson/redisson

与 spring boot 整合

https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter#spring-boot-starter

区别

分布式锁建立在共享介质上,所以上面的三种方式都需要借助于其他组件来实现。

数据库层面不适合做高并发处理。

redis 依赖于全局时间,需要考虑到加锁时间的问题。

zookeeper 建立在创建节点的基础上,属于重操作,相对于 redis 内存操作慢一些。

由于 zookeeper 使用了 zab 协议,针对写请求会转发到领导者,如果领导者节点宕机,会从跟随者节点中选举出数据最完整的节点晋升为领导者,不会出现类似 redis 异步同步数据丢失的问题。

对于一些并发请求大的应用,使用 zookeeper 可能出现锁获取失败的情况,使用 redis 集群不会因为,因为 redis 的单线程高并发处理一般情况下难以达到,一般瓶颈在网卡带宽上。

之前自己写的文章

https://blog.csdn.net/zlpzlpzyd/article/details/132716450

参考链接

https://www.jianshu.com/p/31335efec309

https://www.cnblogs.com/xuwc/p/14019932.html

https://juejin.cn/post/6844903729406148622

https://www.cnblogs.com/crazymakercircle/p/14504520.html

https://blog.csdn.net/qq_26709459/article/details/112770526

https://zhuanlan.zhihu.com/p/639756647

https://zhuanlan.zhihu.com/p/383512946

https://www.cnblogs.com/zwj-199306231519/articles/17411947.html

https://baijiahao.baidu.com/s?id=1784900642230670850

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

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

相关文章

顶顶通用户申请和安装 空号识别 模块流程

一、申请 空号识别 授权 打开网址&#xff1a;http://my.ddrj.com&#xff0c;注册并登录。 点击“我的授权” -> “申请授权” &#xff08;根据负责人的要求选择“在线”或是“离线”&#xff09;。 找到名称为空号识别的授权并点击“加号”图标打开授权&#xff0c;然…

Uni-App三甲医院、医保定点三甲医院在线预约挂号系统源码

医院在线预约挂号系统是一种方便患者预约挂号的系统&#xff0c;患者可以通过该系统进行预约挂号&#xff0c;省去了到医院现场排队等待的时间&#xff0c;提高了就诊效率。随着医院信息化水平的不断发展&#xff0c;医院在线预约挂号管理系统已成为医院管理中不可或缺的一部分…

SQL-窗口函数

什么是窗口函数 可以像聚合函数一样对一组数据进行分析并返回结果&#xff0c;二者的不同之处在于&#xff0c;窗口函数不是将一组数据汇总成单个结果&#xff0c;而是为每一行数据都返回一个结果。 窗口函数组成部分 1.创建数据分区 窗口函数OVER子句中的PARTITION BY选项用…

大师学SwiftUI第6章 - 声明式用户界面 Part 3

安全域视图 SwiftUI还内置了创建安全文本框的视图。这一视图会把用户输入的字符替换成点以及隐藏敏感信息&#xff0c;比如密码。 SecureField(String, text: Binding)&#xff1a;该初始化方法创建一个安全输入框。第一个参数定义占位文本&#xff0c;​​text​​参数为存储…

leetcode 013二维区域和检索---矩阵不可变

给定一个二维矩阵 matrix&#xff0c;以下类型的多个请求&#xff1a; 计算其子矩形范围内元素的总和&#xff0c;该子矩阵的左上角为 (row1, col1) &#xff0c;右下角为 (row2, col2) 。 实现 NumMatrix 类&#xff1a; NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进…

Quartus II使用小技巧

工程结构&#xff1a; 在建立完某项设计的文件后&#xff0c;依次在其里面新建四个文件夹&#xff0c;分别为&#xff1a;rtl、qprj、msim、doc。 rtl文件夹用于存放设计的源文件。 doc文件夹用于存放设计的一些文档性的资料。 qprj文件夹用于存放quaruts 工程以及quartus生…

Git入门详细教程

一、Git概述&#x1f387; Git官网 Git是一个开源的分布式版本控制系统&#xff0c;用于跟踪文件的变化和协作开发。它允许多个开发者在同一项目中共同工作&#xff0c;并能够有效地管理代码的版本和历史记录。Git可以帮助开发团队更好地协作&#xff0c;追踪代码变更&#xf…

记一次多平台免杀PHP木马的制作过程

注意&#xff1a;本文转载自本作者稀土掘金博客 博客地址&#xff1a; 御坂19008号 的个人主页 - 动态 - 掘金 文章目录 前言声明绕过情况使用方法运行环境绕过点介绍技术原理讲解变量传值覆盖模块代码执行阻断模块InazumaPuzzle程序锁定器PerlinNoise危险函数生成与执行类构造…

Android 基础技术——addView 流程

笔者希望做一个系列&#xff0c;整理 Android 基础技术&#xff0c;本章是关于 addView 在了解 addView 流程之前&#xff0c;先回答下以下几个问题&#xff1a; PhoneWindow是什么时候创建的&#xff1f; DectorView 是什么&#xff1f; DectorView 是什么时候创建的&#xf…

Oracle行转列函数,列转行函数

Oracle行转列函数&#xff0c;列转行函数 Oracle 可以通过PIVOT,UNPIVOT,分解一行里面的值为多个列,及来合并多个列为一行。 PIVOT PIVOT是用于将行数据转换为列数据的查询操作(类似数据透视表)。通过使用PIVOT&#xff0c;您可以按照特定的列值将数据进行汇总&#xff0c;并将…

Flowable 生成流程图

/*** 生成流程图** param processId 任务ID*/ RequestMapping("/diagram/{processId}") public void genProcessDiagram(HttpServletResponse response,PathVariable("processId") String processId) {InputStream inputStream flowTaskService.diagram(p…

SpringCloud整合Zookeeper代替Eureka案例

文章目录 本期代码下载地址zookeeper简介zookeeper下载安装新建服务提供者测试 新建消费者测试 本期代码下载地址 地址:https://github.com/13thm/study_springcloud/tree/main/days4 zookeeper简介 zookeeper是一个分布式协调工具&#xff0c;可以实现注册中心功能 关闭Lin…

WampServer

开发笔记 推荐链接php无法保存SESSION问题部署SSL时候产生的问题 推荐链接 链接目录 php无法保存SESSION问题 php.ini文件和phpForApache.ini 文件 里面都有 对路径的控制&#xff0c;相关路径问题可能也需要进行修改&#xff0c;打开文件搜索wamp64或wamp 就可以看到了&…

线程池--JAVA

虽然线程是轻量级进程&#xff0c;但是如果当创建和销毁的的频率非常之高&#xff0c;那么它也就会消耗很多的资源。 而线程池就是用来优化线程频繁创建和销毁的场景&#xff0c;减少线程创建、销毁的频率。 ExecutorService JAVA标准库为我们实现了线程池&#xff0c;Execu…

windows11上安装虚拟机VMware

1、安装虚拟机&#xff08;待补充&#xff09; 第二步&#xff1a;安装VMware tools 实现windows文件上传到虚拟机中 1、安装好虚拟机后&#xff0c;查看虚拟机ip用Xshell连接虚拟机&#xff0c;并安装VMware tools(只有安装了VMware tools才能实现虚拟机和本机的文件共享。在…

无人机航迹规划(四):七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划(提供MATLAB代码)

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁殖…

Python编辑开发---pycharm pro 2023 中文

PyCharm Pro 2023是一款功能强大的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;旨在提高Python开发人员的生产力。它提供了智能代码编辑、实时代码分析和调试工具&#xff0c;支持版本控制和数据库工具&#xff0c;以及可扩展的插件系统。PyCharm Pro 2023可在多…

什么是区块链?

区块链 区块链 &#xff08;英语&#xff1a;blockchain&#xff09;是借由 密码学 与 共识机制 等技术建立&#xff0c;存储数据的 保证不可篡改和不可伪造的 分布式技术。 什么是区块 区块 就是将一批数据打包在一起&#xff0c;并且给打包出来的区块编号。第一个区块的编…

Kylin 安装novnc 远程访问

noVNC可以使用浏览器直接访问服务器&#xff0c;而不需要使用VNC客户端。 1.初始环境 关闭防火墙或允许IP访问本机 2.安装依赖 dnf install -y tigervnc-server git 3.git下载novnc git clone https://github.com/novnc/noVNC.git git clone https://gitee.com/yangyizhao…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用相机日志跟踪功能&#xff08;C&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和短曝光功能的技术背景Baumer工业相机通过NEOAPI SDK使用相机日志跟踪功能1.引用合适的类文件2.通过NEOAPI SDK使用相机日志跟踪功能3.通…