PHP中用redis执行lua脚本和multi和pipeline比较

//$redis = new Redis(); #实例化redis类
$redis->connect('127.0.0.1'); #连接服务器

$lua = <<       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
$s = $redis->eval($lua,array('key1','key2','first','second'),2);
var_dump($s);

//解锁
$redis->del('lockkey');
$redis->set('lockkey','123');
$lock=['key'=>'lockkey','token'=>'123'];
var_dump(unlock($redis,$lock)); 
 

//批量获取hash的值
$redis->del('user:1','user:2','errKey');

$redis->hmset('user:1',["age"=>21,"name"=>"jack"]);
$redis->hset("user:2","age","22");
$redis->hset("user:2","name","tom");


$pipe = $redis->multi(Redis::PIPELINE);
$pipe->hgetAll('user:1');
$pipe->lpop('errKey');
$pipe->set('a',100);
$pipe->hgetAll('user:2');
$pipeResult = $pipe->exec();
var_dump('PJPELINE----',$pipeResult);
var_dump($redis->get('a'));

$pipe = $redis->multi(Redis::MULTI);

$pipe->hgetAll('user:1');
$pipe->lpop('errKey');
$pipe->set('a',200);
$pipe->hgetAll('user:2');
$pipeResult = $pipe->exec();
var_dump('MULTI----',$pipeResult);
var_dump($redis->get('a'));

$script="local rst={}; for i,v in pairs(KEYS) do rst[i]=redis.call('hgetall', v) end; return rst";
var_dump('LUA----',$redis->eval($script,['user:1','user:2'],2));

$redis->close(); #关闭连接

function unlock($redis,array $lock)
{
    $key = $lock['key'];
    $token    = $lock['token'];
    $script = '
        if redis.call("GET", KEYS[1]) == ARGV[1] then
            return redis.call("DEL", KEYS[1])
        else
            return 0
        end
    ';
    return $redis->eval($script, [$key, $token], 1);
}

说明:
lua
$redis->eval($lua,array('key1','key2','first','second'),2)执行的对应命令如下:
eval “return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}” 2 key1 key2 first second
解释: “return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}” 是被求值的 Lua 脚本,数字 2 指定了键名参数的数量, key1 和 key2 是键名参数,分别使用 KEYS[1] 和 KEYS[2] 访问,而最后的 first 和 second 则是附加参数,可以通过 ARGV[1] 和 ARGV[2] 访问它们。

PHP中使用redis拓展执行脚本时,eval方法的参数 3个,第一个是脚本代码,第二个是一个数组,参数数组,第三个参数是个整数,表示第二个参数中的前几个键名参数,剩下的都是附加参数

multi与pipeline流水线
Redis::MULTI方式会将命令逐条发给redis服务端,服务端缓冲。只有在需要使用事务时才选择Redis::MULTI方式,它可以保证发给redis的一系列命令以原子方式执行。但效率相应也是最低的。(不如连续发送多个执行快)

交互过程:tcpdump -i any port 6480 -A
$5
MULTI

OK

$3
GET
$1
a

QUEUED

$3
GET
$1
a

QUEUED

EXEC

$3
bbb
$3
bbb

Redis::PIPELINE方式,可以将一系列命令打包发给redis服务端,客户端缓冲,不保证这些命令原子执行。如果只是为了一下执行多条redis命令,无需事务和原子性,那么应该选用Redis::PIPELINE方式。代码的性能会有大幅度提升!

$3
GET
$1
a
*2
$3
GET
$1
a

$3
bbb
$3
bbb
 

你可能感兴趣的:(php)