Redis 6.x の Threaded I/O 対応雑感

2020/5/6 追記

  • ベンチマーク結果に mset / sadd / zadd / hset / lpush / lrange 300 を追加しました


Redis 6系がリリースされましたね!
mag.osdn.jp

やはり気になったのは「マルチスレッド対応」という文字。
Redisといえばシングルスレッドでしたが、今回の対応がどういうものか?パフォーマンスにどの程度影響するのか?が気になったので軽く調べてみました。


redis.confの説明文

redis.confTHREADED I/O の頁が追加されています。
要約するとあくまで I/Oアクセスをマルチスレッド化 する対応のようです。 1


スレッド化なし/あり時の実際のプロセスの様子

io-threads=1の時
f:id:toritori0318:20200506025518p:plain

io-threads>1の時
スレッド表示OFF f:id:toritori0318:20200506025523p:plain スレッド表示ON f:id:toritori0318:20200506025601p:plain

きちんとスレッド化されている様子がわかりますね!


ベンチマーク

簡易的なベンチマークを取ってみました。

環境

ロール OS インスタンスタイプ Redisバージョン
Redisサーバ AmazonLinux2 c5.2xlarge(8core) Redis 6.0.1
ベンチマーククライアント AmazonLinux2 c5.2xlarge(8core) Redis 6.0.1

OSチューニングしたところは ulimit / net.core.somaxconn くらいです。

ベンチマークコマンド

スレッド数8、パイプライン16並列でループ実行しました。

# get/set
redis-benchmark -t get,set -n 1000000 --threads 8 -P 16 --dbnum 1 -q -l

# mset
redis-benchmark -t mset -n 1000000 --threads 8 -P 16 --dbnum 1 -q -l

# sadd
redis-benchmark -t sadd -n 1000000 --threads 8 -P 16 --dbnum 1 -q -l

# zadd
redis-benchmark --threads 8 --dbnum 1 -q -l -n 1000000 --threads 8 -P 16 -r 1000000 zadd myzset __rand_int__ member:__rand_int__

# hset
redis-benchmark --threads 8 --dbnum 1 -q -l -n 1000000 --threads 8 -P 16 -r 1000000 hset myhash field:__rand_int__ value:__rand_int__

# lpush
redis-benchmark --threads 8 --dbnum 1 -q -l -n 1000000 --threads 8 -P 16 -r 1000000 lpush mylist __rand_int__

# lrange_300
redis-benchmark -t lrange_300 -n 1000000 --threads 8 -P 16 --dbnum 1 -q -l

サーバ起動コマンド

io-threadsの数値を変えて比較してみました。 2

redis-server --protected-mode no --io-threads <num>

結果

ループで10回程度回したrps平均値です。

Redisサーバスレッド数 get set mset sadd zadd hset lpush lrange_300
1 1,155,995 1,344,768 347,639 1,283,881 259,651 799,513 1,036,402 53,091
2 1,196,952 1,415,721 351,426 1,337,262 261,772 837,762 1,100,286 53,603
4 1,232,383 1,500,202 355,968 1,397,251 267,699 853,392 1,130,196 53,930
6 985,922 1,227,587 193,678 1,277,302 239,738 618,960 1,085,098 27,358

4スレッドくらいまでは順調にパフォーマンス上がっていますが、6スレッドでは逆に性能劣化していますね。。
スレッドの増やし過ぎもよく無さそうです。

redis.confの説明では

By default threading is disabled, we suggest enabling it only in machines that have at least 4 or more cores, leaving at least one spare core.  
Using more than 8 threads is unlikely to help much. 
We also recommend using threaded I/O only if you actually have performance problems, 
with Redis instances being able to use a quite big percentage of CPU time, otherwise there is no point in using this feature.

とありますので、よく考えて設定する必要がありそうです。


まとめ

スレッド化することによりパフォーマンスの向上がみられました。
ただし単純に増やせば良いものでも無さそうなので、実際にスレッドI/Oを利用するときにはきちんと性能評価を行った方が良いでしょう。



  1. つまり計算量過多による挙動は変わりません。試しにスレッドを有効にして大量の keys * 実行後に他オペレーションがブロックされるかどうか確認してみましたが、やはり今まで通りブロックされました。

  2. ちなみに redis.confの io-threads の値を変えて試してみたんですが実際に反映しないような気が…?