redis实现分布式锁
来源:互联网 发布:1977特纳里夫空难 知乎 编辑:程序博客网 时间:2024/06/05 17:16
1.基本思想
http://doc.redisfans.com/string/set.html 有说明 如下
命令 SET resource-name anystring NX EX max-lock-time 是一种在 Redis 中实现锁的简单方法。
客户端执行以上的命令:
- 如果服务器返回 OK ,那么这个客户端获得锁。
- 如果服务器返回 NIL ,那么客户端获取锁失败,可以在稍后再重试。
设置的过期时间到达之后,锁将自动释放。(必须设置过期时间,以防获取锁的机器崩溃没有释放锁,其他机器永远不能获得锁)
可以通过以下修改,让这个锁实现更健壮:
- 不使用固定的字符串作为键的值,而是设置一个不可猜测(non-guessable)的长随机字符串,作为口令串(token)。
- 不使用 DEL 命令来释放锁,而是发送一个 Lua 脚本,这个脚本只在客户端传入的值和键的口令串相匹配时,才对键进行删除。
这两个改动可以防止持有过期锁的客户端误删现有锁的情况出现。
以下是一个简单的解锁脚本示例:
2.代码实现
import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import redis.clients.jedis.exceptions.JedisNoScriptException;import java.util.Collections;import java.util.HashSet;import java.util.Set;import java.util.UUID;/** * 分布式锁 */public class RedisLock { private JedisCluster jedisCluster; private String value; private static final String OK = "OK"; private final int defaultLockExpireTime; private static String releaseLockLua = "if redis.call('get', KEYS[1]) == ARGV[1]" + " then" + " return redis.call('del', KEYS[1])" + " else" + " return 0" + " end"; private String key; private static String sha; public RedisLock(JedisCluster jedisCluster, String key) { this.jedisCluster = jedisCluster; this.key = key; this.defaultLockExpireTime = 2000; } public RedisLock(JedisCluster jedisCluster, String key, int expireTime) { this.jedisCluster = jedisCluster; this.key = key; this.defaultLockExpireTime = expireTime; } /** * 无限阻塞直到获取到锁 */ public void lock() { value = UUID.randomUUID().toString(); for (; ; ) { //不存在则添加 且设置过期时间(单位ms) String status = jedisCluster.set(key, value, "NX", "PX", defaultLockExpireTime); //获得锁 if (OK.equals(status)) { break; } try { Thread.sleep(2); } catch (Exception e) { //ignore } } } /** * 尝试获取锁 超时返回 * * @param awitTime 等待时间 * @return 是否成功获得锁 */ public boolean tryLock(long awitTime) { value = UUID.randomUUID().toString(); long expireTime = System.currentTimeMillis() + awitTime; while (System.currentTimeMillis() < expireTime) { //不存在则添加 且设置过期时间(单位ms) String status = jedisCluster.set(key, value, "NX", "PX", defaultLockExpireTime); //获得锁 if (OK.equals(status)) { return true; } try { Thread.sleep(2); } catch (Exception e) { //ignore } } return false; } /** * 尝试获取锁 立即返回 * * @return 是否成功获得锁 */ public boolean tryLock() { value = UUID.randomUUID().toString(); //不存在则添加 且设置过期时间(单位ms) String status = jedisCluster.set(key, value, "NX", "PX", defaultLockExpireTime); //获得锁 return OK.equals(status); } /** * 释放锁 释放失败则抛异常 */ public void unlockWithExcepion() { if (sha == null) { sha = jedisCluster.scriptLoad(RedisLock.releaseLockLua, "releaseLockLua"); } Long eval; try { eval = (Long) jedisCluster.evalsha(sha, Collections.singletonList(key), Collections.singletonList(value)); } catch (JedisNoScriptException e) { eval = (Long) jedisCluster.eval(releaseLockLua, Collections.singletonList(key), Collections.singletonList(value)); } if (eval == 0) { throw new RuntimeException("释放锁失败,已超时"); } } /** * 释放锁 * * @return 锁是否释放成功 */ public boolean unlock() { if (sha == null) { sha = jedisCluster.scriptLoad(RedisLock.releaseLockLua, "releaseLockLua"); } Long eval; try { eval = (Long) jedisCluster.evalsha(sha, Collections.singletonList(key), Collections.singletonList(value)); } catch (JedisNoScriptException e) { eval = (Long) jedisCluster.eval(releaseLockLua, Collections.singletonList(key), Collections.singletonList(value)); } return eval == 1; } public static void main(String[] args) throws InterruptedException { HostAndPort hostAndPort1 = new HostAndPort("ip1", 20621); HostAndPort hostAndPort2 = new HostAndPort("ip2", 20622); HostAndPort hostAndPort3 = new HostAndPort("ip3", 20622); Set<HostAndPort> set = new HashSet<>(); set.add(hostAndPort1); set.add(hostAndPort2); set.add(hostAndPort3); JedisCluster jedisCluster = new JedisCluster(set); RedisLock redisLock = new RedisLock(jedisCluster, "redis:zhp"); redisLock.lock(); System.out.println("处理数据"); redisLock.unlock(); }}
阅读全文
0 0
- Redis实现分布式锁
- Redis 分布式锁实现
- Redis 分布式锁实现
- Redis实现分布式锁
- redis实现分布式锁
- Redis实现分布式锁
- 分布式锁redis实现
- Redis 分布式锁实现
- redis分布式锁实现
- redis实现分布式锁
- Redis分布式锁实现
- redis分布式锁实现
- redis实现分布式锁
- Redis分布式锁实现
- Redis实现分布式锁
- Redis实现分布式锁
- redis实现分布式锁
- Redis实现分布式锁
- 笔试复习_C++_类(一)
- 知道创宇研发技能表3.1
- 笔试面试高频题(操作系统)
- springboot学习----加载application.property
- 计算机网络笔记整理(四):网络层
- redis实现分布式锁
- Qt Creator下载和安装(详细教程)
- Python和Java的区别
- lrzsz串口工具移植到ARM开发板
- Faster-RCNN
- validate+jquery+ajax表单验证
- LintCode 4:Ugly Number II
- unity 在pc平台 重启应用程序
- python的urlparse