prefacio
Como ya se ha aprendizaje de los principios cerraduras Redission reentrada y cerraduras justas, y luego buscar la forma de lograr RedLock Redission de.
principio RedLock
RedLock se basa en el bloqueo distribuido ReDiS implementado, se puede garantizar las siguientes características:
- exclusividad mutua: En cualquier momento, sólo un cliente puede obtener un bloqueo; estancamiento evite:
- Cuando el cliente para conseguir el bloqueo, aun cuando se produjo la partición de tiempo de inactividad del cliente o de la red, no punto muerto; (tiempo de supervivencia clave de uso)
- Resiliencia: Mientras un nodo mayoría REDIS ejemplo de funcionamiento normal, es posible proporcionar servicios, bloqueo o liberar el bloqueo;
algoritmo RedLock, lo que significa que no sólo crea un bloqueo en un ejemplo redis, se debe crear en la cerradura varias instancias Redis, el n- / 2 + 1 , debe haber creado con éxito un bloqueo en la mayoría de los nodos Redis, esto puede ser considerado en su conjunto el éxito de bloqueo RedLock, para evitar problemas, sólo en dicha cerradura en una instancia Redis traído.
RedLock aquí unos días para resolver adhieren hace un artículo más a fondo:
https://mp.weixin.qq.com/s/gOYWLg3xYt4OhS46woN_Lg
El principio redisson
Redisson hay un MultiLock
concepto de múltiples cerraduras se pueden combinar en una gran cerradura, cerradura grande en una aplicación unificada para el bloqueo y la liberación de la cerradura
El redisson se basa en la realización RedLock MultiLock
hace, entonces nos fijamos en la aplicación específica de la misma que corresponde
casos de uso RedLock
Mira los usos oficiales de código:
( https://github.com/redisson/redisson/wiki/8.-distributed-locks-and-synchronizers#84-redlock )
1RLock lock1 = redisson1.getLock("lock1");
2RLock lock2 = redisson2.getLock("lock2");
3RLock lock3 = redisson3.getLock("lock3");
4
5RLock redLock = anyRedisson.getRedLock(lock1, lock2, lock3);
6
7// traditional lock method
8redLock.lock();
9
10// or acquire lock and automatically unlock it after 10 seconds
11redLock.lock(10, TimeUnit.SECONDS);
12
13// or wait for lock aquisition up to 100 seconds
14// and automatically unlock it after 10 seconds
15boolean res = redLock.tryLock(100, 10, TimeUnit.SECONDS);
16if (res) {
17 try {
18 ...
19 } finally {
20 redLock.unlock();
21 }
22}
Estos son ejemplos de cerradura de tres redis, la cerradura a continuación, obtener un resultado final.
El principio RedissonRedLock
El ejemplo anterior utilizando redLock.lock () o trylock () en última instancia, realizar RedissonRedLock
un método.
RedissonRedLock
Heredado de RedissonMultiLock
, implementos de algunos de estos métodos:
1public class RedissonRedLock extends RedissonMultiLock {
2 public RedissonRedLock(RLock... locks) {
3 super(locks);
4 }
5
6 /**
7 * 锁可以失败的次数,锁的数量-锁成功客户端最小的数量
8 */
9 @Override
10 protected int failedLocksLimit() {
11 return locks.size() - minLocksAmount(locks);
12 }
13
14 /**
15 * 锁的数量 / 2 + 1,例如有3个客户端加锁,那么最少需要2个客户端加锁成功
16 */
17 protected int minLocksAmount(final List<RLock> locks) {
18 return locks.size()/2 + 1;
19 }
20
21 /**
22 * 计算多个客户端一起加锁的超时时间,每个客户端的等待时间
23 * remainTime默认为4.5s
24 */
25 @Override
26 protected long calcLockWaitTime(long remainTime) {
27 return Math.max(remainTime / locks.size(), 1);
28 }
29
30 @Override
31 public void unlock() {
32 unlockInner(locks);
33 }
34
35}
Véase locks.size()/2 + 1
, por ejemplo, tenemos tres instancias de cliente, entonces por lo menos dos ejemplos del éxito de bloqueo considera el éxito de bloqueo de bloqueo distribuido.
A continuación, nos fijamos en lock()
la realización concreta
El principio RedissonMultiLock
1public class RedissonMultiLock implements Lock {
2
3 final List<RLock> locks = new ArrayList<RLock>();
4
5 public RedissonMultiLock(RLock... locks) {
6 if (locks.length == 0) {
7 throw new IllegalArgumentException("Lock objects are not defined");
8 }
9 this.locks.addAll(Arrays.asList(locks));
10 }
11
12 public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
13 long newLeaseTime = -1;
14 if (leaseTime != -1) {
15 // 如果等待时间设置了,那么将等待时间 * 2
16 newLeaseTime = unit.toMillis(waitTime)*2;
17 }
18
19 // time为当前时间戳
20 long time = System.currentTimeMillis();
21 long remainTime = -1;
22 if (waitTime != -1) {
23 remainTime = unit.toMillis(waitTime);
24 }
25 // 计算锁的等待时间,RedLock中:如果remainTime=-1,那么lockWaitTime为1
26 long lockWaitTime = calcLockWaitTime(remainTime);
27
28 // RedLock中failedLocksLimit即为n/2 + 1
29 int failedLocksLimit = failedLocksLimit();
30 List<RLock> acquiredLocks = new ArrayList<RLock>(locks.size());
31 // 循环每个redis客户端,去获取锁
32 for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext();) {
33 RLock lock = iterator.next();
34 boolean lockAcquired;
35 try {
36 // 调用tryLock方法去获取锁,如果获取锁成功,则lockAcquired=true
37 if (waitTime == -1 && leaseTime == -1) {
38 lockAcquired = lock.tryLock();
39 } else {
40 long awaitTime = Math.min(lockWaitTime, remainTime);
41 lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
42 }
43 } catch (Exception e) {
44 lockAcquired = false;
45 }
46
47 // 如果获取锁成功,将锁加入到list集合中
48 if (lockAcquired) {
49 acquiredLocks.add(lock);
50 } else {
51 // 如果获取锁失败,判断失败次数是否等于失败的限制次数
52 // 比如,3个redis客户端,最多只能失败1次
53 // 这里locks.size = 3, 3-x=1,说明只要成功了2次就可以直接break掉循环
54 if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {
55 break;
56 }
57
58 // 如果最大失败次数等于0
59 if (failedLocksLimit == 0) {
60 // 释放所有的锁,RedLock加锁失败
61 unlockInner(acquiredLocks);
62 if (waitTime == -1 && leaseTime == -1) {
63 return false;
64 }
65 failedLocksLimit = failedLocksLimit();
66 acquiredLocks.clear();
67 // 重置迭代器 重试再次获取锁
68 while (iterator.hasPrevious()) {
69 iterator.previous();
70 }
71 } else {
72 // 失败的限制次数减一
73 // 比如3个redis实例,最大的限制次数是1,如果遍历第一个redis实例,失败了,那么failedLocksLimit会减成0
74 // 如果failedLocksLimit就会走上面的if逻辑,释放所有的锁,然后返回false
75 failedLocksLimit--;
76 }
77 }
78
79 if (remainTime != -1) {
80 remainTime -= (System.currentTimeMillis() - time);
81 time = System.currentTimeMillis();
82 if (remainTime <= 0) {
83 unlockInner(acquiredLocks);
84 return false;
85 }
86 }
87 }
88
89 if (leaseTime != -1) {
90 List<RFuture<Boolean>> futures = new ArrayList<RFuture<Boolean>>(acquiredLocks.size());
91 for (RLock rLock : acquiredLocks) {
92 RFuture<Boolean> future = rLock.expireAsync(unit.toMillis(leaseTime), TimeUnit.MILLISECONDS);
93 futures.add(future);
94 }
95
96 for (RFuture<Boolean> rFuture : futures) {
97 rFuture.syncUninterruptibly();
98 }
99 }
100
101 return true;
102 }
103}
El código del núcleo ha añadido una nota para lograr el principio es muy simple, basado en RedLock pensado a través de todo el cliente Redis y, a continuación, activar el bloqueo, el último recuento del número de éxitos para determinar si el bloqueo se realiza correctamente.
declarar
Este artículo partir de mi blog: https://www.cnblogs.com/wang-meng y números públicos: Una ramiflorous ser considerado romántico , debe volver a imprimir favor indique la fuente!
socio interesado puede estar preocupado por el pequeño número de público individuo: Una rama recuento de flores románticas