分布式锁中的基于redis的setnx的原理以及set和setnx的区别是什么
基于Redis实现分布式锁。虽然网上介绍的Redis分布式锁博客比较多,却有着各种各样的问题,本篇博客将详细介绍如何正确地使用setnx实现Redis分布式锁
这里就不介绍错误的示范了 大家直接看正确的例子:
//保存客户端标识
private static final ThreadLocal<String> LOCAL = new ThreadLocal<String>();
/**
*
* @param jedis
* @param lockKey 锁key
* @param expires 过期时间 一般为 System.currentTimeMillis()+ 过期时间
* @return
*/
public static boolean getDistributedLock(Jedis jedis, String lockKey, long expires) {
//客户端标识 在释放锁时 确保由设置锁的客户端来释放自己的锁
String uuid = UUID.randomUUID().toString();
LOCAL.set(uuid);
String expiresStr = uuid+"#"+expires;
// 如果当前锁不存在,返回加锁成功
if (jedis.setnx(lockKey, expiresStr) == 1) {
return true;
}
// 如果锁存在,获取锁的过期时间
String currentValue = jedis.get(lockKey);
String currentValueStr = null==currentValue?null:currentValue.split("#")[1];
// 判断当前锁是否过期
if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
// 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间 此处多个客户端会覆盖锁的过期时间
String oldValue = jedis.getSet(lockKey,expiresStr);
String oldValueStr = null ==oldValue?null:oldValue.split("#")[1];
// 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才有权利加锁
if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
//由于上面会覆盖锁的过期时间 此处让获取锁的客户端 重新设置为自己的过期时间
jedis.set(lockKey,expiresStr);
return true;
}
}
// 其他情况,一律返回加锁失败
return false;
}
/**
*
* @param jedis
* @param lockKey 锁key
* @param value 过期时间 一般为 System.currentTimeMillis()+ 过期时间
* @return
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, long value) {
String uuid = LOCAL.get();
String valueStr = uuid+"#"+value;
//根据uuid 这个标识 让客户端 去释放自己的锁 不能释放别人的锁
if(valueStr.equals(jedis.get(lockKey))){
jedis.del(lockKey);
return true;
}
return false;
}
————————————————
版权声明:本文为CSDN博主「wudidewu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wudidewu/article/details/79817125
分布式锁中的基于redis的setnx的原理以及set和setnx的区别是什么的更多相关文章
- 分布式锁(2) ----- 基于redis的分布式锁
分布式锁系列文章 分布式锁(1) ----- 介绍和基于数据库的分布式锁 分布式锁(2) ----- 基于redis的分布式锁 分布式锁(3) ----- 基于zookeeper的分布式锁 代码:ht ...
- 分布式锁(3) ----- 基于zookeeper的分布式锁
分布式锁系列文章 分布式锁(1) ----- 介绍和基于数据库的分布式锁 分布式锁(2) ----- 基于redis的分布式锁 分布式锁(3) ----- 基于zookeeper的分布式锁 代码:ht ...
- 借读:分布式锁和双写Redis
本帖最后由 howtodown 于 2016-10-3 16:01 编辑问题导读1.为什么会产生分布式锁?2.使用分布式锁的方法有哪些?3.本文创造的分布式锁的双写Redis框架都包含哪些内容? ...
- 分布式锁的实现之 redis 篇
为什么需要分布式锁 引入经典的秒杀情景,100件商品供客户抢.如果是单机版的话,我们使用synchronized 或者 lock 都可以实现线程安全.但是如果多个服务器的话,synchronized ...
- springboot实现分布式锁(spring integration,redis)
Springboot实现分布式锁(Spring Integration+Redis) 一.在项目的pom.xml中添加相关依赖 1)Spring Integration依赖 <dependenc ...
- 服务注册发现consul之四: 分布式锁之四:基于Consul的KV存储和分布式信号量实现分布式锁
一.基于key/value实现 我们在构建分布式系统的时候,经常需要控制对共享资源的互斥访问.这个时候我们就涉及到分布式锁(也称为全局锁)的实现,基于目前的各种工具,我们已经有了大量的实现方式,比如: ...
- 分布式锁与实现--基于ZooKeeper实现
引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...
- 分布式锁实现(一):Redis
前言 单机环境下我们可以通过JAVA的Synchronized和Lock来实现进程内部的锁,但是随着分布式应用和集群环境的出现,系统资源的竞争从单进程多线程的竞争变成了多进程的竞争,这时候就需要分布式 ...
- 分布式锁中的王者方案-Redisson
上篇讲解了如何用 Redis 实现分布式锁的五种方案,但我们还是有更优的王者方案,就是用 Redisson. 缓存系列文章: 缓存实战(一):20 图 |6 千字|缓存实战(上篇) 缓存实战(二):R ...
随机推荐
- vue data数据恢复初始化
Object.assign(this.$data, this.$options.data())
- 使用Nginx的proxy_cache缓存功能取代Squid[原创]
使用Nginx的proxy_cache缓存功能取代Squid[原创] [文章作者:张宴 本文版本:v1.2 最后修改:2009.01.12 转载请注明原文链接:http://blog.zyan.cc/ ...
- thinkPHP5.0.22初体验---路由,url访问
“豪情卷起万重浪,吼吼哈哈-”一学thinkPHP才知道这是个国内研究的php web开发框架,瞬间自豪感如电流一般传遍全身 这就不多不说说 一.控制器 所谓MVC编程,无外乎函数(sometimes ...
- php面向对象相关技术
step1 一个经典类的设计和实例化 <?php class mycoach { public $_name=''; public $_age=''; public $_expert=array ...
- Linux下C++编译(代码高亮自动换行)
1.环境准备 在ubuntu中要想编译c程序可以安装gcc编译器,编译c++的话就不能使用gcc了,要使用g++编译器. 安装gcc或是g++可以在新立得软件包管理器中直接搜索后安装或是使用终端文字命 ...
- DveOps路线指南
学习DevOps所需的技能 1. 编程语言 python java javascrit 2. 学习不同的操作系统概念 进程管理,线程和兵法,套接字,I/O管理,虚拟化,内存储存储和文件系统. 3. ...
- websocket练习
html代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> < ...
- struts2没有打印日志原因和No result defined for action XXXAction and result input
在项目中调用一个action的方法的时候发生了一个错误,但是在catalina.out和配置的log4j都没有打印异常,后来在执行的action中加了logger.error("XXXXX& ...
- chomre 控制台断点调试
在上图蓝色圆圈中数字,它们分别代表: 1.停止断点调试 2.不跳入函数中去,继续执行下一行代码(F10) 3.跳入函数中去(F11) 4.从执行的函数中跳出 5.禁用所有的断点,不做任何调试 6.程序 ...
- Python Internet 模块
Python Internet 模块 以下列出了 Python 网络编程的一些重要模块: 协议 功能用处 端口号 Python 模块 HTTP 网页访问 80 httplib, urllib, xml ...