How to implement a distributed lock and availability with Redis

  In the actual development scenario, we may encounter different client needs exclusive access to a shared resource, which is the same time allowing only one client operating the shared resources, in order to achieve this purpose, usually a distributed lock to solve the current popular distributed lock implementations have a database, Memcached, Redis, file system, ZooKeeper, because Redis high performance, simple to deploy widely used, so today I will give you the next to share, how to implement a distributed lock with Redis .

First, a reliable, highly available distributed lock needs to meet the following

Mutually exclusive: at any moment, only one client has a lock can not be acquired multiple clients

Security: The lock can only be held by the lock client deleted and can not be removed by other clients

Deadlock: Get a lock client is down for some reason, failed to release the lock, other clients will not be able to acquire the lock, the need for mechanisms to avoid this kind of problem

High Availability: As part of the node goes down, the client can still get a lock or lock release

 

Second, implemented using a single node distributed lock Redis

Redis achieved using a single node distributed lock is the most common way, although not considered highly available, but simple, low cost and is used by many small and medium enterprises.

  Many online article said setnx achieved using a distributed lock, but setnx command can not set their own lock atomic expiration time, which means we can not set its expiration time setnx while executing the command, then there will be a deadlock, such as: Customer a complete end just executed setnx, this time the client a hung up, did not complete lock to set the expiration time, this time produced a deadlock, all clients can no longer obtain the lock. the situation generally use Lua script to achieve (because Redis Lua script execution is atomic), in fact, starting from the Redis 2.6.12 version set commands can replace setnx command, Tell me what network we set the parameters of the command

SET key value [EX seconds] [PX milliseconds] [NX|XX]

Parameter Description:

EX second: set the expiration time for the second bond seconds. SET key value EX second effect is equivalent to SETEX key second value.

PX millisecond: a setting key expiration time millisecond milliseconds. SET key value PX millisecond effect equivalent to PSETEX key millisecond value.

NX: only when the bond is absent, fishes key set operation. SET key value NX effect equivalent to SETNX key value.

XX: only when key already exists, fishes key set operation.

For example: 30,000 this role SET key value NX PX command is only when this key does not exist will set the key value (the role of NX option), the timeout is set (PX action option) 30,000 milliseconds

Then we take a set command or PX EX, and NX parameters can satisfy the above-mentioned mutual exclusivity (locking), the deadlock (expire) two requirements.

So how to meet the safety requirements of it?

For example: Client A to get locked and set an expiration time for the lock 10S, but due to some reason, the execution time A exceeds the client 10S, case locks automatically expire, the client B to get the lock, then the client A At this point just finished removing locks, but this time to remove the client B plus the lock, how to prevent this unsafe situation happen?

Option One:

We can make a thread to acquire a lock to open a daemon thread, used to own lock "renewal."

When passed 9S, Client A has not been performed, this time daemon thread will execute expire command, and then lock "renewal" 10S, 9S first daemon thread begins execution, execution once every 9 seconds.

When the client A task finishes, it will turn off explicit daemon thread.

If the client A sudden downtime due to A threads and daemon threads in the same process, a daemon thread will stop. This lock to a timeout when no one gave it renewed, it is automatically released.

Option II:

We can also be set at the value set value locked into a unique identifier identifies the lock who added the lock, the lock deleted when the judgment is not added their own that lock, if not not deleted.

Note: This implies a new problem, not their own judgment is added and release locks are two independent operations, not atomic, so we need to use Lua script to execute judgment and release the lock.

Third, improve the high availability distributed lock Redis

In large applications, general Redis services are clustered, master-slave replication, Cluster, etc., due to the Slave Master synchronous or asynchronous, so there will be client A lock on the Master, this time down Master, Slave not completed lock synchronization, Slave becomes Master, the client B can now complete lock operation, how to solve this problem?

Official gives Redlock algorithm, meaning roughly as follows:

In a distributed version of the algorithm where we assume we have N Redis Master nodes, which are completely independent, we do not have any copy or other distributed coordination algorithm implied (if you're on this program may Redis Cluster cluster not applicable, because the hash is based Redis Cluster groove (hash slot) assigned to the manner, evident distributed coordination algorithms on different nodes).

We put N is set to 5, so we need to run five master nodes on different computers or virtual machines to ensure they are in most cases not down at the same time. A client needs to do the following to get the lock:

1, acquires the current time (in milliseconds).

2, with the same key and turns random value (uniquely identifies the client) requests a lock on N nodes, in this step, the client requests a lock on each master, and have a total release time of the phase lock much smaller than the timeout. For example, if the automatic lock release time is 10 seconds, that each node lock request timeout may be in the range of 5-50 ms, this can prevent a client blocking too long on one master node shoot down, if a master node is not available, we should try next master node as soon as possible.

3, client computing second step it takes to obtain a lock, only when the client successfully obtained a lock on most of the master node (in this case three), and total time spent not more than lock release time, this that it is the lock acquisition a success.

4, if the lock acquisition is successful, it is now time to lock automatically released before the first lock release time minus consumed to obtain a lock.

5, if the lock acquisition failed, either because no lock to succeed, more than half (N / 2 + 1) or because the total elapsed time exceeds the lock release time, the client will be to release the lock on each master node, even he believes that those who did not succeed lock.

Although RedLock algorithm can solve the problem of high availability distributed lock Redis single point, but if there is a crash restart the cluster node occurs, or there will be security issues lock. Scene specific problems are as follows:

Suppose a total of A, B, C, D, E, 5 th Redis nodes contemplated following sequence of events occurs:

1, a client successfully locked A, B, C, successfully acquire the lock (but not locked D and E)

2, the node C crash restart, but the client 1 on C added no persistent lock down, missing

3, the node C after the restart, the client 2 locked C, D, E, successfully acquire the lock

In this way, Client 1 and Client 2 while access to the lock (for the same resource). For this scenario, the solution is very simple, is to make delay the restart after a crash Redis, and this delay is longer than the expiration time lock just fine. After this and other node restart, locks on all the nodes have been ineffective. There was no case of two client gets the same resource more than appeared.

Under special circumstances to achieve short Redis cluster distributed lock with more to be considered, especially in the case of more servers, need more testing.

Finally, a variety of language codes Redlock algorithm, interested friends can-depth study follows:

Redlock-py (Python implementation):

https://github.com/SPSCommerce/redlock-py

Redlock-php (PHP implementation):

https://github.com/ronnylt/redlock-php

PHPRedisMutex (PHP more complete implementation):

https://github.com/php-lock/lock#phpredismutex

Redsync.go (Go realization):

https://github.com/hjr265/redsync.go

Redisson (Java implementation):

https://github.com/redisson/redisson

Redis :: DistLock (Perl realization):

https://github.com/sbertrang/redis-distlock

Redlock-cpp (C ++ to achieve):

https://github.com/jacket-code/redlock-cpp

Redlock-cs (. C # / NET implementation):

https://github.com/kidfashion/redlock-cs

node-redlock (NodeJS 实现). Includes support for lock extension:

https://github.com/mike-marcacci/node-redlock

Summary: The need to choose for Redis distributed lock according to their actual situation is in the form of a stand-alone or highly available cluster

Third, the fact redis distributed lock availability

  The above program is built specifically for distributed lock redis redis clusters, in fact, we may just be a black box redis link from the inside on the main switch and the main library acquired from the node for the program did not exist, program just business.

So if you want to achieve the above distributed lock, but also with the support of dba.

Guess you like

Origin www.cnblogs.com/zenghansen/p/12450909.html