<?php
//https://www.cnblogs.com/taijun/p/5007329.html
$redis = new Redis(); #实例化redis类
$redis->connect('127.0.0.1'); #连接服务器
$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
$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
scan
$it = 0;
while (true) {
// 匹配
$keys = $redis->rawCommand('SCAN', $it, 'MATCH', 'content_relate_topic_*', 'COUNT', 1000);
echo $keys[0] . PHP_EOL;
if ($keys === false || $keys[0] == 0) {
var_dump($keys);
break;
}
$it = $keys[0];
foreach ($keys[1] as $key) {
if (preg_match('/content_relate_topic_(\d+)/', $key, $match)) {
$str .= $match[1] . PHP_EOL;
$n++;
$relateTopic = $redis->get($key);
usleep(100);
if (trim($relateTopic,' #|')) {
$strNotEmpty .= $match[1] . PHP_EOL;
}
if ($n % 10000 == 0) {
file_put_contents($outFile, $str, FILE_APPEND);
file_put_contents($outFileNotEmpty, $strNotEmpty, FILE_APPEND);
$str = "";
$strNotEmpty = "";
$logStr = date('Y-m-d H:i:s') . ' -- ' . $n . PHP_EOL;
echo $logStr;
}
}
}
usleep(3000);
}
redis批量获取hash key的数据
PHP中使用redis执行lua脚本示例
redis中multi与pipeline介绍分析