Redis里面为什么要用脚本?
- 减少网络开销,一个脚本包含多个命令
- 原子操作, redis是单线程的,Redis的API是原子性的操作,所以一个脚本在Redis里面是作为一个整体执行,中途不会被插入其他操作,脚本本身就是事务,更简单,速度更快
- 可复用,客户端发送的脚步会永久存在redis中,这样,其他客户端可以复用这一脚本而不需要使用代码完成相同的逻辑
注意事项
- lua中不能使用block命令,否则会造成堵塞
Redis调用lua脚本语法
redis-cli方式
# KEYS和ARGV中间的 ',' 两边的空格,不能省略。
Redis-cli -h address -p port --eval path/to/redis.lua KEYS[1] KEYS[2] , ARGV[1] ARGV[2] ...
- --eval,告诉redis-cli读取并运行后面的lua脚本
- path/to/redis.lua,是lua脚本的位置
- KEYS[1] KEYS[2],是要操作的键,可以指定多个,在lua脚本中通过KEYS[1], KEYS[2]获取
- ARGV[1] ARGV[2],参数,在lua脚本中通过ARGV[1], ARGV[2]获取
redis命令模式
> EVAL script numkeys key [key ...] arg [arg ...]
- key代表要操作的rediskey
- arg可以传自定义的参数
- numkeys用来确定key有几个
- script就是你写的lua脚本
- lua脚本里面使用KEYS[1]和ARGV[1]来获取传递的key和arg
tips
- 在用eval命令的时候,可以注意到每次都要把执行的脚本发送过去,这样势必会有一定的网络开销,所以redis对lua脚本做了缓存,通过script load 和 evalsha实现
- script load命令会在redis服务器缓存你的lua脚本,并且返回脚本内容的SHA1校验和,然后通过evalsha 传递SHA1校验和来找到服务器缓存的脚本进行调用
- Redis 会把所有执行过的脚本都缓存在内存中,但是在重启的时候会释放掉之前保存的脚本
- Lua 脚本中的变量一定是本地变量,即变量前面加上 local 前缀:local var = 1;
- 通过 eval 带入的 ARGV 参数如果原来是数字的,会被转换为字符串,如果你的逻辑中需要判断该变量 > 0 或 < 0 之类的数字判断则必须进行字符串到数字的转换,使用 tonumber() 方法 if (tonumber(ARGV[1]) > 0) then return 1; end;
PHP使用示例
<?php
$redisHost = '127.0.0.1';
$redisPort = 6379;
//实例化redis类
$redis = new Redis();
$redis->connect($redisHost, $redisPort);
$lua = <<<SCRIPT
return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}
SCRIPT;
//对应的redis命令如下 eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
//2表示KEYS的值为前2个,剩下的参数为ARGV
$s = $redis->eval($lua,array('key1','key2','first','second'),2);
var_dump($s);
文章评论