我编写了一个php脚本,将数据从一个服务器(我们称之为服务器a)拉到另一个服务器(服务器b)。服务器A中的数据是一个redis列表,存储了所有需要在服务器B中写入的操作命令,例如:
["setex",["session:xxxx",604800,"xxxx"]]
["set",["uid:xxx","xxxxx"]]
["pipeline",[]]
["set",["uid:xxx","xxxxx"]]
["hIncrBy",["Signin:xxxx","totalTimes",1]]
["pipeline",[]]
....
我的php代码是:
while($i < 1000){
$line = $redis['server_a']->rpop('sync:op');
list($op,$params) = json_decode($line,1);
$r = call_user_func_array(array($redis['server_b'], $op), $params);
$i++;
}
有线的情况是,当call_user_func_array方法不正确地执行redis命令时,队列中的所有剩余命令都无法正确地写入服务器b。
我花了将近一个星期的时间在这个问题上寻找答案。经过数千次测试,我发现如果删除无法正确执行的“错误命令”,例如[“pipeline”,[]]行。所有其他命令都可以正确插入。所以它让我想起了一些redis事务问题。可能有一些机制,当一个命令在redis中执行不正确时,之后的所有其他命令都将被视为一个事务。所以我在while循环中添加了exec()命令:
while($i < 1000){
$line = $redis['server_a']->rpop('sync:op');
list($op,$params) = json_decode($line,1);
$r = call_user_func_array(array($redis['server_b'], $op), $params);
$redis['server_b']->exec(); //this is the significant update
$i++;
}
然后,我的问题解决了!!!!
我的问题是,有人能帮我解释一下redis的机制吗?我的假设正确吗?
最佳答案
您的库可能出于任何原因将事务用于流水线。pipeline
不是实际的redis命令,请参见http://redis.io/commands
只需去掉所有带有空参数的pipeline
命令,或者在之前发出->exec
时使用pipeline
。
关于php - 在php循环中将数据写入redis时发生了有趣的事情,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33735012/