当前位置: 首页 > news >正文

JAVA 分布式锁的5种实现方式

1、分布式锁的基本概念

        分布式锁 是在分布式系统环境下,控制多个进程/服务/主机互斥访问共享资源的核心协调机制。它解决了单机锁(如Java的synchronizedReentrantLock)在分布式场景下失效的问题,是构建可靠分布式应用的必备工具。

        解决我们在多个jvm中最终只能有一个jvm执行,从而保证了幂等性的问题。

2、业务超时,一直不释放锁如何处理?

        可以采用续命设计,续命多次,如果业务还是没有执行完毕,则认为超时,应该主动释放该锁,防止其他jvm一直阻塞等待。

(1)主动释放锁;(2)回滚当前业务逻辑;(3)主动停止该线程;(4)移除监听。

3、集群环境中保证定时任务执行的幂等性问题

幂等性:执行结果保证唯一不能够重复。

当我们定时任务服务集群的情况下,有可能会同时重复执行定时任务,

解决思路:

        多个jvm集群的定时任务,在触发的时候,获取分布式锁,如果能够获取到分布式锁的jvm,就能够执行定时任务,没有获取到的就不能执行定时任务。

4、基于zookeeper实现分布式锁

(1)实现分布式锁思路:

        因为Zookeeper节点路径保持唯一,不允许重复,且有临时节点特性,连接关闭后当前节点会自动消失,从而实现分布式锁。

(2)实现原理:(临时节点 + 事件通知)

        多个jvm请求同时创建相同的临时节点(lockPath),只要谁能够创建成功 谁就能够获取到锁;如果创建节点的时候,突然该节点已经被其他请求创建的话则直接等待;只要能够创建节点成功,则开始进入到正常业务逻辑操作,其他没有获取到锁的jvm进行等待;正常业务逻辑流程执行完后,调用zk关闭连接方式释放锁,从而使其他的请求开始进入到获取锁的资源。

疑问:如果使用zk实现分布式锁,获取锁之后业务逻辑方法一直没有执行完毕,导致其他所有的请求等待的话如何解决?

 设置Session连接超时时间,在规定的时间内获取锁后超时啦~自动回滚当前数据库业务逻辑。

5、基于数据库实现分布式锁

(1)悲观锁

        就是先select … for update 锁住主键key_resource那个记录,如果为空,则可以插入一条记录,如果已有记录判断下状态和时间,是否已经超时。这里需要注意一下哈,必须要加事务哈。

(2)搞个version字段

        每次更新修改,都会自增加一,然后去更新余额时,把查出来的那个版本号,带上条件去更新,如果是上次那个版本号,就更新,如果不是,表示别人并发修改过了,就继续重试。

6、基于redis实现分布式锁

(1)采用Setnx

        Redis中SetnX与Set命令的区别

        Setnx 可以返回该key是否存在,存在返回0 ,不存在返回1,如果该key存在的情况下,是不能做修改的。Set 每次直接覆盖该key对应的value。

获取锁的原理:

        多个redis客户端执行setNx命令,设置一个相同的redis的key,谁能创建key成功,谁就能获取锁,如果该key已经存在的情况下,则再创建的时候会返回false。

释放锁的原理:

删除该key。

7、基于redisson实现分布式锁

        多个jvm同时在redis中写入一个相同的key,谁能够写入成功,谁就能获取到锁。

      (1)向redis中写入key的时候使用lua脚本,不是setNx;

      (2)如果写入key成功,会单独开启一个看门狗线程(续命定时任务线程),默认的情况下每隔10s时间不断续命延迟。

     (3)一直不断实现续命的情况下,也会发生死锁问题,此时设定续命的次数,续命多次如果业务逻辑还没有执行完毕,主动回滚当前的mysql事务,并释放该锁。

8、基于Curator实现分布式锁(解决羊群效应问题)

核心思想:

        (1)从缓存中查找是否已经创建分布式锁,如果已经创建了分布式锁,则直接复用(具有可重入性)。

        (2)如果缓存中没有,则创建一个分布式锁。

        (3)实现原理

                创建一个临时节点,获取当前父节点下的子节点,如果是为最小的节点,则表示获取锁成功,否则获取锁失败,阻塞等待,则监听上一个节点。

      (4)当上一个节点如果释放锁之后,直接进入到获取锁的状态,唤醒使用wait notify技术。

http://www.dtcms.com/a/322016.html

相关文章:

  • 【C++高阶五】mapset对红黑树的封装
  • 【昇腾】Atlas 500 A2 智能小站制卡从M.2 SATA盘启动Ubuntu22.04系统,重新上电卡死没进系统问题处理_20250808
  • 图片识别表格工具v3.0绿色版,PNG/JPG秒变可编辑Excel
  • Redis初步介绍和分布式系统介绍
  • 项目一系列-第4章 在线接口文档 代码模板改造
  • 临床医学 RANDOM SURVIVAL FORESTS(randomSurvivalForest)-2 python 例子
  • shell脚本使用
  • 软件销售跟进思路
  • 期货和期权对冲后能盈利吗?
  • 大力水手4——AI驱动的多帧生成与神经网络渲染
  • MySQL NULL 值处理详细说明
  • 《天天酷跑》:用Pygame打造经典跑酷游戏的开发与玩法全解析
  • 库函数NTC采样温度的方法(STC8)
  • react的form.resetFields()
  • cuda编程之内核执行配置参数
  • 智慧交通场景下 mAP↑28%:陌讯多模态融合算法实战解析
  • Linux入门到精通,第二周自我总结
  • 书生浦语第五期-L1G3-LMDeploy 课程
  • 配电线路故障定位在线监测装置的技术解析与应用价值
  • C语言编译流程讲解
  • 第七篇:动画基础:requestAnimationFrame循环
  • 解决多线程安全性问题的方法
  • 可编辑51页PPT | 某鞋服品牌集团数字化转型项目建议书
  • 相机Camera日志实例分析之十:相机Camx【萌拍调节AE/AF拍照】单帧流程日志详解
  • 基于MATLAB实现的毫米波大规模MIMO系统中继混合预编码设计
  • [windows]torchsig 1.1.0 gr-spectrumdetect模块安装
  • LeetCode 刷题【34. 在排序数组中查找元素的第一个和最后一个位置、35. 搜索插入位置】
  • 哈希法(Java)
  • 【数据结构】排序(sort) -- 计数排序
  • wstool和git submodule优劣势对比