未分類

あなたのサイトは大丈夫?Redisの速度面の向上を考える

投稿日:

使用する環境

Redis 5.0.5

言語 PHP 5.5.18

phpredisモジュールを使用

CentOS 7.6.1810

VirtualBox 4.3.12

 

 

複数まとめて登録(mset)したほうがパフォーマンスが良いらしい

実際に検証してみる。

まずは、1件ずつのセットです。

「1件ずつのデータセットを1万回繰り返す」 という動作を100回繰り返しその平均タイムを出しています。

$times = 100;
for($count=1;$count<=$times;$count++){
    $time_start = microtime(true);
            $host = '127.0.0.1';
            $port = 6379;
            $r = new Redis();
            $r->connect($host, $port);
            for($i=1;$i<=10000;$i++){
            $r->set('key'.$i,'value'.$i);
            }
    $sum += microtime(true) - $time_start;
}
$ave = $sum / $times;
echo $ave;

 

今度は、複数のセットです。

ここでは、作成したKVを一度配列にまとめ、

それをまとめてRedisに登録しています。

$times = 100;
for($count=1;$count<=$times;$count++){
    $time_start = microtime(true);
            $host = '127.0.0.1';
            $port = 6379;
            $r = new Redis();
            $r->connect($host, $port);
            $regist = '';
            for($i=1;$i<=10000;$i++){
                $regist['key'.$i] = 'value'.$i;
            }
            $r->mSet($regist);
        $sum += microtime(true) - $time_start;
    }
    $ave = $sum / $times;
    echo $ave;

 

計測結果は、

1つずつセット

0.39885906934738(秒)

複数同時にセット

0.029414405822754(秒)

 

結果は、明らかですね笑

複数同時セットの方が10倍以上速いです。

Redisのパフォーマンスを生かすには、msetを利用する方が断然良いようです。

しかし、msetを使用するには問題があります。

それは、有効期限です。

Redisに登録するデータはあくまで一時的なもの。

基本的には、有効期限を設定する必要があるからです。

 

もし、1つずつ値をセットするのなら、有効期限を決めてセットするsetexコマンドというものがあります。

しかし、有効期限を決めて、複数のデータを登録するコマンド(msetex)はありません。

 

そのため、有効期限を決めてセットする場合には、

・setexで1つずつデータを登録するか

・msetでまとめて登録した後、expireで有効期限を設定するか

という方法があります。

 

しかし、これでは速度はあまり変わりそうにありません。

念のため、どちらでの登録が高速か、先ほどと同じ方法で計測してみます。

 

 

有効期限付きで、一つずつ登録する。

$times = 100;
for($count=1;$count<=$times;$count++){
    $time_start = microtime(true);
            $host = '127.0.0.1';
            $port = 6379;
            $r = new Redis();
            $r->connect($host, $port);
            for($i=1;$i<=10000;$i++){
             $r->setex('key'.$i,10,'value'.$i);
            }
    $sum += microtime(true) - $time_start;
}
$ave = $sum / $times;
echo $ave;

 

まとめて登録した後、一つずつ有効期限を設定する

$times = 100;
for($count=1;$count<=$times;$count++){
    $time_start = microtime(true);
            $host = '127.0.0.1';
            $port = 6379;
            $r = new Redis();
            $r->connect($host, $port);
            $regist = '';
            for($i=1;$i<=10000;$i++){
                $regist['key'.$i] = 'value'.$i;
            }
            $r->mSet($regist);
            for($i=1;$i<=10000;$i++){
                $r->expire('key'.$i, 10);
            }
        $sum += microtime(true) - $time_start;
    }
    $ave = $sum / $times;
    echo $ave;

 

計測結果は、

有効期限付きで、一つずつ登録する

0.41783607721329(秒

まとめて登録した後、一つずつ有効期限を設定する
0.43793610334396(秒)

という結果でした。

ほとんど変わらないですが、有効期限付きで一つずる登録したほうがわずかに速いようです。

うーん、これじゃあ、せっかくのパフォーマンスが生かせない。

 

結論

まとめてセットしたほうが速度は断然早いけれど、その速度を保ったまま有効期限を設定する方法が存在しない。

 

改善案

1 . hSetを使用し、複数データを一つにまとめ、それら全てを同じ有効期限で管理する。

2 . lua scriptを使用し、高速に処理できるmsetexコマンドを実装する。

 

1の方は、やってみましたが、データの扱いが難しく、多次元配列を使用していたこともあり、

後からデータを追加する場合には、サブキーで値を上書きしないように、

valueのみをJSONでエンコードし、登録するという動作をしていたために、

そのために使用していたforeachの処理で、結果として処理速度が落ちてしまったため、断念しました。

そもそも、複雑なデータをRedisに登録しようっていう考えが間違っているとは思うのだけど。

今度時間があるときに、2のパターンも試してみようと思います。

 

-未分類

Copyright© エンジニアの階段 , 2019 All Rights Reserved Powered by STINGER.