EVAL格式为EVAL script numkeys key [key ...] arg [arg ...]
script是脚本内容,用双引号标记,numkeys 为全局变量KEYS的个数,KEYS数组从1开始,key为键值多个用空格隔开,arg为附加参数,用ARGV代表,取值也从1开始
eval "return {1,2,{3,'helo world'}}" 0
以上语句对应的script内容为双引号里面的内容即“return{1,2,{3,'hello world'}}”,这里面脚本内容没有用到键名参数KEYS,所以后面的键名参数数量numkeys数量为0,注意没有键值参数必须输入0不然会报错,执行结果为
下面看一下带有键名参数和附加参数的命令
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
可以看到script内容为“return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}”,键名参数为"KEYS[1]","KEYS[2]",所以键名参数numkeys数量为2,然后KEYS[1]和KEYS[2]对应的值分别为key1和key2,附加参数为"ARGV[1]","ARGV[2]",对应的值分别为first和second,执行结果为
这个是官方的例子,为了区分开我执行另外一个结果验证一下,可以看出键值都变了
接下来测试一下在lua中执行redis命令获取redis对应的info信息
eval "return redis.call('info')" 0
以上语句可以看到script内容为“eval "return redis.call('info')" ,因为没有键名参数所以numkeys值为0
看一下结果
感觉这个结果好乱,那我们直接执行info server 获取info信息中的服务节点信息
eval "return redis.call('INFO','SERVER')" 0
这里记得用逗号隔开,我们在不使用eval输入命令时是"info server"这样,但是redis.call需要使用逗号隔开,执行结果如下
最后我们执行多个节点命令并使用多个键名参数
eval "return {redis.call(KEYS[1],KEYS[2]),redis.call(KEYS[3],KEYS[4]) }" 4 INFO SERVER INFO MEMORY
执行结果为
这里建议使用键名参数代替直接写值,原因有以下几点
1. EVAL 命令要求你在每次执行脚本的时候都发送一次脚本主体(script body)。Redis 有一个内部的缓存机制,因此它不会每次都重新编译脚本。
2. 使用正确的格式来传递键名参数和附加参数很重要:因为如果将参数硬写在脚本中,那么每次当参数改变的时候都要重新发送脚本,但是如果通过使用正确的格式来传递键名参数和附加参数,就可以在脚本主体不变的情况下,直接使用 EVALSHA 命令对脚本进行复用,免去了无谓的带宽消耗,提高性能。