redis执行lua脚本的实现
作者:lx18854869896
redis EVAL命令可以执行lua脚本,redis保证脚本执行的原子性,脚本由嵌入式执行引擎(Lua 5.1解释器)执行。
1,语法
EVAL script numkeys [key [key ...]] [arg [arg ...]]
第一个参数 script 是脚本的源代码
第二个参数 numkeys 是输入键名参数的数量
后面的就是 key 和 参数。
例如:
> EVAL "return 'Hello, scripting!'" 0 "Hello, scripting!"
其中 "return 'Hello, scripting!'" 就是lua脚本,后面的0就是没有key 也没有参数,可以看到redis返回的就是脚本的返回值。
还有一种方式就是 写一个固定的脚本传递参数,比如
> EVAL "return ARGV[1]" 0 'hello scripting' "hello scripting" > EVAL "return ARGV[1]" 0 hello scripting "hello" > EVAL "return ARGV[3]" 0 hello scripting (nil)
可以看到是从[1] 开始获取,而不是[0],参数是以空格隔开,如果超出范围返回nil。
一个使用key的例子
> EVAL "return { KEYS[1], KEYS[2], ARGV[1], ARGV[2], ARGV[3] }" 2 key1 key2 arg1 arg2 arg3 1) "key1" 2) "key2" 3) "arg1" 4) "arg2" 5) "arg3"
可以看到这个lua脚本可以使用{}返回多个值。不知道这个在java 里面返回的是个字符串还是list。
2,调用redis命令
可以通过 redis.call() 或 redis.pcall() 从Lua脚本调用Redis命令。两者几乎相同,除了调用 redis.call() 函数时产生的错误会直接返回到执行该函数的客户端。相反,调用 redis.pcall() 函数时遇到的错误会返回到脚本的执行上下文。
例子:
> EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 foo bar OK
简单的调用了一个set命令,看起来没有意义,但是多了可以保证原子性就有意义了,比如
> EVAL "local a=redis.call('SET',KEYS[1],ARGV[1]) local b=redis.call('SET',KEYS[2],ARGV[2]) return a and b" 2 k1 k2 v1 v2 OK
3,脚本缓存
> SCRIPT LOAD "return 'Immabe a cached script'" "c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f" > EVALSHA c664a3bf70bd1d45c4284ffebb65a6f2299bfc9f 0 "Immabe a cached script"
可以看到使用script load 缓存一个脚本,返回一个ID,之后可以通过evalsha ID 来调用它。
至于lua脚本语言这个东西,摸索着写写就熟悉了。举几个例子:
获取并删除
local value = redis.call('get', KEYS[1]) if value then redis.call('del', KEYS[1]) return value else return nil end
解释,定义一个变量value如果获取到了keys[1]的值,就是删除这个值并返回OK否则返回nil,还可以写成
if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end
看起来跟shell脚本差不多吧。
到此这篇关于redis执行lua脚本的实现的文章就介绍到这了,更多相关redis执行lua脚本内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!