1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel】Redis::pipelineが爆速だったメモ

Posted at

最近業務の一貫で他エンジニアのコードレビューをしている時にコメントした件を備忘録として残しておく。

自身が所属するプロジェクトでは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サーバーに対して適切なキーリストを渡してあげることかなと思います。

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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?