缓存-分布式锁-分布式锁原理与使用
怎么来实现这个分布式锁呢?
方案一:
这种设计方案,会出现一个问题:当线程获取到锁,然后执行完业务逻辑,准备去删除锁的时候,突然服务器宕机了,会导致这个锁一直存在,得不到释放,会造成死锁的情况。
解决方案就是:设置一个过期时间,即使服务器宕机不能手动释放,也可以过期自动释放
方案二:
解决了方案一的问题,不过,还会有问题,假如当我们获取到锁之后将要去设置过期时间的时候,这时候服务器宕机了,也会造成死锁情况。
解决方案:保证获取锁和设置过期时间是原子性的,setnx ex命令可以保证原子性
方案三:
这种方案解决了设置锁的原子性,但是在删除锁的时候,是应该直接删除的吗?当我们的业务执行时间很长的时候,这时候假定锁已经过期了,别的线程获得了锁,先前线程执行完业务之后,去删除锁,就会去删除别人的锁
解决方案:在设置锁的时候指定自己的UUID,执行完业务后,获取锁检查是否是自己之前设置的,如果是自己设置的,就删除,否则就跳过,在删除锁的时候也要保证原子性,为什么呢?假如我们获取到这个锁的确是我们自己之前设置的,但是在获取值到删除锁中间还是有一段时间,假如这段时间,锁失效了,别人获取到了锁,这时候我们还是会认为锁是自己的,会导致误删。
方案四:
手动如何实现分布式锁
实现分布式锁的前提一定要保证在获取到锁+过期时间、获取锁+删除锁这两步操作都是原子操作。
上图就是我解决方案的流程图。接下来就看看我代码是怎么实现的吧。
/*** 从数据库查询并封装数据::分布式锁* @return*/
public Map<String, List<Catelog2Vo>> getCatalogJsonFromDbWithRedisLock() {//1、占分布式锁。去redis占坑 设置过期时间必须和加锁是同步的,保证原子性(避免死锁)String uuid = UUID.randomUUID().toString();Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS);if (lock) {System.out.println("获取分布式锁成功...");Map<String, List<Catelog2Vo>> dataFromDb = null;try {//加锁成功...执行业务(只允许获取到分布式锁的线程去数据库中查)dataFromDb = getDataFromDb();} finally {// Lua脚本,在脚本中有两步操作:一、获取当前这个分布式锁,判断这个分布式锁是不是我的,二、如果是我的就删除,并返回1,否则返回0String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";//删除锁stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);}//先去redis查询下保证当前的锁是自己的//获取值对比,对比成功删除=原子性 lua脚本解锁// String lockValue = stringRedisTemplate.opsForValue().get("lock");// if (uuid.equals(lockValue)) {// //删除我自己的锁// stringRedisTemplate.delete("lock");// }return dataFromDb;} else {System.out.println("获取分布式锁失败...等待重试...");//加锁失败...重试机制//休眠一百毫秒try {TimeUnit.MILLISECONDS.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}return getCatalogJsonFromDbWithRedisLock(); //自旋的方式}
}
缓存-分布式锁-分布式锁原理与使用相关推荐
- 快来学习Redis 分布式锁的背后原理
以前在学校做小项目的时候,用到Redis,基本也只是用来当作缓存.可阿粉在工作中发现,Redis在生产中并不只是当作缓存这么简单.在阿粉接触到的项目中,Redis起到了一个分布式锁的作用,具体情况是这 ...
- 还不知道 Redis 分布式锁的背后原理?还不赶快学习一下
前言 以前在学校做小项目的时候,用到Redis,基本也只是用来当作缓存.可阿粉在工作中发现,Redis在生产中并不只是当作缓存这么简单.在阿粉接触到的项目中,Redis起到了一个分布式锁的作用,具体情 ...
- 【网课平台】Day16.项目优化:压测、加缓存优化与分布式锁
文章目录 一.压力测试 1.优化需求 2.性能指标 3.安装Jmeter 4.压力测试 5.优化日志 二.缓存优化 1.给接口加Redis缓存 2.缓存穿透 3.解决缓存穿透 4.缓存雪崩 5.缓存击 ...
- Redis分布式锁背后的原理
什么是分布式锁? 分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性. 分布式锁需要具 ...
- Day137-139.尚品汇:制作SKU、商品详情、项目优化:Redis缓存、redssion分布式锁
目录 Day5 制作SKU 1. 制作SKU 2. 多表查询如何写? 3. 制作SKU 4. Thymeleaf Day06 商品详情 1. 获取分类信息 2. 获取最新价格信息 3. 获取销售信息 ...
- 电商项目实战之缓存与Redis分布式锁
电商项目实战之缓存与Redis分布式锁 缓存失效 缓存穿透 缓存雪崩 缓存击穿 分布式缓存 分布式锁 SpringBoot整合Redisson实现分布式锁 实现过程 缓存和数据库一致性 场景分析 解决 ...
- Redis分布式锁的实现原理
目前基于Redis实现的分布式锁常用的框架是Redisson,它的使用比较简单,在项目中引入Redisson的依赖,然后基于Redis实现分布式锁的加锁与释放锁. Redis分布式锁的底层原理 R ...
- Redis分布式锁的实现原理看这篇就够了~
2019独角兽企业重金招聘Python工程师标准>>> 一.写在前面 现在面试,一般都会聊聊分布式系统这块的东西.通常面试官都会从服务框架(Spring Cloud.Dubbo)聊起 ...
- zookeeper-常用命令,集成springboot,分布式锁实现和原理 ,dock集群zookeeper搭建,
(一)zookeeper数据模型 树形结构 每个节点里面保存信息 节点拥有子节点 节点是临时的也可以是持久的 四大节点 PERSISTENT-持久化目录节点 客户端与zookeeper断开连接后,该节 ...
最新文章
- 【Python】青少年蓝桥杯_每日一题_6.27_输出符合要求的10个自然数
- linux内核杂记(13)-系统调用(1)
- SAP物料主数据创建时间和创建个数的函数关系
- 大型网站的架构设计问题—-大型高并发高负载网站的系
- UE3 Lightmass 技术指南
- Windows Server 2016-批量设置用户下次登陆须更改密码
- 简易博客编辑器:玩转document.execCommand命令
- 数据处理——数据编码
- mysql父子节点分层_mysql 递归实例 父子节点层级递归
- Himall商城枚举帮助类EnumHelper(3)
- 四线电阻式触摸屏原理
- 29、程序员的面试考题,要求用一个for循环打出乘法表。
- 三进制计算机_三进制会取代二进制计算机吗?
- 与dalao学校的联shou考wan(11.2)(dp+乱搞+树形dp+期望)
- 的脑袋里有台超级计算机,我的脑袋里有台超级计算机
- 产品销售份额数据统计流程图模板分享
- PythonStock(29)股票系统:涛动周期论 经济周期决定人生财富命运,下一步的研究方向,从宏观角度进行市场行情研究。
- html .html后缀的网页百度收录吗,百度收录动态页面吗
- 最新kali之sslyze
- (4.1.36.1)Graphics图形学解析补充篇:路径Path