【Laravel】我记下了Redis::pipeline非常快速的笔记

最近,我在业务中负责对其他工程师的代码进行了评论,在此将其作为备忘录保存下来。

在我所属的项目中,我们使用PHP × Laravel,并且这次有以下的实施要求。
将多个列表类型的键设置到Redis中。

然后进行了如下实施。

foreach($key_map as $key => $value) {
   Redis::lpush($key, $value);
   Redis::expire($key, self::CACHE_EXPIRE_TIME);
}

如果你认为可以正常运行,而且不需要担心性能的话,就可以不去理会,但既然有机会,那么可以去看一下Laravel官方文档( https://readouble.com/laravel/5.4/ja/redis.html ),上面有这样的命令。

如果需要在一次操作中向服务器发送多个命令,应该使用管道。pipeline方法接受一个参数,并返回一个“闭包”,该闭包接受Redis实例。您可以使用此Redis实例发出所有命令,并且可以在一次操作中将它们全部执行完成。

Redis::pipeline(function ($pipe) {
    for ($i = 0; $i < 1000; $i++) {
        $pipe->set("key:$i", $i);
    }
});

嗯嗯,实例内发出所有命令并在一次操作中全部执行,确实看起来性能不错。

就这样,随便创造一个artisan命令并试一试。
这样做看起来像这样。

        // 直接
        $startTime = microtime(true);
        for ($i = 0; $i < $count; $i++) {
            Redis::lpush('test_key' . $i, 'hoge');
        }
        $runningTime =  microtime(true) - $startTime;
        var_dump('straight running time: ' . $runningTime . ' [s]');

        // pipeline
        $startTime = microtime(true);
        $redis = Redis::connection('redis_0');
        $redis->pipeline(function ($pipe) use($count) {
            for ($i = 0; $i < $count; $i++) {
                $pipe->lpush('test_key_pipeline' . $i, 'hoge');
            }
        });
        $runningTime =  microtime(true) - $startTime;
        var_dump('pipeline running time: ' . $runningTime . ' [s]');

↓↓结果↓↓

// 10件一括
# php artisan redis_test 10
string(42) "straight running time: 0.0122230052948 [s]"
string(46) "pipeline running time: 0.00022292137145996 [s]"

// 1000件一括
# php artisan redis_test 1000
string(43) "straight running time: 0.15764403343201 [s]"
string(45) "pipeline running time: 0.0015499591827393 [s]"

从性能来看,大约提高了100倍。似乎没有使用的理由。因为set等原本就可以原子性地执行,所以不需要使用,但是在需要批量执行的情况下,可以考虑使用列表或哈希类型。

当有多个Redis服务器时,需要注意的是因为同样的命令会发送到所有服务器,可能会出现浪费的情况,所以可以根据连接将其分组,并为每个Redis服务器传递适当的键列表。

我将继续努力学习。