基于redis的分布式锁解析
在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现。
固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效率高。
redis锁失效的情况:
- 客户端1从master节点获取了锁
- master宕机了,存储锁的key还没来得及同步到slave节点上
- slave升级为master
- 客户端2从新的master上获取到同一个资源的锁
于是,客户端1和客户端2同事持有了同一个资源的锁,锁的安全性被打破。
如果我们不考虑这种极端情况,需要实现一个基于单节点redis锁的大致流程:
set cache_key random_seed NX PX 30000
上面这个set命令拆解开就是:
setnx cache_key random_seed
expire cache_key 30
虽然这两组命令执行的效果一样,但是第二个是非原子性操作,如果执行了setnx成功,但是expire失败的话,就会造成这个key一直存在了,无法释放的情况。
redis的作者也指出,在使用单节点redis锁的时候,设置一个随机种子作为key的值是很有必要的,保证了一个客户端释放的锁必须是自己所持有的那个锁。假设获取锁时set的不是一个随机数,而是一个固定值,那么可能会出现下面的情况:
- 客户端1获取锁成功
- 客户端1在某个操作上阻塞了很长时间
- 过期时间到了,锁自动释放(但是在客户端1看来自己还是持有锁中)
- 客户端2获取到了对应同一个资源的锁
- 客户端1从阻塞中恢复了,释放掉自己持有的锁,也就是释放掉了客户端2持有的锁
客户端2的锁被客户端1是否,失去安全性。
释放锁的操作,很多人直接用del命令,这会有很大的问题,保证不了这个key是被加锁人锁删。这时候需要用到随机数了。释放锁的操作有三步:
- get 所持有锁
- 判断这个锁是否自己所持有
- 删除持有锁
所以,这三步要保证原子性。用lua脚本来执行,redis官方已经提供脚本文件。
if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end
这段脚本在执行的时候,需要把前面的随机数作为argv[1] 的值传进去,把cache_key作为keys[1]的值传进去。
public class RedisLockHelper {@Resourceprivate R2mClusterClient r2mClusterClient;/*** 类似于setNx的功能,同时设置过期时间为expire毫秒** @param key 加锁key* @param value 确保在加锁时间内的唯一因子* @param expire 过期时间的毫秒数* @return*/private String setLock(String key, String value, long expire) {return this.set(key, value, "NX", "PX", expire);}/*** 删除指定key value* 如果 r2m中 key 对应的value==value 返回 1* 如果 r2m中 key 对应的value!=value 返回 0** @param key* @return*/private boolean atomDelete(String key, String value) {List<String> values = new ArrayList<>();values.add(value);String sb = "if redis.call('get',KEYS[1])==ARGV[1] then " +" return redis.call('del',KEYS[1]) " +" else " +" return 0" +" end";if (this.eval(sb, key, values) == 1) {return true;}return false;}private Long eval(String mobel, String key, List<String> value) {return (Long) this.r2mClusterClient.eval(mobel, key, value);}private String set(String key, String value, String nxxx, String expx, long time) {return this.r2mClusterClient.set(key, value, nxxx, expx, time);}
}
r2mClusterClient 就是jedis客户端的封装。
基于redis的分布式锁解析相关推荐
- 基于 Redis 实现分布式锁思考
以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/xuan_lu/article/details/111600302 分布式锁 基于redis实 ...
- nx set 怎么实现的原子性_基于Redis的分布式锁实现
前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...
- 基于Redis的分布式锁和Redlock算法
来自:后端技术指南针 1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手 ...
- redis系列:基于redis的分布式锁
一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...
- 基于 Redis 的分布式锁到底安全吗?
[完整版] 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现 ...
- js 拉勾网效果_Node.js 中实践基于 Redis 的分布式锁实现
在一些分布式环境下.多线程并发编程中,如果对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题. 作者简介:五月君,Nodejs Developer ...
- php使用redis分布式锁,php基于redis的分布式锁实例详解
在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现. 固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效 ...
- 基于Redis的分布式锁到底安全吗(上)?
网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现算法也看似合 ...
- 基于Redis的分布式锁实现
本文转自 一.分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问,Java中我们一般可以使用synchronized语法和ReetrantLock去保证,这实际上是本地锁的 ...
最新文章
- [CQOI2012] 局部极小值(状压DP + 容斥 + 搜索)
- Unable to parse the date: 2017-12-30 日期格式转化失败
- ERP会给企业带来什么好处?
- Language binding(语言绑定)
- jQuery 1.3 API 参考文档中文版
- 新华三培训2---HSRP/VRRP/GLBP
- 在线问卷调查系统分析与实现
- 三阶段最小二乘法 回归分析 3SLS python实现
- 2022-2028年全球与中国婴儿食品包装行业产销需求与投资预测分析
- #爬取电影天堂的磁力链接#
- 深度学习基础理论(学习中持续更新)
- 如何确定当前的iPhone /设备型号?
- MAC地址 单播,组播,广播
- 利用线性布局和相对布局实现一个简单的页面
- electron-vue+electron-updater实现自动更新
- 后缀自动机(我太蒟了!)
- 度分秒与经纬度的互转
- 小样本few shot
- navicat数据库管理软件延长试用期
- 开源的晶体管测试仪版本注意事项
热门文章
- aac蓝牙编解码协议_蓝牙音频编码哪个音质好?今天我们来逐一解读
- html5新特性 移除哪些,html5\CSS3有哪些新特性、移除了哪些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分HTML和HTML5?...
- c语言运动会成绩统计报告,C语言程序设计运动会成绩统计系统1研究报告.doc
- python打包的exe如何免杀_通过Python实现Payload分离免杀过程详解
- java对象的状态,Java编程菜鸟课程:状态对象
- Vmware 和 Windows 代理设置
- mysql 函数的参数_MySQL中的数值函数
- 山东计算机编程哪个学校好,山东男孩,8岁懂电脑编程,10岁考上南科大,最后为何惨遭退学?...
- postgresql 编码_开源力量与职业发展 --写给对PostgreSQL有志趣的朋友们
- 【 MATLAB 】DFT的性质讨论(二)序列的循环移位及其 MATLAB 实现(频域方法)