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

所属分类: 软件编程 / java 阅读数: 104
收藏 0 赞 0 分享

  01分布式锁运用场景

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

 @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。这样轻轻松松解决了。
  商场上面现已有许多许多成熟的结构,咱们能够不需要去手写分布式结构来完成。

更多精彩内容其他人还在看

JavaWeb项目部署到服务器详细步骤详解

这篇文章主要介绍了JavaWeb项目如何部署到服务器,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

IDEA基于支付宝小程序搭建springboot项目的详细步骤

这篇文章主要介绍了IDEA基于支付宝小程序搭建springboot项目的详细步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解SpringBoot应用服务启动与安全终止

这篇文章主要介绍了SpringBoot应用服务启动与安全终止,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring Boot启动及退出加载项的方法

这篇文章主要介绍了Spring Boot启动及退出加载项的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring Data Jpa 自动生成表结构的方法示例

这篇文章主要介绍了Spring Data Jpa 自动生成表结构的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

IDEA中osgi的开发应用指南详解

这篇文章主要介绍了IDEA中osgi的开发应用指南详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解用maven将dubbo工程打成jar包运行

这篇文章主要介绍了详解用maven将dubbo工程打成jar包运行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

详解Java合并数组的两种实现方式

这篇文章主要介绍了Java合并数组的两种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

使用Jenkins Pipeline自动化构建发布Java项目的方法

这篇文章主要介绍了使用Jenkins Pipeline自动化构建发布Java项目的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

使用Maven配置Spring的方法步骤

这篇文章主要介绍了使用Maven配置Spring的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享
查看更多