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