Redis实现分布式锁
一、Redis特性
- Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问。
- 多客户端对redis的连接并不存在竞争关系。
- Redis命令操作具有原子性。
二、分布式锁的要求
- 安全性: 互斥,在任何时候,只有一个客户端能持有锁。
- 活跃性A:没有死锁,即使客户端在持有锁的时候崩溃,最后也会有其他客户端能获得锁,有超时机制。
- 活跃性B:故障容忍,只有大多数Redis节点时存活的,客户端仍可以获得锁和释放锁。
三、实现锁的重要命令
SETNX key value
当且仅当key不存在时,将key的值设为value,返回1
若给定的key已经存在,则SETNX不做任何动作,返回0
GETSET key value
将给定key的值设为value,返回key对应的旧的value
当key存在但不是字符串类型时,返回一个错误
当key不存在时,返回nil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| private boolean acquireLock(Long tenantId, String lockKey, long expired) { boolean success = false; long value = System.currentTimeMillis() + expired; boolean flag = cacheClient.setnx(tenantId, lockKey, String.valueOf(value)); if (flag) { success = true; } else { long oldValue = Long.valueOf(cacheClient.get(tenantId, lockKey)); if (oldValue < System.currentTimeMillis()) { String getValue = cacheClient.getSet(tenantId, lockKey, String.valueOf(value)); if (Long.valueOf(getValue) == oldValue) { success = true; } else { success = false; } } else { success = false; } } return success; } private void unLock(Long tenantId, String lockKey) { cacheClient.del(tenantId,lockKey); }
|