一、Lua和Redis
这篇其实和Redis本身的源码关系不是太大了,主要是看一下对REDIS的支持。Lua可能好多人都没有听说过,但是如果搞过网游的人,估计都用过,做为一种胶水语言,Lua对C/C++的支持非常友好,这是一般的脚本语言都没有做到的。它很小很轻量,所以非常容易与其它程序集成。在魔兽和仙剑等游戏中都广泛使用。
Lua的缺点也很明显,对开发支持的力度不大,功能也少,功能少,就意味着如果搞复杂或者大的东西需要自己实现轮子。
二、运行机制
引入LUA的本质还是要提高REDIS的功能强度。在REDIS中,使用单线程调用执行LUA脚本,保证整个脚本的运行期间不会被其它请示中断。在脚本出现错误或者异常问题时,通过pcall方法来实现异常的控制。另外,假如在LUA脚本中由于编写错误引起的死循环等,都可以通过指令将其杀死,而不会引起对REDIS的整体的漫延侵蚀。
为了实现对LUA的支持,REDIS提供了相关的命令操作主要有:
EVAL 直接加载执行脚本
EVALSHA 执行缓存的脚本
SCRIPT LOAD 加载脚本到服务器缓存,但不执行
SCRIPT EXISTS 校验脚本的存在性
SCRIPT FLUSH 脚本缓存
SCRIPT KILL 杀死运行脚本,无写操作时
三、开发和应用
在REDIS中,LUA应用场景非常丰富:
1、使用脚本可以进行类似批处理的操作,减少网络开销。
2、保持整个命令操作的一致性。
3、减少重复造轮子。脚本可以复用。
看一个小例子:
local num = redis.call('incr', KEYS[1])
if num == 1 then
redis.call('expire', KEYS[1], ARGV[1])
end
if num > tonumber(ARGV[2]) then
return 0
end
return 1;
执行这个小脚本:
redis-cli -a 123456 --eval ./mySet.lua LimitIP:127.0.0.1 , 10 5 //注意:逗号前后各有一个空格
运行结果:
# redis-cli--eval ratelimiting.lua rate.limitingl:127.0.0.1 , 10 5
(integer) 1
# redis-cli--eval ratelimiting.lua rate.limitingl:127.0.0.1 , 10 5
(integer) 0
其实就是限制访问频率在两秒一次,大于这个返回0,否则为1.
是不是很简单,但真用起来,可就不简单了。LUA写得稍微复杂,还是不好调试错误,这也算是一个小缺憾。
四、总结
本篇做为整个REDIS源码学习的末尾一篇,不是学习Lua的,重点是讲LUA和Redis是如何配合提高工作效率的,正如做饭,一份简单的调料会让食材发生天翻地覆的味道的转化。善其事,必先利其器也是同样的道理。