<h3><span id="为什么要使用lua脚本">为什么要使用Lua脚本?</span></h3>
lua脚本有很多的优点,但是对于我来说我使用它只因为它能保证原子性。为什么它能保证原子性你就使用它呢?一个简单的例子,在我们的Java代码中,一个简单的++i都不能保证原子性更别提复杂的情况了。但是使用lua在执行几百行代码的情况下都不需要考虑高并发所带来的问题。
lua基础
- 创建lua脚本
就像创建其他的文档一样,新建一个以.lua为后缀的文档,比如说test.lua
- –单行注释。–[[多行注释,多行注释–]]
- 打印语句
- 常见数据类型
boolean、number、string、nil(这个就是我们平常见的null)
一些小的细节问题
· type() 用于查看变量的数据类型,比如print(type(10.4*3)) --> number
· 判断一个变量是否为空时应该使用" a"==“nil"而不是” a"==nil
· lua中"1"+“1” 不是合并字符串成ab而是等于2,想要进行字符串拼接需要"1"…“1” -->11
· lua查看字符串长度应该这样来print(#“Hello”) -->5
· lua中比较不等于的时候要这样比较:a~= b
· lua中逻辑运算符是and、or、not
- 变量
- 条件判断
1 2 3 4 5 6 7
| if maxValue > limit then value = limit; else if value = maxValue; else value = 0; end
|
- 循环
1 2 3
| for i, v in ipairs(a) do print(i, v) end
|
- 函数
1 2 3 4 5 6 7
| function (n) if n == 0 then return 1 else return -1 end end
|
看完以上几条你的基础其实已经过关了,如果仅仅在操作redis上的话就已经够了。
redis执行lua脚本
- 在脚本中如何与redis进行交互
1 2 3 4
| local value = redis.call('GET',key) redis.call('SET',key,value+2) redis.call('DECR',key) redis.call('EXPIRE',key,10)
|
你是否看明白了呢,只需要执行redis.call命令,第一个参数放入要执行的命令,后面的参数放入命令需要的参数就ok了。
- 如何执行脚本呢
1
| redis-cli --eval redis-ratelimiter-counter.lua key limit , value1 value2
|
上方这段命令的意思呢,其实就是告诉redis:请你启动客户端的时候帮我执行一下redis-ratelimiter-counter.lua这个文档,然后呢,执行文档的话有这么几个参数,key、limit 、 value1、value2
细心小伙伴可能会有疑问了,为什么传了4个参数只有一个逗号其他都是空格隔开呢。我们来看一下他们分别是怎么获取的就明白了
1 2 3 4 5
| local key = KEYS[1]; local limit = KEYS[2];
local value1 = ARGV[1]; local value2 = ARGV[2];
|
这样的话你是不是看明白了呢,逗号前后的参数是两种不同的传值方式而已。
- 如何在Java进程中执行lua呢
你只需要这样的一段代码就可以调用redis执行脚本redis-ratelimiter-tokenBucket.lua了
1 2 3 4 5 6 7 8 9 10 11 12 13
| @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"))); List<Object> keyList = new ArrayList(); keyList.add(key); keyList.add(limit); List<Object> argvList = new ArrayList(); argvList.add(lrefreshInterval); String result=redisTemplate.execute(redisScript,keyList,argvList).toString(); }
|
看到这里你对lua还有什么疑问么,感兴趣的话来看一下我是如何使用的吧:https://github.com/shiyujun/syj-ratelimit
本文出自http://shiyujun.cn,转载请保留。