分布式锁,其实最终还是要保证锁(数据)的一致性,说到数据一致性,基于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; } }

最新文章

  1. 手把手教从零开始在GitHub上使用Hexo搭建博客教程(三)-使用Travis自动部署Hexo(1)
  2. vue+node开发手机端h5页面开发遇到的坑
  3. 用面对对象方式定tab标签
  4. resin 64 &amp; Java install
  5. tomcat deploy部署项目三种方法
  6. drawBitmapMesh方法关键参数的说明
  7. Yum出错Error: Cannot find a valid baseurl for repo: base
  8. [js高手之路]深入浅出webpack教程系列9-打包图片(file-loader)用法
  9. Windows as a Service(1)—— Windows 10服务分支
  10. PyCharm链接服务器同步代码
  11. js,获取和设置cookie、 localStorage
  12. Ubuntu 12.04: How to enable root login
  13. PHPstorm远程连接侧边栏怎么打开,远程数据库侧边栏怎么打开
  14. 分析easyswoole3.0源码,服务启动为例(一)
  15. [python] RRT快速拓展随机树
  16. eclipse 中右键项目出现卡死导致无法共享项目的解决办法
  17. sed用法说明
  18. JavaScript+CSS+DIV实现表格变色示例
  19. 深入理解Hadoop之HDFS架构
  20. React-Native使用极光进行消息推送

热门文章

  1. 使用 Sublime + PlantUML 高效地画图
  2. (2) Java SQL框架(java.sql.*)中常用接口详解
  3. 【Leetcode_easy】674. Longest Continuous Increasing Subsequence
  4. 02. oc语言是动态语言
  5. 【c# 学习笔记】使用新成员隐藏基类成员
  6. go os.State类用法
  7. Mybatis表关联一对多、多对一、多对多
  8. 【链接】js监听input输入框内容变化
  9. 会话技术——Cookies和Session详解
  10. [转帖]8086 CPU 寄存器简介