Redis中是如何实现分布式锁的?
分布式锁常见的三种实现方式:
-
数据库乐观锁;
-
基于Redis的分布式锁;
-
基于ZooKeeper的分布式锁。
本次面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。
要点
Redis要实现分布式锁,以下条件应该得到满足
互斥性
-
在任意时刻,只有一个客户端能持有锁。
不能死锁
-
客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
容错性
-
只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
实现
可以直接通过 set key value px milliseconds nx 命令实现加锁, 通过Lua脚本实现解锁。
//获取锁(unique_value可以是UUID等)
SET resource_name unique_value NX PX 30000
//释放锁(lua脚本中,一定要比较value,防止误解锁)
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
代码解释
-
set 命令要用
set key value px milliseconds nx,替代setnx + expire需要分两次执行命令的方式,保证了原子性, -
value 要具有唯一性,可以使用
UUID.randomUUID().toString()方法生成,用来标识这把锁是属于哪个请求加的,在解锁的时候就可以有依据; -
释放锁时要验证 value 值,防止误解锁;
-
通过 Lua 脚本来避免 Check And Set 模型的并发问题,因为在释放锁的时候因为涉及到多个Redis操作 (利用了eval命令执行Lua脚本的原子性);
加锁代码分析
首先,set()加入了NX参数,可以保证如果已有key存在,则函数不会调用成功,也就是只有一个客户端能持有锁,满足互斥性。其次,由于我们对锁设置了过期时间,即使锁的持有者后续发生崩溃而没有解锁,锁也会因为到了过期时间而自动解锁(即key被删除),不会发生死锁。最后,因为我们将value赋值为requestId,用来标识这把锁是属于哪个请求加的,那么在客户端在解锁的时候就可以进行校验是否是同一个客户端。
解锁代码分析
将Lua代码传到jedis.eval()方法里,并使参数KEYS[1]赋值为lockKey,ARGV[1]赋值为requestId。在执行的时候,首先会获取锁对应的value值,检查是否与requestId相等,如果相等则解锁(删除key)。
存在的风险
如果存储锁对应key的那个节点挂了的话,就可能存在丢失锁的风险,导致出现多个客户端持有锁的情况,这样就不能实现资源的独享了。
-
客户端A从master获取到锁
-
在master将锁同步到slave之前,master宕掉了(Redis的主从同步通常是异步的)。主从切换,slave节点被晋级为master节点
-
客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。导致存在同一时刻存不止一个线程获取到锁的情况。
redlock算法出现
这个场景是假设有一个 redis cluster,有 5 个 redis master 实例。然后执行如下步骤获取一把锁:
-
获取当前时间戳,单位是毫秒;
-
跟上面类似,轮流尝试在每个 master 节点上创建锁,过期时间较短,一般就几十毫秒;
-
尝试在大多数节点上建立一个锁,比如 5 个节点就要求是 3 个节点 n / 2 + 1;
-
客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了;
-
要是锁建立失败了,那么就依次之前建立过的锁删除;
-
只要别人建立了一把分布式锁,你就得不断轮询去尝试获取锁。
Redis 官方给出了以上两种基于 Redis 实现分布式锁的方法,详细说明可以查看:
https://redis.io/topics/distlock 。
Redisson实现
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还实现了可重入锁(Reentrant Lock)、公平锁(Fair Lock、联锁(MultiLock)、 红锁(RedLock)、 读写锁(ReadWriteLock)等,还提供了许多分布式服务。
Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。
Redisson 分布式重入锁用法
Redisson 支持单点模式、主从模式、哨兵模式、集群模式,这里以单点模式为例:
// 1.构造redisson实现分布式锁必要的Config
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:5379").setPassword("123456").setDatabase(0);
// 2.构造RedissonClient
RedissonClient redissonClient = Redisson.create(config);
// 3.获取锁对象实例(无法保证是按线程的顺序获取到)
RLock rLock = redissonClient.getLock(lockKey);
try {
/**
* 4.尝试获取锁
* waitTimeout 尝试获取锁的最大等待时间,超过这个值,则认为获取锁失败
* leaseTime 锁的持有时间,超过这个时间锁会自动失效(值应设置为大于业务处理的时间,确保在锁有效期内业务能处理完)
*/
boolean res = rLock.tryLock((long)waitTimeout, (long)leaseTime, TimeUnit.SECONDS);
if (res) {
//成功获得锁,在这里处理业务
}
} catch (Exception e) {
throw new RuntimeException("aquire lock fail");
}finally{
//无论如何, 最后都要解锁
rLock.unlock();
}
加锁流程图
解锁流程图
我们可以看到,RedissonLock是可重入的,并且考虑了失败重试,可以设置锁的最大等待时间, 在实现上也做了一些优化,减少了无效的锁申请,提升了资源的利用率。
需要特别注意的是,RedissonLock 同样没有解决 节点挂掉的时候,存在丢失锁的风险的问题。而现实情况是有一些场景无法容忍的,所以 Redisson 提供了实现了redlock算法的 RedissonRedLock,RedissonRedLock 真正解决了单点失败的问题,代价是需要额外的为 RedissonRedLock 搭建Redis环境。
所以,如果业务场景可以容忍这种小概率的错误,则推荐使用 RedissonLock, 如果无法容忍,则推荐使用 RedissonRedLock。
参考
https://github.com/javazhiyin/advanced-java/ https://crazyfzw.github.io/2019/04/15/distributed-locks-with-redis/
顶尖架构师栈
关注回复关键字
【C01】超10G后端学习面试资源
【IDEA】最新IDEA激活工具和码及教程
【JetBrains软件名】 最新软件激活工具和码及教程
工具&码&教程
转载于:https://mp.weixin.qq.com/s/ELc_9k3QwEHdse_yFatDPw
本文由 mdnice 多平台发布
相关文章:
Redis中是如何实现分布式锁的?
分布式锁常见的三种实现方式: 数据库乐观锁; 基于Redis的分布式锁; 基于ZooKeeper的分布式锁。 本次面试考点是,你对Redis使用熟悉吗?Redis中是如何实现分布式锁的。 要点 Redis要实现分布式锁,以下条件应…...
似然和概率
前言 高斯在处理正态分布的首次提出似然,后来英国物理学家,费歇尔 概率是抛硬币之前,根据环境推断概率 似然则相反,根据结果推论环境 P是关于x的函数,比如x为正面朝上的结果,或者反面朝上的结果…...
php代码审计篇熊海cms代码审计
文章目录 自动审计逐个分析首页index.php文件包含漏洞后台逻辑漏洞cookie绕过登录后台sql报错注入存储型XSS 结束吧 自动审计 看到有很多 逐个分析 首页index.php文件包含漏洞 读一下代码,可以看到很明显的一个文件包含 <?php //单一入口模式 error_repor…...
Android Camera2获取摄像头的视场角(FOV)信息
一、概念 FOV(Field of View)是一个用于描述视野范围的术语。它通常用于计算设备(如摄像机、虚拟现实头显或眼睛)所能捕捉到的可见区域。 水平FOV(Horizontal FOV):描述视野在水平方向上的范围…...
服务接口调用OpenFeign_日志增强
OpenFeign虽然提供了日志增强功能,但是默认是不显示任何日志的,不过开发者在调试阶段可以自己配置日志的级别。 OpenFeign的日志级别如下: NONE:默认的,不显示任何日志;BASIC:仅记录请求方法、URL、响应状…...
ADC数模转化器
简介 • ADC ( Analog-Digital Converter )模拟 - 数字转换器 • ADC 可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁 • 12 位逐次逼近型 ADC , 1us 转换时间 (12位:分辨率…...
Linux DataEase数据可视化分析工具结合cpolar实现远程访问
文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务…...
使用JAXB将xml转成Java对象
文章目录 使用JAXB将xml转成Java对象1. xml内容2. Java对象类3. 封装的工具类4. 测试 使用JAXB将xml转成Java对象 工作中遇到个问题,需要将xml转对象,之前复杂的xml都是自己用dom4j来解析组装成Java对象,但是对于简单的,看到了JAX…...
第6讲:v-for使用
目录 1.循环遍历 2.v-for遍历整形变量(99乘法表) 3.v-for遍历普通数组 4.v-for遍历数组对象 1.循环遍历 v-for指令基于一个数组渲染一个列表,它和JavaScript的遍历语法相似: v-for”item in list” list 是一个数组, i…...
ubuntu http 服务器响应
代码: h文件 #include <iostream> #include <curl/curl.h>#include <net/if.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <string.h>#include <event.h> #include <event2/http.h> #include <…...
C语言 结构体位域
在C语言中,结构体位域是一种特殊的结构体成员,它允许在结构体中定义一个二进制位字段,以便在单个字节中存储多个布尔值或枚举值。 结构体位域的定义方式如下: struct { unsigned int bit1: 1; // 定义一个名为bit1的位域&…...
ChatGPT AIGC 非常实用的AI工具集合大全
实战AI 工具箱 AIGC ChatGPT 职场案例60集, Power BI 商业智能 68集, 数据库Mysql8.0 54集 数据库Oracle21C 142集, Office, Python ,ETL Excel 2021 实操,函数,图表,大屏可视化 案例实战 http://t.csdn.cn/zBytu...
Visual Studio Cpp CLR C# 替换
1、首先将文件中所有都替换 你需要的名字 替换为整个解决方案 2、新建工程取名 Laserbeam_upper 3、把原工程下的cpp放进来,并改名Laserbeam_upper 4、在这里逐步添加 属性表配置opencv 5、cpp需要修改的两个地方 6、CLR新建和添加 选类库新建、然后直接粘贴进来…...
typeorm利用mongodb,save的时候更新会出现重复数据的问题。
是因为mongodb把new Object当成插入的数据了,修正方案 ObjectIdColumn({name: _id,})Transform((value) > new ObjectId(value.obj._id.toString()))// ts-ignore_id: ObjectId;Transform((value) > new ObjectId(value.obj._id.toString()))转换下就好了。...
决策树案例分析
决策树(Decision Tree)常用于研究类别归属和预测关系的模型,比如是否抽烟、是否喝酒、年龄、体重等4项个人特征可能会影响到‘是否患癌症’,上述4项个人特征称作‘特征’,也即自变量(影响因素X),‘是否患癌…...
Linux基本操作符(1)
W...Y的主页 😊 代码仓库分享 💕 目录 Linux的登录 Linux下基本指令 指令操作的理解 几个与用户操作符 ls 指令 pwd命令 cd 指令 touch指令 mkdir指令 rmdir指令 && rm 指令 什么叫操作系统,我相信如果是学计算机的都听说过&…...
pg数据表同步到hive表数据压缩总结
1、背景 pg库存放了大量的历史数据,pg的存储方式比较耗磁盘空间,pg的备份方式,通过pgdump导出后,进行gzip压缩,压缩比大概1/10,随着数据的积累磁盘空间告警。为了解决pg的压力,尝试采用hive数据…...
2023-Chrome插件推荐
Chrome插件推荐 一键管理扩展 链接 https://chromewebstore.google.com/detail/lboblnfejcmcaplhnbkkfcienhlhpnni 介绍 一键开启、禁用Chrome插件。 Checker Plus for Gmail™ 链接 https://jasonsavard.com/zh-CN/Checker-Plus-for-Gmail https://chromewebstore.goo…...
VUE使用DXFParser组件解析dxf文件生成图片
<template><div><input type"file" change"handleFileChange" /></div><el-table :data"tableData" style"width: 100%"><el-table-column prop"Control_No" label"序号" width…...
SpringBoot 集成 AKKA
文章目录 应用场景与 SpringBoot 集成示例 应用场景 AKKA 是一个用于构建高并发、分布式和容错应用程序的开源框架。它基于Actor模型,提供了强大的并发抽象和工具,适用于各种业务场景。以下是一些使用AKKA框架的常见业务场景的示例: 实时数据…...
OpenClaw多模态实践:Qwen3.5-9B-VL图文报告自动生成
OpenClaw多模态实践:Qwen3.5-9B-VL图文报告自动生成 1. 为什么需要多模态自动化 去年整理学术文献时,我每天要手动截取论文图表、复制关键数据、整理成Markdown笔记。这个过程不仅耗时,还经常漏掉重要细节。直到发现OpenClaw可以对接Qwen3.…...
实战指南:基于同一份OpenSpec,用快马平台同步生成前后端代码,确保联调无忧
最近在开发一个电商平台时,我们团队遇到了前后端联调效率低下的问题。由于接口文档和实际代码存在差异,经常出现前端调用参数和后端接收不一致的情况。后来我们发现,基于OpenSpec规范同步生成前后端代码可以完美解决这个问题,这里…...
AtCoder Beginner Contest 429
【赛时五题】AtCoder Beginner Contest 429 https://www.bilibili.com/video/BV1gXsZz8ELL/ 【赛时6题】AtCoder Beginner Contest 429 https://www.bilibili.com/video/BV1gXsZz8EZQ/ Atcoder Beginner Contest 429 https://www.bilibili.com/video/BV1SosZzdENX/ https://blo…...
F5 big IP DNS 导出cname txt记录
DNS上的A记录配置与cname不在同一文件中 cname和txt这一类的在下面这个目录 /var/named/config/namedb可以通过winscp连接DNS后,找到这个目录,里面的所有文件即是,之所以有多个文件,是因为每1个权威域都对应1个独立文件...
Bypass Paywalls Clean:智能内容解锁工具的终极使用指南
Bypass Paywalls Clean:智能内容解锁工具的终极使用指南 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 在数字化信息时代,学术研究者、新闻从业者和知识工作者…...
新手入门:在快马平台动手实现你的第一个ui-ux-pro-max设计页面
作为一个刚接触前端设计的新手,最近在InsCode(快马)平台尝试做了一个UI-UX-Pro-Max级别的登录注册页面,整个过程意外地顺利。这里记录下我的实践过程,希望能帮到同样想入门的朋友。 从零搭建页面框架 先用HTML搭建基础结构,包含表…...
COMSOL激光打孔形貌优化:不同入射角设置方法与模型注释解析
COMSOL 不同激光入射角打孔形貌设置方法 模型内容:不同激光入射角度的设置 优势:视频教学和模型注释清晰明了,各个情况都有涉及可参考性极强,可以修改,收敛性已调至最优,本案例可进行拓展应用服务ÿ…...
用快马AI一键生成数据库管理原型,告别navicat手工建表写接口
用快马AI一键生成数据库管理原型,告别navicat手工建表写接口 最近在开发一个员工信息管理系统时,我深刻体会到传统数据库管理工具的局限性。虽然navicat这类工具能帮我们可视化操作数据库,但每次新建项目都要手动建表、写接口,重…...
投资分析太复杂?用TradingAgents-CN实现零代码智能分析的3个方案
投资分析太复杂?用TradingAgents-CN实现零代码智能分析的3个方案 【免费下载链接】TradingAgents-CN 基于多智能体LLM的中文金融交易框架 - TradingAgents中文增强版 项目地址: https://gitcode.com/GitHub_Trending/tr/TradingAgents-CN TradingAgents-CN作…...
AI集成开发工程师的技术实践与转型之路
第一章:技术架构演进与AI融合趋势 1.1 传统开发范式的演进 现代软件开发正经历从单一业务系统向智能化业务系统的转型。传统的.NET技术栈作为企业级应用开发的基石,其技术架构也在不断演进: // 典型的三层架构示例 public class BusinessLogic {private readonly IDataAc…...
