分布式锁实现----红锁

红锁实现

多个Redisson + 过半加锁成功

这几台redis都是主,没有存,这样就不需要进行数据同步操作,所以没问题

红锁的流程

  1. 首先获取当前时间
  2. 按照一定的顺序给 n 台独立的redis 进行加锁
  3. 一切顺利的情况是给这几个redis 一直加锁完成
  4. 如果有一部分redis没有加锁完成,就要计算加锁完成的数量是否已过半
  5. 加锁失败的情况:a、加锁时间 > 锁的有效期 b、未过半
  6. 所有的redis 都要释放一遍锁

红锁常见问题

  • 服务器时间校准问题——需要运维维护

  • 启动挂掉的redis时要延时启动
    锁的过期时间是20s、启动挂掉的redis 30s后再启动

    场景:线程一在加锁的时候,给redis 1、2、3 都加锁,过半过去锁成功,然后redis 3 挂掉,这时候 线程一还没有执行完逻辑。然后运维人员启动了这个redis、这个时候线程二进来 会给redis 3、4、5 上锁成功,同样能获取到锁。 这样两个线程在同一段时间就都能拿到锁,违背了锁的互斥性。

    怎么解决? —- 运维人员延迟启动、延时启动redis 的时间一定要大于锁的过期时间。

实现

配置的n个Redis 是独立的n台Redis n 是奇数

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
34
35
36
37
38
39
40
public class RedisRedissonRedLockLock {

@Autowired
@Qualifier("redissonRed1")
private RedissonClient redissonRed1;
@Autowired
@Qualifier("redissonRed2")
private RedissonClient redissonRed2;
@Autowired
@Qualifier("redissonRed3")
private RedissonClient redissonRed3;

@Autowired
OrderService orderService;

@Override
public String test(){
//生成key
String lockKey = "lockKey"; // 根据实际业务设置

//红锁 redis son
RLock rLock1 = redissonRed1.getLock(lockKey);
RLock rLock2 = redissonRed2.getLock(lockKey);
RLock rLock3 = redissonRed3.getLock(lockKey);
RedissonRedLock rLock = new RedissonRedLock(rLock1,rLock2,rLock3);

try {
rLock.lock(); // 此代码默认 设置key 超时时间30秒,过10秒,再延时
try {
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
// TODO 需要加锁的逻辑
} finally {
rLock.unlock();
}
return null;
}
}

分布式锁实现----红锁
http://yoursite.com/post/38d7315d.html/
Author
Chase Wang
Posted on
November 30, 2021
Licensed under