- 论坛徽章:
- 0
|
Redis新分支,进行服务端lua脚本支持的开发
早在一年前,在Redis 的google group上就曾有人提出redis能不能提供诸如keya=kayb这样类似脚本语言的方法来操作数据。而最近Redis作者antirez同学连续发表的两篇博文将Redis执行脚本一事正式提到日程上来。
1 服务端执行脚本的好处:
按antirez同学的说法,Redis执行脚本有如下一些好处:
•能够上Redis更快!很多Redis应用的使用方式是read-compute-write模式,这使得一次简单的数据计算都需要客户端与服务端进行两次通信,而如果把中间的compute过程转移到服务端执行,则可以成倍地减少round-trip时间。
•充分利用CPU!Redis的绝大多数应用场景都是IO密集型,即使是到达CPU100%极限(Redis无法使用多核)的,CPU的使用也大多是在网络协议栈的处理上,但如果使用服务端执行的脚本,则可以充分将Redis Server的CPU利用起来。
•但最根本的原因在于:这样我们可以只在Redis中实现最基本的能够满足99%用户需求的功能,把其它独特应用场景下的1%的功能留给自定义的服务端执行脚本来实现。对于害怕Redis引入服务端脚本后变得冗余庞大的同学,看到这里可以舒一口气了,因为这就是为了防止满足无休止的需求而提出的终极解决方案。
2 如何实现
在考虑各个方案后,Redis采用了内嵌lua解释器的方式,lua语言是一种小巧灵活的语言,被广泛地嵌入在很多服务程序中,我们熟悉的人nginx-lua模块,tokyotyrant也支持lua的嵌入。
3 使用方法及例子
Redis的方案是客户端将lua脚本作为命令传给服务端,服务端读到脚本,调用解释器进行解释后进行执行并返回。如下例:
EVAL [ ... ]•EVAL:服务端执行脚本的命令
•body:lua脚本的内容
•num_keys_in_args:在后面的参数中,有几个是表示key的
•args…:参数,其中包括num_keys_in_args个key,剩下的是普通的参数
下面是几个作者提供的使用例子:
例1:直接返回keys和args
redis> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 arg1 arg2
1) "key1"
2) "key2"
3) "arg1"
4) "arg2"例2:lua的数据结构在Redis的返回中的形式
redis> eval "return 10" 0
(integer) 10
redis> eval "return 'foobar'" 0
"foobar"
redis> eval "return {1,2,'a','b'}" 0
1) (integer) 1
2) (integer) 2
3) "a"
4) "b"
redis> eval "return {err='Some Error'}" 0
(error) Some Error
redis> eval "return {ok='This is a status reply'}" 0
This is a status reply例3:用lua访问Redis存储数据
OK
redis> eval "return redis('get',KEYS[1])" 1 x
"foo"例4:一个真实的例子
# Conditional decrement.
#
# Decrement the value of a key only if the current value is greater than
# a specified value.
require 'rubygems'
require 'redis'
r = Redis.new
cond_decr = < tonumber(ARGV[1])
then
value = value - 1
redis('set',KEYS[1],value)
end
return value
LUA
r.set(,4)
5.times {
puts(r.eval(cond_decr,1,,0))
}
上面脚本的执行结果如下:
ruby cond-decr.rb
3
2
1
0
0
目前服务端脚本支持的分支已经在github上可以看到,有兴趣的同学可以试用一下。
相关链接:
Redis and scripting Scripting branch released
|
|