前几天同事遇到一个更新 redis 失败的问题,我觉得很有意思,背后的技术细节也可以深入挖掘,所以通过本文做个记录。我本人对这个问题也有很多的疑点,希望阅读此文的读者能够解答。
代码功能和实现也非常简单:
$ip = "localhost";
$port = 24362;
$socket=fsockopen($ip,$port,$errno, $errstr);
$t1 = microtime(true);
$line="";
$arr = range(1,1000);
foreach($arr as $K=>$t){
$line="lpush send_mass_mailx {$row}\r\n";
$bool = fwrite($socket,$line);
if ($bool === false) {
echo $t . "_error\n" ;
exit; } }
fclose($socket);
$t2 = microtime(true);
echo '耗时'.round($t2-$t1,4).'秒';
通过上述代码可以看出,功能就是循环向 reids 队列插入数据,遇到的问题就是:通过 llen send_mass_mailx
命令发现大概 990 ~ 1000 之间的数据总是插入不成功。
自己当时并不知道背后的原因,但是从代码严谨性的角度(没有对 redis 服务器的响应进行判断,所以代码无法知晓数据是否成功插入 redis 队列)考虑,我修改了下代码:
$ip = "localhost";
$port = 24362;
$socket=fsockopen($ip,$port,$errno, $errstr);
$t1 = microtime(true);
$line="";
$arr = range(1,1000);
foreach($arr as $K=>$t){
$line="lpush send_mass_mailx {$row}\r\n";
$bool = fwrite($socket,$line);
if ($bool === false) {
echo $t . "_error\n" ;
exit;
}
$m = fgets($socket,200);
echo $m "\n"
}
fclose($socket);
$t2 = microtime(true);
echo '耗时'.round($t2-$t1,4).'秒';
两个代码片段之间差异很小(第二个代码增加了 fgets 操作),但带来的结果却完全不同:第二个代码不但成功运行,而且向 redis 队列成功插入了 1000 个值。
背后的原因在哪儿?
可能很多人问,为什么不用一些 PHP redis 封装库呢,不管从那个角度看使用封装库是一个正确的决定,但是、本文是为了分析问题,从另外个角度了解事情的背后原理。