分布式锁的实现?

news2024/11/25 10:48:54

分布式锁的实现?

答:

应用比较广泛:后台业务的防重提交

以前的传统应用用户流量比较小,为了节省成本,很多应用的成本都是单节点部署,为了解决单节点访问资源一致性的问题,对于java来说,一般使用的是synchronized和Renntrantlock锁来进行实现的,但是随着微服务架构的兴起,为了支持高并发的流量,和高可用的结构,应用逐渐就从单节点到多节点,到集群,这个时候jvm的锁就没有办法满足我们的需求了,于是就出现了分布式锁的概念,那么分布式锁究竟是什么,分布式锁是分布式系统或者集群环境下,多进程可见,并且互斥的锁,如果要实现优秀的分布式锁,需要具备的特性,首先这个锁对多个集群节点是可见的,其次,这个锁对各个节点是互斥的,这个锁还必须是高可用的,不能在我业务执行的过程中,这个锁突然失效了,最后这个锁必须是高性能的,一个优秀的分布式锁加锁一般都是几毫秒。在互联网高并发的情况下会出现各种各样的问题,失效锁重入,所以分布式锁高可用就要支持这些异常的场景。
1.常见的分布式锁的方案:
1.基于数据库的实现(3种) C端高并发不适合,后台管理系统,可以根据场景选择这个方案
1.防重表(新系统可以使用,因为他是不侵入我们的业务,实现简单)
通过操作表的数据来实现,获取锁的时候插入一条记录,释放锁的时候删除一条记录。
设计字段:id(自增) 唯一的key 创建时间 更新时间等等
怎么获取锁和释放的锁的呢?
执行业务方法的时候,我们可以向这个表插入一条记录,这个记录里面的唯一key可以设置为业务的主键,或者业务的编号。如果多个请求进入这个方法,那么只有一个方法能够插入成功。因为我们的数据库有一个唯一的key做保证的。加完锁的话就执行我们的业务逻辑,执行完业务逻辑的话,我们就要释放锁,通过根据防重表里面的唯一键去删除对应的记录。删除了之后,这个请求他持有的分布式锁就被释放掉了,后面的请求过来的话,就可以拿到这个锁。
优点:就是方案很简单,只需要以来数据库,不需要依赖任何的中间件
缺点:当我们执行方法插入防重表记录的时候,把它加锁了,这个时候由于其他原因被重启了,锁的记录没有被释放,就会产生了死锁,所以,我们的解决方法就是在防重中加入一个过期时间的字段。再起一个定时任务,定时去扫描当前过期时间和我们的当前时间做对比,如果说过期了的话我们就把这条记录给删掉,这样我们就实现了死锁的问题。
再就是阻塞的问题。 锁的可重入问题(这个可以通过在表中加一个字段线程的id,加锁的次数字段,获取了锁的进程每次进来就把次数字段+1,每次释放-1,直到线程次数为0,这个线程持有的锁就会释放)
2.悲观锁(性能差,最简单)
利用了业务表的行锁,sql中用for update把他给锁掉,但是mysql的innodb在进行加锁的时候,必须要加一个唯一的索引主键,如果不加这个的话,那查询的时候用for update可能会把你的整个表都给锁了,所以在用的时候要非常的慎重
执行的过程:以spring为例。
a.开启spring的事务的自动事务提交,比如在方法或者类上加一个transaction,
b.开始执行锁掉的记录,select …for update来实现
c.执行业务逻辑。
d.spring自动提交事务,最后就把锁给释放掉了
优点:1.天然的实现了阻塞
缺点:2.性能很差
3.乐观锁
一般我们认为数据的更新是不会发生冲突的,只有数据库在更新提交的时候,我们才会进行数据的检测,如果在检测的时候出现了数据不一致的情况,就会返回失败的信息,实现乐观锁的话就要可以加版本号、时间戳
优点:不用锁表,也不用锁记录,他会检测这个数据的版本是不是一致 ,相对来说他的性能会比悲观锁要强很多,但是高并发发时候,对数据库的冲击也比较大,因为版本号要经常的去更新和维护

2.基于redis的实现
在这里插入图片描述
3.基于zookper的实现

  • 核心思想:当客户端要获取锁,则创建节点,使用完锁,就删除该节点!
    1.客户端获取到锁,在lock节点下创建临时顺序节点。(避免了宕机问题)
    2.然后获取到lock下面的所有子节点,客户端获取到所有子节点之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。使用完锁后,就将该节点删除。
    3.如果发现自己创建的节点,并非lock所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,同时对其注册事件监听器,监听删除事件。
    4.如果发现比自己小的那个节点被删除,则客户端的Watcher会收到相应通知,此时再次判断自己创建的节点是否是lock子节点中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听。

参考博客:https://blog.csdn.net/MoastAll/article/details/125320077

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux系统(守护进程-线程)08_守护进程,线程,线程创建,线程退出,线程回收,杀死线程,线程分离,线程属性分离

01 学习目标 1.守护进程的特点 2.熟练进行守护进程的创建 3.熟练掌握多线程的创建 4.熟练掌握线程的退出和资源回收 02 守护进程相关的概念 进程组:多个进程在同一个组,第一个进程默认是进程组的组长。 会话:进程组的更高一级,多…

二分搜索帮我解决实际问题

文章阅读 文章阅读 二分搜索代码框架常应用于「在有序数组中搜索指定元素」这个基本场景,具体的实际问题可以没有那么直接,但是也可以使用二分搜索进行解决 实际问题一般都让你求最值,比如让你求吃香蕉的「最小速度」,让你求轮船…

JavaWeb《后端内容:4. 项目实战:书城系统》

0.把之前的系统的Myssm部分封装为包 新建空的工件jar包 创建相同的文件夹,导入相应文件要从out里面导入字节码文件 全部设置完后点构建工件,然后点刚刚我们设置的这个工件,然后从src下的out文件相应的位置就能找到这个jar包,用于…

Discourse Table Builder 插件

ABC 仓库链接GitHub - discourse/discourse-table-builder: A theme component that allows for easily building and editing of markdown tables in Discourse. 概述Table Builder 这个插件能够让用户能够在 Discourse 的编辑对话框中快速的对表格进行编辑,同时也…

Flink学习——处理不同数据源的流数据,存入不同的Sink端

目录 一、单机版安装 二、IDEA操作Flink (一)添加依赖 (二)数据源——Source 1.加载元素数据 2.加载集合数据 3.加载文件目录 4.加载端口 5.加载kafka的topic——重要&常用 6.加载自定义数据源 (三)输出端——Sink 1.读取文件中的数据,处理后输出到…

ESP32设备驱动-振动电机模块驱动

振动电机模块驱动 文章目录 振动电机模块驱动1、振动电机介绍2、硬件准备3、软件准备4、驱动实现1、振动电机介绍 振动电机是用于产生振动的机械装置。 振动的产生是在驱动轴上质量不均匀的电动机的支持下发生的。 它是一种微型直流电机,通过振动让用户知道声音。 在此必须注…

《计算机网络—自顶向下方法》 Wireshark实验(五):UDP 协议分析

用户数据报(UDP)协议是运输层提供的一种最低限度的复用/分解服务,可以在网络层和正确的用户即进程间传输数据。UDP 是一种不提供不必要服务的轻量级运输协议,除了复用/分用功能和简单的差错检测之外,几乎就是 IP 协议了,也可以说它…

RabbitMQ养成记 (10.高级特性:死信队列,延迟队列)

死信队列(DLX) 这个概念 在其他MQ产品里面也是有的,只不过在Rabbitmq中稍微特殊一点 什么叫私信队列呢? 就是当消息成为 dead message之后,可以重新发到另外一台交换机,这个交换机就是DLX。 注意这里的有翻…

基于OpenCV的人脸检测软件(含Python源码+UI界面+图文详解)

软件功能演示 摘要:人脸检测的目标是找出图像中所有的人脸对应的位置,算法的输出是人脸外接矩形在图像中的坐标,可能还包括姿态如倾斜角度等信息。本文详细介绍了其实现的技术原理,同时给出完整的Python实现代码,并且通…

GeoTools实战指南: 空间坐标系-地理信息科学的核心

GeoTools实战指南: 空间坐标系-地理信息科学的核心 引言 在我们的日常生活中,地图、GPS导航和地理位置服务已经变得司空见惯。但是,你有没有想过这些工具背后的工作原理呢?它们都依赖于一种称为"空间坐标系"的关键概念。本文将深入探讨空间坐标系的基础知识和其…

多线程专题(上)学习随手笔记

JMM:主内存物理内存线程共享,工作内存CPU缓存线程独占volatile:可见性、禁止指令重排,不可保证原子性;用于懒汉单例模式(双重检测)或状态标记Synchronized:保证代码块或方法同步化执…

Unity的URP下使用SRPBatcher

大家好,我是阿赵。这里继续来讲一下URP相关的东西。 这次主要说的是SRP Batcher的使用 一、在URP下实现SRP Batcher 1、设置 在我们创建的URPAsset文件的高级选项里面,有一个SRP Batcher的开关,默认就是勾上的。 2、修改shader 在把项目转…

小白白也能学会的 PyQt 教程 —— 自定义组件 Switch Button

文章目录 前言思路讲解代码部分 前言 最近在搞 Python 课程设计,想要搞一个好看的 UI,惊艳全班所有人。但打开 Qt Creator,Win7 风格的复古的按钮是在让我难以下手。 其次,我因为想要打造一个 Fluent UI 样式的设置页面&#xff…

详解c++STL—string组件

目录 一、string基本概念 1、本质 2、string和char * 区别: 3、特点: 二、string构造函数 1、构造函数原型 2、示例 三、string赋值操作 1、赋值的函数原型 2、示例 四、string字符串拼接 1、函数原型 2、示例 五、string查找和替换 1、功…

tomcat目录结构

tomcat服务器安装根目录下有很多子目录,这些目录的作用是: (1)bin:存放了tomcat服务器中的可执行的批处理文件(startup.bat shutdown.bat) (2)conf:存放了tomcat相关的配置文件(其中的server.xml是tomcat服务器核心配置文件) …

26. Pandas处理分析网站原始访问日志

Pandas处理分析网站原始访问日志 目标:真实项目的实战,探索Pandas的数据处理与分析 实例: 数据来源:我自己的wordpress博客蚂蚁学Python – 你有没有为写代码拼过命?那你知不知道 人生苦短,我用Python&am…

Python挑选出无Labelme标注文件的图片文件

Python挑选出无Labelme标注文件的图片文件 前言前提条件相关介绍实验环境Python挑选出无Labelme标注文件的图片文件代码实现输出结果 前言 本文是个人使用Python处理文件的电子笔记,由于水平有限,难免出现错漏,敬请批评改正。 (https://blog.…

【设计原则与思想:总结课】38 | 总结回顾面向对象、设计原则、编程规范、重构技巧等知识点

到今天为止,设计原则和思想已经全部讲完了,其中包括:面向对象、设计原则、规范与重构三个模块的内容。除此之外,我们还学习了贯穿整个专栏的代码质量评判标准。专栏的进度已经接近一半,马上就要进入设计模式内容的学习…

Python: 生成ubuntu apt镜像地址

文章目录 1. 目的2. 设计3. 实现4. 调用5. 参考 1. 目的 每次新配置 Ubuntu 系统,免不了配置 apt 源。尽管可以通过 GUI 界面进行选择,但自动化程度不够,不同桌面(Unity/Gnome/KDE)下的界面也不太一样; 使…

Java基础-sleep和wait的区别

本文介绍Java中sleep和wait方法的使用区别 文章目录 sleep()wait()sleep()和wait()对比区别相同点 sleep() 查看sleep方法,可见其是static native方法 public static native void sleep(long millis) throws InterruptedException;sleep()方法需要指定等待的时间。…