Java之分布式锁的5种实现过程

 更新时间:2025年09月13日 09:19:02   作者:右手嘚温暖  
这篇文章主要介绍了Java之分布式锁的5种实现过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1、分布式锁的基本概念

分布式锁是在分布式系统环境下,控制多个进程/服务/主机互斥访问共享资源的核心协调机制。

它解决了单机锁(如Java的synchronized、ReentrantLock)在分布式场景下失效的问题,是构建可靠分布式应用的必备工具。

解决我们在多个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…forupdate锁住主键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)当上一个节点如果释放锁之后,直接进入到获取锁的状态,唤醒使用waitnotify技术。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring RedirectAttributes参数跳转代码实例

    Spring RedirectAttributes参数跳转代码实例

    这篇文章主要介绍了Spring RedirectAttributes参数跳转代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • SpringBoot启动流程之引导上下文DefaultBootstrapContext的过程

    SpringBoot启动流程之引导上下文DefaultBootstrapContext的过程

    本文详细介绍了SpringBoot版本2.7.18中SpringApplication的run方法,引导注册组件初始化器BootstrapRegistryInitializer是SpringBoot的第一个扩展点,负责应用启动早期阶段的初始化和配置,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Java getParameter方法案例详解

    Java getParameter方法案例详解

    这篇文章主要介绍了Java getParameter方法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • JVM运行时数据区原理解析

    JVM运行时数据区原理解析

    这篇文章主要介绍了JVM运行时数据区原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • java网络爬虫连接超时解决实例代码

    java网络爬虫连接超时解决实例代码

    这篇文章主要介绍了java网络爬虫连接超时解决的问题,分享了一则使用httpclient解决连接超时的Java爬虫实例代码,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • java实现画图板功能

    java实现画图板功能

    这篇文章主要为大家详细介绍了java实现画图板功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • spring boot整合Swagger2的示例代码

    spring boot整合Swagger2的示例代码

    Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的 Web 服务。这篇文章主要介绍了spring boot整合Swagger2,需要的朋友可以参考下
    2017-04-04
  • 教你在SpringBoot中管理多环境配置文件

    教你在SpringBoot中管理多环境配置文件

    在项目开发中,一般会分为开发环境,测试环境和生产环境.如果总是在一个文件中修修改改,难免会出现错误,尤其是在交接的过程中,一旦出现问题,轻则丢失绩效,重则需要删库跑路.本文则带大家详细了解怎么管理多环境配置文件,需要的朋友可以参考下
    2021-05-05
  • 解析阿里一面CyclicBarrier和CountDownLatch的区别

    解析阿里一面CyclicBarrier和CountDownLatch的区别

    这篇文章主要介绍了阿里一面CyclicBarrier和CountDownLatch的区别是啥,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Rxjava+Retrofit+MVP实现购物车功能

    Rxjava+Retrofit+MVP实现购物车功能

    这篇文章主要为大家详细介绍了Rxjava+Retrofit+MVP实现购物车功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05

最新评论