当前位置: 代码迷 >> 综合 >> Redis深度历险-Redis分布式锁
  详细解决方案

Redis深度历险-Redis分布式锁

热度:81   发布时间:2024-02-05 09:07:14.0

原子操作

原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何context switch线程切换

分布式锁

分布式锁本质上要实现的目标就是在 Redis 里面占一个“茅坑”,当别的进程也要来占时,发现已经有人蹲在那里了,就只好放弃或者稍后再试;对于执行时间超过锁定时间的,需要锁具有重入性

Java 版本的可重入锁(基于ThreadLocal和引用计数)

public class RedisWithReentrantLock {private ThreadLocal<Map> lockers = new ThreadLocal<>();private Jedis jedis;public RedisWithReentrantLock(Jedis jedis) {this.jedis = jedis;}private boolean _lock(String key) {return jedis.set(key, "", "nx", "ex", 5L) != null;}private void _unlock(String key) {jedis.del(key);}private Map <String, Integer> currentLockers() {Map <String, Integer> refs = lockers.get();if (refs != null) {return refs;}lockers.set(new HashMap<>());return lockers.get();}public boolean lock(String key) {Map refs = currentLockers();Integer refCnt = refs.get(key);if (refCnt != null) {refs.put(key, refCnt + 1);return true;}boolean ok = this._lock(key);if (!ok) {return false;}refs.put(key, 1);return true;}public boolean unlock(String key) {Map refs = currentLockers();Integer refCnt = refs.get(key);if (refCnt == null) {return false;}refCnt -= 1;if (refCnt > 0) {refs.put(key, refCnt);} else {refs.remove(key);this ._unlock(key);}return true;}public static void main(String[] args) {Jedis jedis = new Jedis();RedisWithReentrantLock redis = new RedisWithReentrantLock(jedis);System.out.println(redis.lock("codehole"));System.out.println(redis.lock("codehole"));System.out.println(redis.unlock("codehole"));System.out.println(redis.unlock("codehole"));}
}

分布式锁线程加锁失败解决方案

仅供参考

1、直接抛出异常,通知用户稍后再试

2、设置锁等待时间,等待特定时间后重试

3、将请求转至延时队列,一会再重试