分布式锁 - 理论篇

news/2024/4/17 0:13:40

一、为什么需要分布式锁

在这里插入图片描述

二、分布式锁实现

1.分布式锁演进 - 基本原理
在这里插入图片描述

我们可以同时去一个地方“占坑”,如果占到,就执行逻辑。否则就必须等待,直到释放锁。“占坑”可以去redis,可以去数据库,可以去任何大家都能访问的地方等待可以自旋的方式
2.分布式锁演进

(1) 分布式锁演进 — 阶段一

在这里插入图片描述
代码如下:

public Map<String,List<Catelog2Vo>> getCatalogJsonFromDbwithRedisLock(){//1、占分布式锁。去redis占坑Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock""111");if(lock){//2、加锁成功... 执行业务Map<String,List<Catelog2Vo>> dataFromDb = getDataFromDb();//3、释放锁redisTemplate.delete( key: "lock");return dataFromDb}else {//加锁失败...重试。synchronized ()//休眠100ms重试//4.自旋的方式return getCatalogJsonFromDbwithRedisLock();}
}问题:如果第二步执行业务代码出异常或者机器断电等会导致第三步不能释放锁

(2)分布式锁演进 — 阶段二
在这里插入图片描述
代码如下:

public Map<String,List<Catelog2Vo>> getCatalogJsonFromDbwithRedisLock(){//1、占分布式锁。去redis占坑Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock""111");if(lock){//1.1、设置过期时间,这样写问题:没有和加锁是同步的,不是原子的redisTemplate.expire( key: "lock", timeout: 30,TimeUnit.SECONDS)//2、加锁成功... 执行业务Map<String,List<Catelog2Vo>> dataFromDb = getDataFromDb();//3、释放锁redisTemplate.delete( key: "lock");return dataFromDb}else {//加锁失败...重试。synchronized ()//休眠100ms重试//4.自旋的方式return getCatalogJsonFromDbwithRedisLock();}
}问题:如果1.1加过期时间时机器断电等会导致第三步不能释放锁redisTemplate.opsForValue.setIfAbsent( "lock", "1111",300,TimeUnit.SECONDS):

(3)分布式锁演进 — 阶段三
在这里插入图片描述
代码如下:

public Map<String,List<Catelog2Vo>> getCatalogJsonFromDbwithRedisLock(){//1、占分布式锁。去redis占坑Boolean lock = redisTemplate.opsForValue.setIfAbsent( "lock", "1111",300,TimeUnit.SECONDS);if(lock){//2、加锁成功... 执行业务Map<String,List<Catelog2Vo>> dataFromDb = getDataFromDb();//3、释放锁redisTemplate.delete( key: "lock");return dataFromDb;}else {//加锁失败...重试。synchronized ()//休眠100ms重试//4.自旋的方式return getCatalogJsonFromDbwithRedisLock();}
}问题:释放锁失败会导致死锁

(4)分布式锁演进 — 阶段四 可在具体项目中使封装使用下面代码,但是建议使用专门的框架
在这里插入图片描述
使用 RedisTemplate 操作分布式锁

    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 {//2.加锁成功...执行业务dataFromDb = getDataFromDb();} finally {//3.删除锁  lua脚本解锁String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) " +"else return 0 end";stringRedisTemplate.execute(new DefaultRedisScript<>(script,Long.class), Arrays.asList("lock"), uuid);//下面不能这样写  // 先去redis查询下保证当前的锁是自己的//获取值对比,对比成功删除=原子性 // String lockValue = stringRedisTemplate.opsForValue().get("lock");// if (uuid.equals(lockValue)) {//     //删除我自己的锁//     stringRedisTemplate.delete("lock");// }}return dataFromDb;} else {System.out.println("获取分布式锁失败...等待重试...");//4. 加锁失败...重试机制,要根据具体业务决定下面需不需要写//休眠一百毫秒try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }return getCatalogJsonFromDbWithRedisLock();     //自旋的方式}}

http://www.ppmy.cn/news/1170095.html

相关文章

YOLOv7-PTQ量化部署

目录 前言一、PTQ量化浅析二、YOLOv7模型训练1. 项目的克隆和必要的环境依赖1.1 项目的克隆1.2 项目代码结构整体介绍1.3 环境安装 2. 数据集和预训练权重的准备2.1 数据集2.2 预训练权重准备 3. 训练模型3.1 修改模型配置文件3.2 修改数据配置文件3.3 训练模型3.4 mAP测试 三、…

LoadRunner录制脚本+编写脚本

LoadRunner安装* 为什么选择LoadRunner 1&#xff09;Jmeter没有录制功能 2&#xff09;可以设计非常非常丰富的测试场景 3&#xff09;LoadRunner能够产出非常丰富的测试报告 LoadRunner三大组件的关系 每个组件是干什么的 VUG&#xff1a;录制脚本&#xff0c;&#xff…

Matlab/C++源码实现RGB通道与HSV通道的转换(效果对比Halcon)

HSV通道的含义 HSV通道是指图像处理中的一种颜色模型&#xff0c;它由色调&#xff08;Hue&#xff09;、饱和度&#xff08;Saturation&#xff09;和明度&#xff08;Value&#xff09;三个通道组成。色调表示颜色的种类&#xff0c;饱和度表示颜色的纯度或鲜艳程度&#xf…

百度松果20231022作业

越狱 盒子与球 斯特林第二类数&#xff08;用dp求&#xff09;*盒子的阶乘 int dp[11][11]; //n>k int A(int x){int res1;fer(i,2,x1)res*i;return res; } signed main(){IOS;dp[2][1]dp[2][2]dp[1][1]1;fer(i,3,11){dp[i][1]1;fer(j,2,i){dp[i][j]j*dp[i-1][j]dp[i-1][j-…

python 均值滤波

网上公开的均值滤波方法不能较好地对两端进行滤波(有边际效应&#xff0c;或者序列长度缩短)&#xff0c;于是自己写了一个可以对两端也进行滤波的函数 def meanfilt(x, N):x_pad np.r_[np.zeros(N-1), x]denominator np.r_[np.arange(1, N1), np.ones(len(x)-N)*N]win_sum …

详解使用sklearn实现一元线性回归和多元线性回归

[Open In Colab] 文章目录 1. 线性回归简介2. 使用sklearn进行一元线性回归3. 线性回归的coef_参数和intercept_参数4. 使用sklearn实现多元线性回归4.1 利用PolynomialFeatures构造输入4.2 进行多元线性回归 5. 总结 import numpy as np import matplotlib.pyplot as plt1. 线…

Java基础(第一期):IDEA的下载和安装(步骤图) 项目结构的介绍 项目、模块、类的创建。第一个代码的实现

文章目录 IDEA1.1 IDEA概述1.2 IDEA的下载和安装1.2.1 下载1.2.2 安装 1.3 IDEA中层级结构介绍1.3.1 结构分类1.3.2 结构介绍project&#xff08;项目、工程&#xff09;module&#xff08;模块&#xff09;package&#xff08;包&#xff09;class&#xff08;类&#xff09; …

靶机 DC-2

DC_2 信息搜集 存活检测 详细扫描 添加 host 后台网页扫描 网页信息搜集 主页面 找到 flag1&#xff0c;提示使用 cewl 密码生成工具 wp 登陆界面 使用 wpscan 扫描用户 wpscan --url http://dc-2/ --enumerate u 扫描出用户 tom、jerry、admin 将三个用户名写入文件中…

一文带你彻底弄懂ZGC

1 推荐的文章 1.1 必看 干掉1ms以内的Java垃圾收集器ZGC到底是个什么东西&#xff1f; 1.2 选看 ZGC有什么缺点? 2 疑问【皆来自上面两篇文章】 2.1 什么使得用户线程工作的同时&#xff0c;让垃圾收集器可以回收垃圾-读写屏障 ZGC (Z Garbage Collector) 和读写屏障: …

灵性·挖掘 3:自我迭代之路

灵性挖掘 3&#xff1a;自我迭代之路 你的观众只有一个&#xff0c;就是你自己不谈感受&#xff0c;只谈行动式感受熬竞争对手用力过猛会反杀自己。进入这种状态是无我的状态。 你的观众只有一个&#xff0c;就是你自己 我活着到底是为了干啥呢&#xff1f; 我吃喝玩乐好像也…

C#/.NET/.NET Core推荐学习书籍

前言 作为一名程序员&#xff0c;我们无时无刻都要考虑着如何通过不断地学习来提升自己的核心竞争力。古人有云&#xff1a;“书中自有黄金屋&#xff0c;书中只有颜如玉”&#xff0c;说明了书籍的重要性&#xff0c;没错工作多年来&#xff0c;发现身边那些优秀的同事、大佬都…

【Java基础面试三十九】、 finally是无条件执行的吗?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; finally是无条件执行的…

Redis --- 安装教程

Redis--- 特性&#xff0c;使用场景&#xff0c;安装 安装教程在Ubuntu下安装在Centos7.6下安装Redis5 特性在内存中存储数据可编程的扩展能力持久化集群高可用快速 应用场景实时数据存储作为缓存或者Session存储消息队列 安装教程 &#x1f680;安装之前切换到root用户。 在…

敏捷是怎么提高工作效率的

敏捷管理是一门极力减少不必要工作量的艺术。 谷歌、亚马逊、苹果、微信、京东等全球 500 强企业都在用的管理方法&#xff0c;适用于各行各业&#xff0c;被盛赞为应获“管理学的诺贝尔奖”。 它专注于让员工不受种种杂事的羁绊&#xff0c;激发个体斗志&#xff0c;释放出巨大…

基于SSM的社区物业管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

GRASP 、SOLID 与 GoF 设计模式

一、GRASP GRASP&#xff1a;通用职责分配软件设计模式(General Responsibility Assignment Software Patterns)&#xff0c;其主要思想是基于单一职责设计软件对象。 思考软件对象设计以及大型构件的流行方式是&#xff0c;考虑其职责、角色和协作。这是被称为职责驱动设计&a…

商家收款码手续费太高了

在竞争激烈、各行各业都如此内卷的当下&#xff0c;商家需要不断寻求提高利润的方法。所谓开源节流&#xff0c;既要学会提高利润率&#xff0c;也要学会节省成本&#xff0c;毕竟钱是挣出来的&#xff0c;同时也是省出来的。作为一个经常使用收款工具的商家&#xff0c;很多人…

Qt窗体设计的布局

本文介绍Qt窗体的布局。 Qt窗体的布局分为手动布局和自动布局&#xff0c;手动布局即靠手工排布各控件的位置。而自动布局则是根据选择的布局类型自动按此类型排布各控件的位置&#xff0c;使用起来比较方便&#xff0c;本文主要介绍Qt的自动布局。 1.垂直布局 垂直布局就是…

ant design vue Message 用法以及内容为 html片段情况

ant design vue 的 Message 用法 全局展示操作反馈信息 何时使用 # 可提供成功、警告和错误等反馈信息。顶部居中显示并自动消失&#xff0c;是一种不打断用户操作的轻量级提示方式。 全局配置&#xff1a; // main.ts// 进行全局配置 message.config({top: 0.7rem,//高度…

【Java基础面试三十八】、请介绍Java的异常接口

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;请介绍Java的异常接口 …
最新文章