lua脚本有很多的优点,但是对于我来说我使用它只因为它能保证原子性。为什么它能保证原子性你就使用它呢?一个简单的例子,在我们的Java代码中,一个简单的++i都不能保证原子性更别提复杂的情况了。但是使用lua在执行几百行代码的情况下都不需要考虑高并发所带来的问题。
print("Hello World!")
a = 5 -- 全局变量local b = 5 -- 局部变量
if maxValue > limit then value = limit; else if value = maxValue; else value = 0; end
for i, v in ipairs(a) do print(i, v) --i是索引,且是从1开始的。v就是value了。end
function test(n) if n == 0 then return 1 else return -1 endend
看完以上几条你的基础其实已经过关了,如果仅仅在操作redis上的话就已经够了。
local value = redis.call('GET',key);redis.call('SET',key,value+2);redis.call('DECR',key);redis.call('EXPIRE',key,10);
你是否看明白了呢,只需要执行redis.call命令,第一个参数放入要执行的命令,后面的参数放入命令需要的参数就ok了。
redis-cli --eval redis-ratelimiter-counter.lua key limit , value1 value2
上方这段命令的意思呢,其实就是告诉redis:请你启动客户端的时候帮我执行一下redis-ratelimiter-counter.lua这个文件,然后呢,执行文件的话有这么几个参数,key、limit 、 value1、value2 细心小伙伴可能会有疑问了,为什么传了4个参数只有一个逗号其他都是空格隔开呢。我们来看一下他们分别是怎么获取的就明白了
local key = KEYS[1];local limit = KEYS[2];
local value1 = ARGV[1];local value2 = ARGV[2];
这样的话你是不是看明白了呢,逗号前后的参数是两种不同的传值方式而已。
@Autowired private RedisTemplate redisTemplate; public void counterConsume(String key, String limit, String lrefreshInterval) { DefaultRedisScript<Long> consumeRedisScript=new DefaultRedisScript(); consumeRedisScript.setResultType(Long.class); consumeRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("script/redis-ratelimiter-tokenBucket.lua")));//加载lua脚本文件 List<Object> keyList = new ArrayList(); keyList.add(key);//通过KEYS[1]取值 keyList.add(limit);//通过KEYS[2]取值 List<Object> argvList = new ArrayList(); argvList.add(lrefreshInterval);//通过ARGV[1]取值 String result=redisTemplate.execute(redisScript,keyList,argvList).toString(); }点击下方“阅读原文”查看源码!!!