Redis lock to unlock the correct posture

redis php is a good friend, write business processes, sometimes using the concept of a lock in php, while only one person may operate an action. This time we have to use locks. There are several ways lock, php not in memory with the lock, the lock can not be used zookeeper, make use of the database lock and consume relatively large, this time we will generally choose to do redis lock mechanism.

 

setnx

Redis lock in the most simple data structure that string. The first time, the lock operation is generally used setnx, when this command is: lock does not exist when a set val, perhaps you will remember to increase the use of locks expire expired, unlocking operation is to use the del command, pseudo-code is as follows:

if (Redis::setnx("my:lock", 1)) { Redis::expire("my:lock", 10); // ... do something Redis::del("my:lock") }

In fact, here is a problem, the problem lies in the middle setnx and expire if they crash and other acts, maybe this lock will not be released. Further optimization may then be stored in the lock and timestamp. Determining the length of the timestamp.

 

set

Official recommendations now directly  set  to achieve lock. We can use the set command to replace setnx, that looks like this

if (Redis::set("my:lock", 1, "nx", "ex", 10)) {
    ... do something

    Redis::del("my:lock")
}

The above code my: lock is set to 1 if and only when the lock is not present, after setting the expiration time of 10 setup is complete.

It is to acquire the lock mechanism, but the mechanism of direct use del to delete lock is wrong. Because that could lead to accidental deletion someone else's lock.

For example, the lock on my 10s, but I deal with time longer than 10s, to the 10s, the lock automatically expire, and others were taken away and locked it up again. So this time, I again call Redis :: del delete lock is established by the people.

Official unlock command is also recommended, recommended to use lua script, first performed get, then del

Program becomes:

$token = rand(1, 100000);

function lock() {
    return Redis::set("my:lock", $token, "nx", "ex", 10);
}

function unlock() {
    $script = `
if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end    
    `
    return Redis::eval($script, "my:lock", $token)
}

if (lock()) {
    // do something

    unlock();
}

token here is a random number when the lock when, to my redis of: lock in existence is the token, unlock when the first get what lock the token, if, and I want to delete the token is consistent explanation this lock is set before me, otherwise, it indicates that the lock has expired, others set, I should not do anything to it.

So: Do ​​not use setnx, directly set were achieved lock.

Guess you like

Origin www.cnblogs.com/yszr/p/11525762.html