Redis correct way to achieve the correct distributed lock

Foreword

In a recent project they manage found redis locked the wrong way, there is a problem in the case of high concurrency. Therefore, search the Internet to find a handful of relevant information. We found that many are copying each other, many of which are flawed. Many still use the redis setnx order to achieve a distributed lock. In fact, redis the set command itself has been integrated functions setnx command, and it is also stronger than it. Here, I use redis-cli client lua script in conjunction with the native implementation redis distributed lock.

Prepare materials

  • redis-server
  • redis-cli

LUA's relationship with REDIS

From the beginning redis2.6.0, internal redis on the built-lua interpreter. lua is redis become the extension of a solution.
format:

eval scripts num [keys ...] [argv ...]
  • eval: lua script command execution in redis
  • scripts: lua script, do not necessarily have to be a function of lua
  • num: The number of keys, and the keys used to distinguish the argv; no keys, the write 0
  • keys: a variable array, generally used to mean redis key, the index starts
  • argv: variable array value representing redis general, the subscript 1 starts from

Redis interact with the lua

Two cases:

  • redis execute lua script: the use of eval command can be redis
  • lua & redis
    • receiving data sent from redis lua using KEYS SCRIPTS in the [] and ARGV []
    • lua call redis command, use the call in the SCRIPTS () or pcall ()
    • lua returns the results to redis, use return

Case Analysis

1. The use of a print parameter lua
127.0.0.1:6379> eval "return {KEYS[1],ARGV[1],ARGV[2]}" 3 key1 key2 first second threed
1) "key1"
2) "second"
3) "threed"

2. By setting the variable lua
# 设置一个 foo='hello' 键值对
127.0.0.1:6379> eval "return redis.call('set','foo','hello')" 0
OK
127.0.0.1:6379> scan 0
1) "0"
2) 1) "foo"
127.0.0.1:6379> get foo
"hello"
127.0.0.1:6379>
3. Set the variable parameter passing mode by lua
127.0.0.1:6379> eval "return redis.call('set',KEYS[1],ARGV[1])" 1 name Bob
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
"Bob"
127.0.0.1:6379>
4. The use of distributed lock disposed redis-cli
# 加锁 , 直接使用 set nx模式 【生产环境中123456 是一个唯一的随机数】
127.0.0.1:6379> set lock 123456 EX 40 NX
OK

# 解锁 , 结合 lua脚本
127.0.0.1:6379> eval "if redis.call('get','lock') == ARGV[1] then return  redis.call('del','lock') else return 0 end" 0 123456
(integer) 1

127.0.0.1:6379> get lock
(nil)

Way above the formatted lua script is as follows:

if redis.call('get','lock') == ARGV[1]
then
    return redis.call('del','lock')
else
    return 0
end

Guess you like

Origin www.cnblogs.com/yinguohai/p/11414779.html