Help us understand the problem. What is going on with this article?

【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複数台ある時は、全部に同じコマンドが発行されて無駄が出たりするので、
手前でconnectionごとにグルーピングして、それぞれのRedisサーバーに対して適切なキーリストを渡してあげることかなと思います。

これからも勉学に励みます。

kitaji_ngzk
元広告営業、今はサーバーサイドエンジニアに転生した 扱ってる言語は主にPHP 現在インフラも勉強中
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away