Java基于Redis的分布式锁
2024-09-07 06:26:50
分布式锁,其实最终还是要保证锁(数据)的一致性,说到数据一致性,基于ZK,ETCD数据一致性中间件做分数是锁,才是王道。但是Redis也能满足最基本的需求。
参考:
https://www.cnblogs.com/technologykai/p/8658689.html
https://www.cnblogs.com/rgcLOVEyaya/p/RGC_LOVE_YAYA_1003days.html
@Component
public class RedisLockManager implements Lock {
Logger logger = LoggerFactory.getLogger(RedisLockManager.class); @Autowired
RedisTool redisManager;
/**
* 请求锁的超时时间(ms)
*/
private final long TIME_OUT = 30000;
/**
* 锁的有效时间(毫秒)
*/
private long expire = 15000;
private String key;
private String value; private volatile boolean isLocked = false; public void setKey(String key) {
this.key = key;
} public void setValue(String value) {
this.value = value;
} @Override
public void lock() {
//系统当前时间,毫秒
long nowTime = System.nanoTime();
//请求锁超时时间,毫秒
long timeout = TIME_OUT * 1000000;
ThreadLocalRandom random = ThreadLocalRandom.current();
try {
while ((System.nanoTime() - nowTime) < timeout) {
boolean flag = redisManager.tryGetDistributedLock(this.key, this.value, this.expire);
if (flag) {
isLocked = true;
//上锁成功结束请求
break;
}
Thread.sleep(3, random.nextInt(500));
}
} catch (Exception e) {
isLocked = false;
logger.error(e.getMessage(), e);
}
} @Override
public void unlock() {
//释放锁
//不管请求锁是否成功,只要已经上锁,客户端都会进行释放锁的操作
if (isLocked) {
redisManager.releaseDistributedLock(this.key, this.value);
this.isLocked = false;
}
} @Override
public void lockInterruptibly() {
// TODO Auto-generated method stub } @Override
public boolean tryLock() {
// TODO Auto-generated method stub
return false;
} @Override
public boolean tryLock(long time, TimeUnit unit) {
this.expire = unit.toMillis(time);
this.lock();
return this.isLocked;
} @Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
@Component
public class RedisTool { @Autwire
Jedis jedis; private final String LOCK_SUCCESS = "OK";
private final String SET_IF_NOT_EXIST = "NX";
private final String SET_WITH_EXPIRE_TIME = "PX"; /**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) { String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false; } private final Long RELEASE_SUCCESS = 1L; /**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public boolean releaseDistributedLock(String lockKey, String requestId) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false; } }
最新文章
- 手把手教从零开始在GitHub上使用Hexo搭建博客教程(三)-使用Travis自动部署Hexo(1)
- vue+node开发手机端h5页面开发遇到的坑
- 用面对对象方式定tab标签
- resin 64 &; Java install
- tomcat deploy部署项目三种方法
- drawBitmapMesh方法关键参数的说明
- Yum出错Error: Cannot find a valid baseurl for repo: base
- [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法
- Windows as a Service(1)—— Windows 10服务分支
- PyCharm链接服务器同步代码
- js,获取和设置cookie、 localStorage
- Ubuntu 12.04: How to enable root login
- PHPstorm远程连接侧边栏怎么打开,远程数据库侧边栏怎么打开
- 分析easyswoole3.0源码,服务启动为例(一)
- [python] RRT快速拓展随机树
- eclipse 中右键项目出现卡死导致无法共享项目的解决办法
- sed用法说明
- JavaScript+CSS+DIV实现表格变色示例
- 深入理解Hadoop之HDFS架构
- React-Native使用极光进行消息推送
热门文章
- 使用 Sublime + PlantUML 高效地画图
- (2) Java SQL框架(java.sql.*)中常用接口详解
- 【Leetcode_easy】674. Longest Continuous Increasing Subsequence
- 02. oc语言是动态语言
- 【c# 学习笔记】使用新成员隐藏基类成员
- go os.State类用法
- Mybatis表关联一对多、多对一、多对多
- 【链接】js监听input输入框内容变化
- 会话技术——Cookies和Session详解
- [转帖]8086 CPU 寄存器简介