在使用分布式锁之前,要先思考一个问题,我们为什么要使用分布式锁?

这是因为,在分布式的部署环境下,原来的这个synchronized 只能在当前的JVM中加锁,不能跨JVM实现加锁,所以这种情况下我们就急需要使用分布式的锁来完成锁的功能。

分布式锁有很多种实现方式,基于zookeeper、基于数据库排他锁、基于缓存redis/memcache...

我们使用基于缓存的redis实现分布式锁。

public class TrainTickService {private Logger logger= LoggerFactory.getLogger(TrainTickService.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;//这个是锁对象@Autowiredprivate DistributeRedisLock distributeRedisLock;/*** 这个方法就是专门用来减售火车票的这样一个系统* 秒杀抢火车票** 30秒没有运行完 怎么办?*/public String produceStock(){String lock="lock";String value=UUID.randomUUID().toString();MyThread myThread=null;//设置个字符串try {// setnx命令//Boolean tag = stringRedisTemplate.opsForValue().setIfAbsent(lock, "");//给这个key设置过期时间//执行下面这一句话的时候突然死了?  是不是又出现死锁了//stringRedisTemplate.expire(lock,30,TimeUnit.SECONDS);//这个命令的底层实际上 也运行的是 咋们的命令  在底层他是怎样来实现原子性的呢?// 充分的利用了 redis和lua脚本  在C的层面上来实现原子性的a//setnx  只有这个可以不存在的时候 这个才会被删除Boolean tag=stringRedisTemplate.opsForValue().setIfAbsent(lock,value,30,TimeUnit.SECONDS);if (!tag) {//递归调用(让来的人中就要抢我们数据库中拥有的这个值)produceStock();return "目前排队人数过多...请稍后重试";}//超过了15//开一个守护线程myThread = new MyThread(lock);myThread.setDaemon(true);myThread.start();// 每隔设置时间的3分支1就进行线程的续命//一会初始值的时候我将火车票  放到redis中去//减去库存//去Redis中将库存数据给取出来int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("traintickes"));//首先要判断下 这个库存是否>0if (stock > 0) {  //说明可以减去库存int rStock = stock - 1;//下一步:将真实的库存放到咋们的Redis中去stringRedisTemplate.opsForValue().set("traintickes", String.valueOf(rStock));logger.info("扣减库存成功....剩余库存:" + rStock);} else {   //说明不能扣减库存logger.info("库存扣减失败、库存是负数、不足...");}  //已经用了15秒钟}finally {if(value.equals(stringRedisTemplate.opsForValue().get(lock))){//在这里要中断这个线程myThread.stop();stringRedisTemplate.delete(lock);logger.info("释放锁成功....");}}return "抢票成功....";}/*** 使用后台线程进行续命* 守护线程*    在主线程下 如果有一个守护线程  这个守护线程的生命周期 跟主线程是同生死的*/class MyThread extends Thread{String lock;public MyThread(String lock){this.lock=lock;}@Overridepublic void run() {while (true){//干这个事情、try{Thread.sleep(10000);}catch (Exception err){}//假设程序还活着  那么说明需要续命logger.info("续费中....");stringRedisTemplate.expire(lock,30,TimeUnit.SECONDS);}}}/*** 使用redisson来完成* @return*/public String produceStockRedisson(){String lock="lock";try {boolean lock1 = distributeRedisLock.lock(lock);if(true==lock1){//说明加锁成功int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("traintickes"));//首先要判断下 这个库存是否>0if (stock > 0) {  //说明可以减去库存int rStock = stock - 1;//下一步:将真实的库存放到咋们的Redis中去stringRedisTemplate.opsForValue().set("traintickes", String.valueOf(rStock));logger.info("扣减库存成功....剩余库存:" + rStock);} else {   //说明不能扣减库存logger.info("库存扣减失败、库存是负数、不足...");}  //已经用了15秒钟}else{return "当前的排队人数过多...";}}finally {distributeRedisLock.unlock(lock);}return "抢票成功....";}
}

Java基于Redis实现分布式锁(原子性操作、续命)——90%以上都搞错了相关推荐

  1. Java基于redis实现分布式锁(SpringBoot)

    前言 分布式锁,其实原理是就是多台机器,去争抢一个资源,谁争抢成功,那么谁就持有了这把锁,然后去执行后续的业务逻辑,执行完毕后,把锁释放掉. 可以通过多种途径实现分布式锁,例如利用数据库(mysql等 ...

  2. Java基于Redis的分布式锁

    分布式锁,其实最终还是要保证锁(数据)的一致性,说到数据一致性,基于ZK,ETCD数据一致性中间件做分数是锁,才是王道.但是Redis也能满足最基本的需求. 参考: https://www.cnblo ...

  3. nx set 怎么实现的原子性_基于Redis的分布式锁实现

    前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...

  4. 基于 Redis 实现分布式锁思考

    以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/xuan_lu/article/details/111600302 分布式锁 基于redis实 ...

  5. redis系列:基于redis的分布式锁

    一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...

  6. js 拉勾网效果_Node.js 中实践基于 Redis 的分布式锁实现

    在一些分布式环境下.多线程并发编程中,如果对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题. 作者简介:五月君,Nodejs Developer ...

  7. 基于Redis的分布式锁实现

    本文转自 一.分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问,Java中我们一般可以使用synchronized语法和ReetrantLock去保证,这实际上是本地锁的 ...

  8. 基于 Redis 的分布式锁到底安全吗?

    [完整版] 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现 ...

  9. php使用redis分布式锁,php基于redis的分布式锁实例详解

    在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现. 固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效 ...

最新文章

  1. pycharm没有python interpreter_首次安装Pycharm出现No Python interpreter selected解决方法
  2. pmc订单表格_复工了,读一则“如何提升订单准交率和生产效率”的真实故事
  3. 每天进步一点点《ML - 高斯混合模型》
  4. ashx获取input file 文件_前端战五渣学前端——FileReader预览本地文件
  5. linux内核killler,Linux 的 OOM Killer 机制分析
  6. 解决 mcrypt.h not found
  7. 台达b3伺服modbus通讯_台达ASDA-AB伺服与EVIEW触摸屏MODBUS通讯
  8. linux虚拟机读取本地磁盘文件,kvm虚拟化学习笔记(十三)之kvm虚拟机磁盘文件读取小结...
  9. datagrid表格序号列
  10. C++ Redis mset 二进制数据接口封装方案
  11. 徘徊过多少橱窗 住过多少旅馆 才会觉得分离也并不冤枉
  12. 魏巍专访丨合作半年拓客100+,他是如何做到的?
  13. CMake 常用方法
  14. 使用emitter的坑,
  15. python,给定任意列表lst和一个任意值item,返回item在lst中第一次出现的位置
  16. 单片机三角波c语言程序,三角波单独发生 单片机程序
  17. 详谈ByteArrayOutputStream的用法
  18. eclipse 无法启动
  19. 用JS代码自动填写正方教务系统的教学评价
  20. DQN(Deep Q Network)及其代码实现

热门文章

  1. U盘启动引导安装linux
  2. [mmdetection] 修改训练数据格式为“.png”
  3. 纽曼Q70 GPS导航仪安装.NET
  4. php 经纬度两点间距离公式,PHP根据两点间的经纬度计算距离,php两点经纬度计算...
  5. 有向无环图描述表达式(C语言)
  6. 14-四层, 七层与DNS负载均衡
  7. claude的 文字分类和总结很强,讯飞星火和chatgpt都没有这样回答
  8. MacBooster 6 for Mac v6.0.6 软件卸载系统清理 破解版下载
  9. JAVA泛型QUIK START
  10. Object wait方法