赞
踩
推荐使用
nil 空
boolean 布尔值
number 数字
string 字符串
table 表
常用命令
不用携带类型
--- 全局变量
name = 'felord.cn'
--- 局部变量
local age = 18
注意事项
Redis脚本在实践中不要使用全局变量,局部变量效率更高。
转换成字符串
local bVar = false;
print(tostring(bVar)); -- 输出"false"
local num1 = 10;
local num2 = 10.0;
local num3 = 10.03;
print(tostring(num1)); --输出"10"
print(tostring(num2)); --输出"10"
print(tostring(num3)); --输出"10.03"
转换成数字
local num = tonumber("10"); -- 返回十进制数10
local num = tonumber("AF",16); -- 返回十六进制数175
local num = tonumber("0xA"); -- 返回10
常用命令
redis.call()和redis.pcall()
redis.call()在执行命令的过程中发生错误时,脚本会停止执行,并返回一个脚本错误,错误的输出信息会说明错误造成的原因;
redis.pcall() 出错时并不引发(raise)错误,而是返回一个带 err 域的 Lua 表(table),用于表示错误;
测试样例
类似Java遇到一个异常,前者会直接抛出一个异常;后者会把异常处理成JSON返回
redis> lpush foo a
(integer) 1
redis> eval "return redis.call('get', 'foo')" 0
(error) ERR Error running script (call to f_282297a0228f48cd3fc6a55de6316f31422f5d17): ERR Operation against a key holding the wrong kind of value
redis 127.0.0.1:6379> EVAL "return redis.pcall('get', 'foo')" 0
(error) ERR Operation against a key holding the wrong kind of value
内容介绍
Redis中使用EVAL命令来直接执行指定的Lua脚本。
语法介绍
EVAL luascript numkeys key [key ...] arg [arg ...]
EVAL:命令的关键字。
luascript:Lua 脚本。
numkeys:指定的Lua脚本需要处理键的数量,其实就是 key数组的长度。
key:传递给Lua脚本零到多个键,空格隔开,在Lua 脚本中通过 KEYS[INDEX]来获取对应的值,其中1 <= INDEX <= numkeys。键名参数 key [key …] 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1], KEYS[2], 以此类推)。
arg:是传递给脚本的零到多个附加参数,空格隔开,在Lua脚本中通过ARGV[INDEX]来获取对应的值,其中1 <= INDEX <= numkeys。命令的最后,那些不是键名参数的附加参数 arg [arg …],可以在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1], ARGV[2], 诸如此类)
功能描述
Redis + Lua实现限流
Lua脚本
-- 获取调用脚本时传入的第一个key值(用作限流的 key) local key = KEYS[1] -- 获取调用脚本时传入的第一个参数值(限流大小) local limit = tonumber(ARGV[1]) -- 获取计数器的限速区间 TTL local ttl = tonumber(ARGV[2]) -- 获取当前流量大小 local curentLimit = tonumber(redis.call('get', key) or "0") -- 是否超出限流 if curentLimit + 1 > limit then -- 返回(拒绝) return 0 else -- 没有超出 value + 1 redis.call("INCRBY", key, 1) -- 如果 key 中保存的并发计数为 0,说明当前是一个新的时间窗口,它的过期时间设置为窗口的过期时间 if (curentLimit == 0) then redis.call('EXPIRE', key, ttl) end -- 返回 (放行) return 1 end
流程分析
通过KEYS[1] 获取传入的key参数;
通过ARGV[1]获取传入的limit参数;
通过 ARGV[2] 获取限流区间 ttl;
redis.call方法,从缓存中get和key相关的值,如果为null那么就返回0;
接着判断缓存中记录的数值是否会大于限制大小,如果超出表示该被限流,返回0;
如果未超过,那么该key的缓存值+1,并设置过期时间为 ttl 秒钟以后,未限流。
jedis执行脚本
// 三个参数 1 脚本、2 key集合、3 arg集合
result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(String.valueOf(limit)));
Redis Lua脚本完全入门
https://segmentfault.com/a/1190000037518418
我司用了 6 年的 Redis 分布式限流器,可以说是非常厉害了!
https://mp.weixin.qq.com/s/kyFAWH3mVNJvurQDt4vchA
分布式限流:基于 Redis 实现
https://pandaychen.github.io/2020/09/21/A-DISTRIBUTE-GOREDIS-RATELIMITER-ANALYSIS/
redis lua运用
https://www.jianshu.com/p/f252de9b2d07
shield-ratelimter
https://github.com/TaXueWWL/shield-ratelimter
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。