:::warning redis的脚本是什么 ::: Redis在2.6推出了脚本功能,允许开发者使用Lua语言编写脚本传到Redis中执行。使用脚本的好处如下:
- 减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。
- 原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入(java等客户端则会执行多次命令完成一个业务,违反了原子性操作)。
- 复用:客户端发送的脚本会永久存储在Redis中,意味着其他客户端可以复用这一脚本而不需要使用代码完成同样的逻辑。
:::warning redis的脚本基本用法 :::
// 执行脚本
EVAL script numkeys key [key …] arg [arg …]
|命令| 脚本 | 参数数量 | 参数列表 | 全局参数列表|
<< EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
>>
1) "key1"
2) "key2"
3) "first"
4) "second"
// 缓存脚本
SCRIPT LOAD script
| 命令 | 基本内容 |
<< SCRIPT LOAD "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}"
>> "a42059b356c875f0717db19a51f6aaca9ae659ea"
// 执行缓存脚本(相比直接执行的优点在于缩减命令内容,节省带宽,推荐使用)
EVALSHA SHA1 numkeys key [key …] arg [arg …]
|命令 |脚本值| 参数数量 | 参数列表 | 全局参数列表|
<< EVALSHA "a42059b356c875f0717db19a51f6aaca9ae659ea" 2 key1 key2 first second
// 其他
script exists SHA1 //判断脚本是否缓存
script flush //清除所有缓存
script kill //中断正在执行的脚本
:::warning 分布式锁场景下的使用 :::
-- 加锁脚本lock.lua
-- 如果获取锁成功,则返回 1
local key = KEYS[1]
local content = ARGV[1]
local ttl = tonumber(ARGV[2])
local lockSet = redis.call('setnx', key, content)
if lockSet == 1 then
redis.call('PEXPIRE', key, ttl)
else
-- 如果value相同,则认为是同一个线程的请求,则认为重入锁
local value = redis.call('get', key)
if(value == content) then
lockSet = 1;
redis.call('PEXPIRE', key, ttl)
end
end
return lockSet
eval lock.lua 1 userId:123 2 60000