redis运行lua脚本


redis.call() 和 redis.pcall()
当 redis.call() 在执行命令的过程中发生错误时,脚本会停止执行,并返回一个脚本错误,错误的输出信息会说明错误造成的原因:
和 redis.call() 不同, redis.pcall() 出错时并不引发(raise)错误,而是返回一个带 err 域的 Lua 表(table),用于表示错误:

例子:
EVAL script numkeys key [key …] arg [arg …]
EVAL “return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}” 2 key1 key2 first second
EVAL “return ARGV[1]” 0 value1
EVAL “redis.call(‘SET’, KEYS[1], ARGV[1]);redis.call(‘EXPIRE’, KEYS[1], ARGV[2]); return 1;” 1 userAge 10 60

SCRIPT LOAD script
EVALSHA sha1 numkeys key [key …] arg [arg …]
SCRIPT LOAD 将脚本 script 添加到Redis服务器的脚本缓存中,并不立即执行这个脚本,而是会立即对输入的脚本进行求值。并返回给定脚本的 SHA1 校验和。如果给定的脚本已经在缓存里面了,那么不执行任何操作。
在脚本被加入到缓存之后,在任何客户端通过EVALSHA命令,可以使用脚本的 SHA1 校验和来调用这个脚本。脚本可以在缓存中保留无限长的时间,直到执行SCRIPT FLUSH为止。
SCRIPT EXISTS sha1 [sha1 …]
SCRIPT FLUSH
清除Redis服务端所有 Lua 脚本缓存

I、编写Lua脚本文件测试例子1:
local key = KEYS[1]
local val = redis.call(“GET”, key);

if val == ARGV[1]
then
        redis.call(‘SET’, KEYS[1], ARGV[2])
        return 1
else
        return 0
end

redis-cli -a 密码 –eval Lua脚本路径 key [key …] ,  arg [arg …]

II、统计ip超限脚本实例测试例子2:

local visitNum = redis.call(‘incr’, KEYS[1])

if visitNum == 1 then
        redis.call(‘expire’, KEYS[1], ARGV[1])
end

if visitNum > tonumber(ARGV[2]) then
        return 0
end

return 1;

III、领券脚本逻辑:测试例子3
–redis keys
local user_today_got_key = KEYS[1]; –Lua下表从1开始
local user_got_key = KEYS[2];
local total_got_key = KEYS[3];
–redis args
local user_per_day_max = tonumber(ARGV[1]);
local user_max = tonumber(ARGV[2]);
local max = tonumber(ARGV[3]);
local userId = ARGV[4];
local couponId = ARGV[5];

— 用户每天可领券的最大数量
local user_today_got = redis.call(“hget”, user_today_got_key, userId);
if(user_today_got and tonumber(user_today_got) >= user_per_day_max) then
    return 1; –fail
end

— 用户可领券的最大数量
local user_got = redis.call(“hget”,user_got_key,couponId);
if(user_got and tonumber(user_got) >= user_max) then
    return 2; –fail
end

— 券的最大数量
local total_got = redis.call(“hget”,total_got_key,couponId);
if(total_got and tonumber(total_got) >= max) then
    return 3; –fail
end

redis.call(“hincrby”,user_today_got_key, userId,1);
redis.call(“hincrby”,user_got_key, couponId,1);
redis.call(“hincrby”,total_got_key, couponId,1);
return 0; — success


发表评论

您的电子邮箱地址不会被公开。