引言

分布式锁是分布式系统的关键组件。本文介绍Redis分布式锁的实现。

一、基础实现

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
public class RedisLock {
private Jedis jedis;

public boolean tryLock(String key, String value, int expireSeconds) {
String result = jedis.set(key, value, "NX", "EX", expireSeconds);
return "OK".equals(result);
}

public void unlock(String key, String value) {
String script =
"if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
jedis.eval(script, Collections.singletonList(key), Collections.singletonList(value));
}
}

// 使用
String lockKey = "lock:order:123";
String lockValue = UUID.randomUUID().toString();

if (redisLock.tryLock(lockKey, lockValue, 30)) {
try {
// 业务逻辑
} finally {
redisLock.unlock(lockKey, lockValue);
}
}

二、Redisson实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Autowired
private RedissonClient redisson;

public void processOrder(Long orderId) {
RLock lock = redisson.getLock("lock:order:" + orderId);

try {
// 尝试加锁,最多等待10秒,锁30秒后自动释放
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
try {
// 业务逻辑
} finally {
lock.unlock();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}

三、可重入锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Redisson支持可重入
RLock lock = redisson.getLock("myLock");

lock.lock();
try {
// 可以再次获取锁
lock.lock();
try {
// 业务逻辑
} finally {
lock.unlock();
}
} finally {
lock.unlock();
}

四、RedLock算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 多个Redis实例
RedissonClient redisson1 = ...;
RedissonClient redisson2 = ...;
RedissonClient redisson3 = ...;

RLock lock1 = redisson1.getLock("myLock");
RLock lock2 = redisson2.getLock("myLock");
RLock lock3 = redisson3.getLock("myLock");

// RedLock
RLock redLock = redisson.getRedLock(lock1, lock2, lock3);

redLock.lock();
try {
// 业务逻辑
} finally {
redLock.unlock();
}

总结

Redis分布式锁核心:

  1. SET NX EX:原子性加锁
  2. Lua脚本:原子性解锁
  3. UUID:防止误删
  4. Redisson:完善的分布式锁实现

参考资料