浅谈Java分布式架构下如何实现分布式锁

 更新时间:2020年07月24日 16:42:46   作者:林口  
这篇文章主要介绍了浅谈Java分布式架构下如何实现分布式锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Java技术迷

  01分布式锁运用场景

  互联网秒杀,抢优惠卷,接口幂等性校验。咱们以互联网秒杀为例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@RestController
 @Slf4j
 publicclassIndexController{
 @Autowired
 privateRedissonredission;
 @Autowired
 privateStringRedisTemplatestringRedisTemplate;
 @RequestMapping("/deduct_stock")
 publicStringdeductStock()throwsInterruptedException{
 intstock=Integer.parseInt
 (stringRedisTemplate.opsForValue().get("stock"));
 if(stock>0){
 intrealStock=stock-1;
 stringRedisTemplate.opsForValue().set("stock",realStock+"");
 log.info("扣减成功,剩下库存+"+realStock);
 }else{
 return"库存不足";
 }
 return"end";
 }
 }

  上面代码假定多个线程一起进来,读到胡成果相同,写入的成果也相同。造成多个减库存操作,只减少了一次。

 好多人想到的处理方式是加synchronized,但是假如是集群项目呢?搭建的是负载均衡项目。打开了两个jvm进程,jvm进程锁失效。

  用nginx做负载均衡,启用两个服务。进行下压测。成果和咱们想的相同,用suynchronized关键字加锁,两台服务器打印的剩下库存有相同的。所以这种方法并没有完成线程安全。

  02根据redisson完成分布式锁

  咱们redis中有一个SETNXKEYVALUE,这个指令的时刻复杂度为O(1),只在键key不存在的情况下,将键key的值设置为value,若键key现已存在,则setnx指令不做任何操作,指令在设置成功时返回一,失利时分返回0.

  那么咱们能够简单用这个指令,完成一个十分简单的分布式锁。Springboot结构中咱们运用这个:

  stringRedisTemplate.opsForValue().setIfAbsent(),它底层是对setnx的封装。

  这样完成有什么问题?

  假如第一个线程抛了异常中断了,其它线程就永远不能处理了,所以咱们加上trycatch,finally。在finally里面delete咱们存的key值。

  假如程序宕机怎么办?不是可捕获异常怎么办?

  这时分程序履行到没有释放锁,即key值一向存在,在发动web服务的时分其它线程也一向不等待。这时分会一向存在死锁,咱们是不是参加锁的超时时刻是否能够,即
  stringRedisTemplate.expire()

  程序迭代的过程是逐步的优化,假定我还没来的及给锁设置时长,服务就宕掉了,这时分该怎么办。

  用两行指令履行咱们能够换成一行的指令,及设置key值的时分,一起设置时长,stringRedisTemplate.opsForValue().setIfAbsent()。合并成一个原子操作。

  这样写的化问题还是有的,假如你设置超时时刻为10秒,而我履行事务代码为小于10秒,还没履行完,就把锁释放掉了。高并发场景下你不能决议履行顺序.

  能够不能够自己加的锁,自己删去,别的线程不能进行操作?
  咱们给每个线程设置一个uuid,唯一id。这样轻轻松松解决了。
  商场上面现已有许多许多成熟的结构,咱们能够不需要去手写分布式结构来完成。

到此这篇关于浅谈Java分布式架构下如何实现分布式锁的文章就介绍到这了,更多相关Java分布式架构  分布式锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

蓄力AI

微信公众号搜索 “ 脚本之家 ” ,选择关注

程序猿的那些事、送书等活动等着你

原文链接:https://www.cnblogs.com/hite/p/13323434.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!

相关文章

  • SpringBoot结合Redis实现序列化的方法详解

    SpringBoot结合Redis实现序列化的方法详解

    Spring提供了一个RedisTemplate来进行对Redis的操作,但是RedisTemplate默认配置的是使用Java本机序列化。如果要对对象操作,就不是那么的方便。所以本文为大家介绍了另一种SpringBoot结合Redis实现序列化的方法,需要的可以参考一下
    2022-06-06
  • 一篇文章带你详解Spring的AOP

    一篇文章带你详解Spring的AOP

    这篇文章主要为大家介绍了Spring的AOP,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • Java按行读取文件文本内容的方式汇总

    Java按行读取文件文本内容的方式汇总

    在工作和学习中,有时候会有一些场景,代码需要配合读取文件来执行,比如:读文件数据,来进行计算、组装SQL、更新操作,本文给大家介绍在Java中按行读取文件文件内容的方式有哪些,感兴趣的朋友一起看看吧
    2023-10-10
  • 详解关于SpringBoot的外部化配置使用记录

    详解关于SpringBoot的外部化配置使用记录

    这篇文章主要介绍了详解关于SpringBoot的外部化配置使用记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Java中的CountDownLatch简单理解

    Java中的CountDownLatch简单理解

    这篇文章主要介绍了Java中的CountDownLatch简单理解,CountDownLatch是一个同步工具类,用来携调多个线程之间的同步,它是是使用一个计数器进行实现的,计数器初始值为线程数量,需要的朋友可以参考下
    2024-01-01
  • 关于Java中static关键字的用法

    关于Java中static关键字的用法

    这篇文章主要介绍了关于Java中static关键字的用法,static:意为静态的,在 Java 里面作为静态修饰符,可以理解为全局的意思,static 不仅可以修饰成员变量,成员方法,还可以修饰代码块,需要的朋友可以参考下
    2023-08-08
  • Java中如何实现不可变Map详解

    Java中如何实现不可变Map详解

    这篇文章主要给大家介绍了关于Java中如何实现不可变Map的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作工具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • java数据结构基础:线性表

    java数据结构基础:线性表

    这篇文章主要介绍了Java的数据解构基础,希望对广大的程序爱好者有所帮助,同时祝大家有一个好成绩,需要的朋友可以参考下,希望能给你带来帮助
    2021-07-07
  • SWT JFace 拖曳效果

    SWT JFace 拖曳效果

    SWT(JFace)体验之拖曳效果
    2009-06-06
  • 微信js-sdk+JAVA实现“分享到朋友圈”和“发送给朋友”功能详解

    微信js-sdk+JAVA实现“分享到朋友圈”和“发送给朋友”功能详解

    本文分享了微信js-sdk+JAVA实现“分享到朋友圈”和“发送给朋友”功能介绍,大家可以参考一下
    2018-03-03

最新评论