Redis 脚本功能可以自定义新的命令,并且也是原子执行。
本篇和上一篇是相对应的。
一、简单介绍下脚本:
redis2.6推出脚本功能,允许开发者使用 Lua语言编写脚本传到Redis中执行,在Lua脚本中可以调用大部分redis命令。
- 使用脚本优点:
- 减少网络开销:执行一次脚本只需要发送一次请求,减少网络往返时延。如果不使用脚本,可能多个命令要发送多个请求,还会出现竞态情况。
- 原子操作:Redis会将脚本作为一个整体执行,中间不会被其他事务插入。编写脚本过程中无须考虑竞态条件,也无须使用事务。事务可以完成的所有功能都可以通过脚本实现。
- 复用:客户端发送的脚本会永久存储在Redis 中,意味着其他客户端可以复用这段脚本。
二、使用脚本实现访问频率限制,
- 方案一:
Lua代码如下:
-- Lua 使用 redis.call()调用redis命令
local times = redis.call('incr', KEYS[1])
if times == 1 then
-- KEYS[1] 键刚刚创建,所以为其设置生存时间
redis.call('expire', KEYS[1], ARGV[1])
end
if times > tonumber(ARGV[2]) then -- ARGV[2]为字符串,需要转为number
return 0
end
return 1
执行脚本:
$ redis-cli –eval /path/to/ratelimiting.lua rate.limiting:127.0.0.1 , 10 3
参数说明:
–eval:告诉redis-cli 读取并运行后面的Lua脚本。
/path/to/ratelimiting.lua : 文件位置
rate.limiting:userId 要操作的key,在脚本中用 KEYS[1]获取
10 3 :两个参数,在脚本中用 ARGV[1]和ARGV[2] 获取
注意:”,” 两边的空格不能省。
- 方案二:
Lua代码如下:
local limitLen = redis.call('llen', KEYS[1])
if limitLen < tonumber(ARGV[2]) then
redis.call('lpush', KEYS[1], os.time())
else
local times = redis.call('lindex', KEYS[1], -1)
if os.time() - times < ARGV[1] then
return 0
else
redis.call('lpush', KEYS[1], os.time())
redis.call('ltrim', KEYS[1], 0, ARGV[2])
end
end
return 1
执行脚本:
$ redis-cli –eval /path/to/ratelimiting.lua rate.limiting:127.0.0.1 , 10 3
rate.limiting:127.0.0.1 这个key 每10 秒最多访问3次
如有错误,请留言指出。