redis分布式锁
什么是分布式锁,为什么需要分布式锁,这些问题在这里我就重复了,相关资料很多就复述了!
官方文档:https://redis.io/topics/distlock
参考博客:http://www.cnblogs.com/linjiqin/p/8003838.html
首先,我们要知道分布式锁必须具备的特性:
- 互斥性(安全):再多线程环境下,必须只能有某一个线程持有锁
- 避免死锁:在规定时间内,持有锁的线程必须释放锁,如果该线程没有主动释放则自动释放锁
- 可用性:当出现单点故障时,可以保证锁正常的设置和释放
- 除设置锁客户端之外,其他客户端不能释放锁
引入依赖:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>x.x.x</version> </dependency>
使用redis设置锁:
public class RLock{ private static final String LOCK_SUCCESS = "OK"; private static final String SET_IF_NOT_EXIST = "NX"; private static final String SET_WITH_EXPIRE_TIME = "PX"; /** * 设置分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param clientId 客户端标识 * @param expireTime 超期时间 * @return 是否设置成功 */ public static boolean setLock(Jedis jedis, String lockKey, String clientId, int expireTime) { String result = jedis.set(lockKey, clientId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); if (LOCK_SUCCESS.equals(result)) { return true; } return false; } }
释放锁:
public class Rlock { private static final Long RELEASE_SUCCESS = 1L; /** * 释放分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 * @param clientId 客户端标识 * @return 是否释放成功 */ public static boolean releaseLock(Jedis jedis, String lockKey, String clientId) { 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(clientId)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; } }