Redis脚本Lua实现访问控制频率

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次

如有错误,请留言指出。

你可能感兴趣的:(Redis)