Distribuye Lock] 03- [utilización redisson alcanzar principio RedLock

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 MultiLockconcepto 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 MultiLockhace, 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 RedissonRedLockun método.

RedissonRedLockHeredado 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

22.jpg

Supongo que te gusta

Origin www.cnblogs.com/wang-meng/p/12536660.html
Recomendado
Clasificación