使用redis实现一个简单的分布式锁,主要是使用redis的setnx和getset方法进行实现。
加锁:
1.使用setnx设置值:
key:为需要加锁的锁名 value 为 当前时间+锁的超时时间
成功:
返回true 和锁的超时时间
失败:
根据key获取超时时间
为空:说明该锁已经释放了,重新获取锁
不为空:
判断锁是否已经超时
超时:
使用getset进行获取锁
如果返回的值和上一步获取的锁的超时时间一样说明获取锁,(当不一样时可能会导致将上一个线程设置的锁的超时时间进行修改,应该影响不大。)
没有超时:
说明锁被别的线程持有。
解锁:
解锁只可解除自己加的锁:
先获取锁的超时时间
为空:说明该锁已经不存在了
不为空: 根据加锁得到的返回值 和解锁得到的时间进行比较,如果一样说明是自己加的锁。
代码:
com.huan.redis.redis_lock.Lock.LockResult ---> 获取锁之后的返回值 用于判断是否获取锁 和 放入锁中的内容
com.huan.redis.redis_lock.Lock ---> 锁的接口
com.huan.redis.redis_lock.RedisLock ---> 锁的具体实现
锁的接口
package com.huan.redis.redis_lock; /** * 锁的接口 * * @描述 * @作者 huan * @时间 2016年10月30日 - 下午2:31:10 */ public interface Lock { LockResult lock(String lockName); /** * 获取锁 * * @param lockName * 需要上那一把锁 * @param lockTime * 需要使用所的时间 * @param waitTime * 当waitTime这个时间之内还没有获取到锁就退出获取锁 */ LockResult lock(String lockName, long lockTime, long waitTime); /** * 释放锁 * * @param lockName */ void unLock(String lockName, LockResult result); static class LockResult { private boolean lock; private long info; public LockResult(boolean lock, long info) { super(); this.lock = lock; this.info = info; } public boolean isLock() { return lock; } public void setLock(boolean lock) { this.lock = lock; } public long getInfo() { return info; } public void setInfo(long info) { this.info = info; } } }
锁的具体实现
package com.huan.redis.redis_lock; import java.text.SimpleDateFormat; import java.util.Date; import redis.clients.jedis.Jedis; /** * 使用redis实现分布式锁 * * @描述 * @作者 huan * @时间 2016年10月30日 - 下午2:39:11 */ public class RedisLock implements Lock { private Jedis jedis; public RedisLock(Jedis jedis) { this.jedis = jedis; } @Override public LockResult lock(String lockName, long lockTime, long waitTime) { long now = System.currentTimeMillis(); LockResult lockResult = new LockResult(false, 0); while (System.currentTimeMillis() - now <= waitTime) { // 重试 直到超时 long needLockTime = System.currentTimeMillis() + lockTime; if (jedis.setnx("lock:" + lockName, String.valueOf(needLockTime)) == 1) { // 获取锁 System.out.println(Thread.currentThread().getName() + " : 获取锁1.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); lockResult = new LockResult(true, needLockTime); return lockResult; } String oldTime = jedis.get("lock:" + lockName); // 如果没有获取锁,则获取锁的持有时间 if (null != oldTime) { // 锁还在 if (System.currentTimeMillis() - Long.parseLong(oldTime) > 0) { // 锁已经超时 needLockTime = System.currentTimeMillis() + lockTime; // 计算新的锁超时时间 String _oldLockTime = jedis.getSet("lock:" + lockName, String.valueOf(needLockTime)); // 设置锁的超时时间 if (null != oldTime && _oldLockTime != null && oldTime.equals(_oldLockTime)) { // 获取锁 System.out.println(Thread.currentThread().getName() + " : 获取锁2.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); lockResult = new LockResult(true, needLockTime); return lockResult; } else { // System.out.println("另外的线程释放锁."); } } // System.out.println(Thread.currentThread().getName() + " : 尝试获取锁.."); } else { // 另外的线程释放锁,需要重新获取锁 needLockTime = System.currentTimeMillis() + lockTime; // 计算新的锁超时时间 if (jedis.setnx("lock:" + lockName, String.valueOf(needLockTime)) == 1) { System.out.println(Thread.currentThread().getName() + " : 获取锁3.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); lockResult = new LockResult(true, needLockTime); return lockResult; } } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } return lockResult; } @Override public void unLock(String lockName, LockResult lockResult) { String oldTime = jedis.get("lock:" + lockName); if (null != oldTime && lockResult.isLock() && lockResult.getInfo() == Long.parseLong(oldTime)) { System.out.println(Thread.currentThread().getName() + " 释放锁.." + new SimpleDateFormat("yyyyMMdd HH:mm:ss").format(new Date())); jedis.del("lock:" + lockName); } else { if (0 == lockResult.getInfo()) { System.out.println(Thread.currentThread().getName() + " : 获取锁失败..."); } else { System.out.println(Thread.currentThread().getName() + " 持有的锁由于已经被被的线程修改锁不用次线程进行释放."); } } } @Override public LockResult lock(String lockName) { return lock(lockName, Long.MAX_VALUE, Long.MAX_VALUE); } }
测试:
相关推荐
redis实现分布式锁,自旋式加锁,lua原子性解锁
主要介绍了Java基于redis实现分布式锁代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现 redis实现分布式锁(java/jedis),其中包含工具方法以及使用demo 本资源是利用java的jedis实现
用Redis实现分布式锁的简易教程,在ppt中附有代码解析
用Redis实现分布式锁 与 实现任务队列
基于go和redis实现分布式锁,使用了看门狗和红锁
C++的redis的API、 需要boost库、可直接加入工程目录编译
分布式锁有很多种解决方案,今天我们要讲的是怎么使用缓存数据库Redis来实现分布式锁。 课程目标: 理解redis分布式锁的应用场景 掌握redis分布式锁的实现原理 掌握redis分布式锁在微服务项目中的应用 掌握...
之前看很多人手写分布式锁,其实 Spring Boot 现在已经做的足够好了,开箱...本篇栈长以 Redis 为例(这也是用得最多的方案),教大家如何利用 Spring Boot 集成 Redis 实现缓存,如何简单、快速实现 Redis 分布式锁。
自己整理的如何利用redis实现分布式锁,redis实现分布式锁看这一篇绝对够。
自己封装redisson方法,同时通过注解的方式加入redis分布式事务锁,可靠。
redis实现分布式锁 数据库实现分布式锁 zk实现分布式锁 今天我们介绍通过redis实现分布式锁。实际上这三种和java对比看属于一类。都是属于程序外部锁。 原理剖析 上述三种分布式锁都是通过各自为依据对各个请求...
分布式锁是在分布式环境下(多个JVM进程)控制多个客户端对某一资源的同步访问的一种实现,与之相对应的是线程锁,线程锁控制的是同一个JVM进程内多个线程之间的同步。分布式锁的一般实现方法是在应用服务器之外通过...
基于Redis方式实现分布式锁
Redis实现分布式锁的几种方法总结 分布式锁是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问...
现在很多项目单机版已经不满足了,分布式变得越受欢迎,同时也带来很多问题,分布式锁也变得没那么容易实现,分享一个redis分布式锁工具类,里面的加锁采用lua脚本(脚本比较简单,采用java代码实现,无须外部调用...
用注解实现redis分布式锁,防止短时间内重复请求,尤其对于请求耗时较长的方法,希望对大家有帮助
本篇博客将介绍第二种方式,基于Redis实现分布式锁。虽然网上已经有各种介绍Redis分布式锁实现的博客,然而他们的实现却有着各种各样的问题,为了避免误人子弟,本篇博客将详细介绍如何正确地实现Redis分布式锁。 ...