使用する環境
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のパターンも試してみようと思います。