いまさらGoでElasticache Redisの負荷・障害試験をがっつりしてみた

こんにちは、
株式会社アプリボット、バックエンドエンジニアの小川詩織です。

今回はgolangで開発中の新規プロジェクトのため、ElasticacheRedisに関する検証を行いました。
かなり長くなってしまいましたが、参考にしていただければ幸いです。

以下、検証内容になります。

まえおき

検証のための実装にはgolangを用い、
go-redisによるElasticache Redisについての検証になります。

また、ゲームで良く活用される Ranking機能 の実装を想定した検証を行いました。
Ranking機能実装のためにRedisは ソート済みセット型 を用います。

Ranking機能についての想定なので、同一ランキングはkeyも同一になり、
Shardを増やしても負荷分散できないため全て Shard=1 として検証を行います。
また、Redisの 要素数は1000万件 用意しました。

Ranking機能として主に備えた機能は以下の通りです。

  • Set : 1件保存 ZADD
  • Get : 1つのelementに対して1件取得 ZSCORE+ZCOUNT
  • Find : 複数取得(複数のelementで ZSCORE+ZCOUNTをPIPEで複数回 )
  • FindByOrder : ソートされたランキングの始まりと終わりを指定して複数件一括取得 ZREVRANGE+ZCOUNT

c5.2xlargeのEC2からElasticacheに負荷を掛けます。
EC2には、EC2のCPU使用率がボトルネックにならない程度のspecとしてc5.2xlargeを用意しました。

本記事では
複数条件によって負荷状況を記録したものが負荷検証、
負荷を掛けながらClusterを落とすなどの障害を人為的に起こし挙動を確認したものが障害検証としています。

クラスタモードについての前提知識

今回クラスタモードに関しての設定は以下の通りです。

上記設定の時、ノードについてPrimaryとReplicaが存在する場合、

  • データ保存(Set) :Primary
  • データ取得(GetやFind, FindByOrder):Replica

と、PrimaryとReplicaでリクエストが分けて送られ、負荷が分散されているようになっています。

やや注意が必要なのが
上記の通りReplicaが存在する時、SetリクエストはReplicaへ行きませんが、
Primaryのデータを非同期的にReplicaへ反映するため、Primary・Replicaノード両方にレプリケーションコストは掛かります。

負荷検証

特に言及が無い限り、Findでは100件、FindByOrderではランダムな開始位置から100件取得します。

検証を行ったパターンは以下の通りです。

  1. 非クラスタモード(replica=0)での Redis インスタンスタイプでの比較検証
  2. クラスタモードで Replica数を1, 2, 4 とした時の比較検証
  3. クラスタモードでReplica=1とした時、保存するデータの scoreの分散値を100or10万件 にした時の比較検証
  4. クラスタモードでReplica=1とした時、 Findする件数を20件or100件 にした時の比較検証

クラスタモードの時、分散は均等分散とし、同じAZにReplicaを配置しています。

上から順に検証結果を示します。

1. 非クラスタモード(replica=0)でのRedis インスタンスタイプでの比較検証

レプリケーションを行わない非クラスタモードでのConfigの設定は以下の通りです。

比較したインスタンスタイプは r5.large , r5.xlarge , m5.large の3つです。
それぞれのSet, Get, Find, FindByOrderについてインスタントタイプ以外は同条件で20分ずつ負荷を掛けました。
その結果は以下の様になりました。
(RPS [Request Per Sec.] は1秒あたりのSet, Get, Find, FindByOrderの平均実行回数、送受信byteに関しては1分あたりの平均値を記載)

RedisのCPU使用率はほぼ100%に張り付いているため、
概ね性能は等しく使い切っている値であると考えられます。
上記のデータを使い、各RPSをインスタンスタイプごとに比較した図を以下に示します。

結果

各インスタンスタイプについて、rシリーズとmシリーズに大きな差は見られませんでしたが、
ややmシリーズの方が性能を発揮する結果となりました。
r5.largeとr5.xlargeについては素直に想定通り処理性能は上昇しましたが、Get以外には大きな上昇は見られません。

2. クラスタモードでReplica数を1, 2, 4とした時の比較検証

ここでの負荷試験ではReplica数を変更して検証を行いました。
クラスタモードの設定については、まえおきで記載した通りです。

結果を順に記載します。
また、結果には参考として非クラスタモード(Replica=0)の時のデータも併載しています。
Set以外にはPrimaryのデータの記載がありませんが、
これはデータ取得の場合はPrimaryにリクエストが行かないため、
CPU使用率等にも影響せず、「取得タイプのコマンドカウント」を見ても0なので除外します。


まえおきのクラスタモードの前提で述べた通り、SetではPrimaryにしかリクエストが行かないものの、
恐らくレプリケーションするためにReplicaの「CPU使用率」と「Redis受信byte」が上昇していることが分かります。
同様の理由でPrimaryでは「Redis送信byte」が「Redis受信byte」と同じ程度には上昇しています。

Replica数を増やしても、Primaryノードはレプリケーションコストが増すため、
PRSは微量ではあるが下がっていくことが分かります。


※Replica=4のケースでは「EC2のCPU使用率」が先に上限まで届いてしまい、
Redisが性能を活かし切る事無く75%程度で止まってしまったのでRPSはやや低めの値になります。


※Replica=4のケースでは「RedisCPU使用率」が余力ある形となってしまったので
RPSはやや低めの値となっています。

上記の通り、多少CPU使用率によって条件に差はあるものの、Replicaの数とRPSの関係についてまとめた表を以下に示します。
 
 

Replica数が3の場合の値がないので、やや誤解を生む斜線になってしまっていますが、
Replica数を増やすと概ね安定して比例的な上昇が見られる事が分かります。
(特にCPU上限の影響をほぼ受けていないSetとFindのグラフでは分かりやすい)

結果

Setに関してはReplica数を増やすとレプリケーションコストが増すのでパフォーマンスは落ちます。
取得に関しては、Replica数を増やすと安定して比例的な上昇が見られ、他に大きな影響を受ける要素は無い事が分かります。

3. クラスタモードでReplica=1とした時、保存するデータのscoreの分散値を100or10万件にした時の比較検証

ランキングの想定的には
scoreの分散を多くすると、スコアが散らばっており、
scoreの分散を少なくすると、ランキングが上位にほぼ集まっている状況が想定されます。

scoreの分散によって、SetやGetのパフォーマンスに影響が出るかを検証したのが以下の結果です。
検証はクラスタモードで、Replica=1として行いました。


CPU使用率はほぼ上限まで活かしきれているので、全て概ね同条件での検証としてRPSの比較がそのまま可能です。

結果

SetについてはほぼRPSは変わりませんでしたが、
データ取得については分散が小さい方がやや早い結果となりました。
GetとFindは、Getが2倍以下なのに対して、Findは4倍ほど処理性能に差が出ました。
この理由については理由を解決できなかったため、後日再検証を行う予定です。
FindByOrderに関しても100件取得しているが、分散が小さい方がかなり高速に処理が行える事が分かります。

4. クラスタモードでReplica=1とした時、 Findする件数を20件or100件にした時の比較検証

一括で取得する(Find)件数によってパフォーマンスに影響が出るか検証したのが以下の結果です。
また分散との関連性を明らかにするために、3.での検証と同様に分散値が100と10万件の場合についての比較も行いました。


CPU使用率はほぼ上限まで活かしきれているので、全て概ね同条件での検証としてRPSの比較がそのまま可能です。

結果

どちらの分散の結果を見ても、取得件数とRPSは比例しないことが分かりました。
かつ、分散が多くなるほどパフォーマンスの違いは大きく影響を及ぼす結果となりました。

障害検証

障害検証では主にフェイルオーバの挙動や、動作中のReplica追加・削除について検証を行いました。

Elasticache Redisでのフェイルオーバは、Primaryが落ちた際、
リードレプリカノードがPrimaryに昇格し、ダウンタイムを最小限に動作する可用性のための機能です。
フェイルオーバについてはElasticacheが検証用の機能を用意してくれており、
コンソールやElasticacheAPIから実行することができます。
落ちたPrimaryはRecoverされ、自動的にReplicaとして復帰します。

You can test a maximum of five node groups in a rolling 24-hour period.

とドキュメントにはあるので24時間で5回のテストが可能となっているので注意して下さい。

検証ではSetやGetのリクエスト負荷を負荷検証と同様に掛け続け、
10秒置きに平均RPSやエラー回数等を出力するようにして、メトリクスと合わせてダウンタイムやCPUの挙動を確認します。

メトリクスでは[エンジンCPU]、[ネットワーク受信byte]、[ネットワーク送信byte]、
[マスタリンクへのヘルスステータス]、[取得タイプのコマンドカウント]、[キャッシュヒット]、
[レプリケーションラグ]など全般的に確認していますが、特出した挙動をしたものがあれば記載しています。

検証を行ったパターンは以下の通りです。

  1. 非クラスタモード(Replica=1)で プライマリエンドポイントを指定 してSet実行中にフェイルオーバ
  2. クラスタモードでReplica=1とした時、Set実行中にフェイルオーバ
  3. クラスタモードでReplica=1とした時、SetとGet実行中にフェイルオーバ
  4. クラスタモードでReplica=2とした時、SetとGet実行中にフェイルオーバ
  5. クラスタモードで MaxConnAge=10分 に増やして、SetとGet実行中にフェイルオーバ
  6. クラスタモードでSetとGetを実行中に Replica追加
  7. クラスタモードでSetとGetを実行中に Replica削除

上から順に検証結果を示します。

1. 非クラスタモード(Replica=1)でプライマリエンドポイントを指定してSet実行中にフェイルオーバ

負荷試験の1.においてPrimaryノードのエンドポイントを指定して動作させていましたが、
Replicaを1つ立てた状態で自動でフェイルオーバさせるために プライマリエンドポイントをアドレスに指定 します。

Configの設定は以下のようにしました。

実行結果は以下の通りです。

Set実行時RPS: 25000

19:00 フェイルオーバAPI実行
  エラー出力開始:19:00:20 (ダウン, RPS=0)
  エラー出力終了:19:01:00 (ダウンタイム復帰)
 昇格Primary1台で稼働中RPS:26000

19:06 元Primary復帰
イベント(コンソール)
2020年2月3日月曜日 19時00分10秒 UTC+9  Test Failover API called for node group 0001
2020年2月3日月曜日 19時00分36秒 UTC+9  Failover from master node dev-loadtest-002 to replica node dev-loadtest-001 completed
2020年2月3日月曜日 19時00分36秒 UTC+9  Failover from master node dev-loadtest-002 to replica node dev-loadtest-001 completed
2020年2月3日月曜日 19時01分24秒 UTC+9  Recovering cache nodes 0001
2020年2月3日月曜日 19時04分48秒 UTC+9  Recovering cache nodes 0001
2020年2月3日月曜日 19時06分58秒 UTC+9  Finished recovery for cache nodes 0001

初期Primary: dev-loadtest-002 (オレンジ)

 

結果

ダウンタイムは40秒ほどで、特に1台稼働中でもRPSの低下は見られませんでした。

1台での稼働中にRPSが微増しているのは
単純にレプリケーションを行うコストが無くなったためかと思われます。
また、Replicaノードがダウンして復帰した瞬間や新規作成した直後、
CPU使用率やネットワーク受信バイトがスパイク的に上昇しますが、これはPrimaryからデータを受け取ってレプリケーションを行うからではないかと考えられます。

2. クラスタモードでReplica=1とした時、Set実行中にフェイルオーバ

1.の検証とほぼ同様の条件で、今度はクラスタモードでフェイルオーバを実行してみました。
クラスタモードでの設定はまえおきで記載した通りです。

実行結果は以下の様になりました。

正常実行時RPS:25000

15:25 フェイルオーバAPI実行 
  エラー出力開始: 15:25:15 (ダウン, RPS=0)
  エラー出力終了: 15:26:15 (ダウンタイム復帰)
 昇格Primary1台で稼働中RPS:25600

15:36 元Primary復帰
イベント(コンソール)
2020年2月6日木曜日 15時25分10秒 UTC+9  Test Failover API called for node group 0001
2020年2月6日木曜日 15時26分16秒 UTC+9  Failover to replica node dev-loadtest-0001-002 completed
2020年2月6日木曜日 15時28分29秒 UTC+9  Recovering cache nodes 0001
2020年2月6日木曜日 15時34分26秒 UTC+9  Finished recovery for cache nodes 0001

初期Primary: dev-loadtest-001(青)

 

結果

非クラスタモードとあまり結果は変わらず、ダウンタイムは60秒ほどで、特に1台稼働中でもRPSの低下は見られませんでした。

3. クラスタモードでReplica=1とした時、SetとGet実行中にフェイルオーバ

クラスタモードの前提で述べた通り、SetはPrimaryへ、GetはReplicaへリクエストが行きます。
それらの負荷を見つつ、データ取得においてもダウンタイムやリソースの挙動に差分がないか確認します。

実行結果は以下の通りです。

正常実行時RPS:Set 23500  /  Get 7100

17:15 フェイルオーバAPI実行
  エラー出力開始:Set  17:15:15 /  Get 17:15:25 (ダウン, RPS=0)
  エラー出力終了:Set  17:16:15  /  Get 17:16:15  (ダウンタイム復帰)
 昇格Primary1台で稼働中RPS:Set 24000  /  Get 7400

17:12 元Primary復帰
イベント(コンソール)
2020年2月6日木曜日 17時15分02秒 UTC+9  Test Failover API called for node group 0001
2020年2月6日木曜日 17時16分11秒 UTC+9  Failover to replica node dev-loadtest-0001-001 completed
2020年2月6日木曜日 17時17分48秒 UTC+9  Recovering cache nodes 0001
2020年2月6日木曜日 17時23分48秒 UTC+9  Finished recovery for cache nodes 0001

初期Primary:dev-loadtest-002(オレンジ)

SetとGetを実行した時、PrimaryよりもReplicaの方がCPU使用率は高くなっています。
この時各ノードが行っている処理としては
Primary:Set、Replicaへのデータ送信(レプリケーション)
Replica:Get、Primaryからのデータ受信(レプリケーション)
となっているはずです。

Setを捌いていたPrimaryが落ちてダウンタイムが明けると、
昇格したPrimaryが1台でSetとGetを両方捌くようになりました。
その時、特に処理性能RPSに差はなく、CPU使用率も劇的な上昇はない事が分かります。
Setに加えてGetを処理するようになるので
CPU使用率が跳ね上がるかと想像してしまいますが、実際は変わりません。
Getコストは増えますがレプリケーションコストが無くなっているため、大きな変化をしない仮定が立ちます。

 
 
[取得タイプのコマンド]を見ることで、GetはReplicaと、1台稼働時のPrimaryにのみリクエストが行っており、
ダウンしたノードがReplicaとして復帰したタイミングでReplicaにのみリクエストが行くようになっている事が分かる。

結果

これまでの検証と同じく1分前後のダウンタイムがあり、正常にフェイルオーバが行われました。
1台で稼働している時間は、昇格したPrimaryにGetとSetリクエストが両方行われますが、
劇的なCPU使用率の上昇はなく、RPSの減少もありませんでした。
GetはReplica(1台稼働時はPrimaryにも)にのみリクエストが行く事がメトリクス上でも確認できます。
特に想定されない異常な値は見受けられません。

1台稼働時にCPU使用率が上昇しない理由については
「Getコストは増えるがレプリケーションコストが無くなっているため、大きな変化をしない」仮定が立てられます。

4. クラスタモードでReplica=2とした時、SetとGet実行中にフェイルオーバ

更にやや複雑になりますが、
Replica=2の時のフェイルオーバ時の昇格Primary、リードではないReplicaの2つの挙動を確認します。
それと3.でのCPUが上昇しない仮説についてもより詳しい情報が分かることになります。

前提としてElasticacheRedisの複数Replicaがある時の挙動ですが、
Replicaの中でもリードレプリカと呼ばれるノードが1台存在し、フェイルオーバ時にはそれが昇格しPrimaryとなる仕様になっています。

実行結果は以下の通りです。

正常実行時RPS:Set 21800  /  Get 8300

11:35 フェイルオーバAPI実行
  エラー出力開始:Set  11:35:30 /  Get 11:36:00 (ダウン, RPS=0)
  エラー出力終了:Set  11:36:40  /  Get 11:36:40  (ダウンタイム復帰)
 昇格Primary1台で稼働中RPS:Set 25000  /  Get 8300

11:43 元Primary復帰
イベント(コンソール)
2020年2月3日月曜日 11時35分26秒 UTC+9  Test Failover API called for node group 0001
2020年2月3日月曜日 11時36分40秒 UTC+9  Failover to replica node dev-loadtest-0001-003 completed
2020年2月3日月曜日 11時37分56秒 UTC+9  Recovering cache nodes 0001
2020年2月3日月曜日 11時43分52秒 UTC+9  Finished recovery for cache nodes 0001

初期Primary:dev-loadtest-002(オレンジ)

まず正常挙動時、3つのノードのCPU使用率はほぼ変わりません。
これはGetでの負荷が2つのReplicaに分散していることと、
Setのレプリケーションコストが2台分になって上昇した結果ではないかと考えられます。

この時の各ノードが行っている処理をまとめると
Primaryオレンジ:Set、Replica2台へのデータ送信(レプリケーション)
Replica青&緑:Get1台分、Primaryからのデータ受信(レプリケーション)
となっているはずです。

フェイルオーバーが起こると、リードレプリカである緑色のノードがPrimaryへ昇格します。
この時の2つのノードの処理は以下の様になります。
昇格Primary緑:Set、Replica1台へのデータ送信(レプリケーション)
Replicaオレンジ:Get2台分、Primaryからのデータ受信(レプリケーション)

メトリクスのデータを見ると、
2台から1台になったReplicaは2台分の処理を捌くのでCPU使用率が大きく上昇し、
ダウンしていたノードがReplicaとして復帰する事で元々のCPU使用率近くに落ち着いています。

また緑のリードレプリカのCPU使用率については
昇格しPrimaryになった時点で元のPrimaryから微増した値になり、
ダウンしていたノードがReplicaとして復帰するとレプリケーションコストが上がり、若干の上昇をしています。

3.でのCPU使用率についての仮説は、このデータを見ると概ね正しい様に見えます。
1.や2.での検証内容を見ても、そもそもレプリケーションでのCPU使用率はそこそこ高いため、
単純にGetでCPUを大幅に使用しているとは考えづらいです。
上記のダウンしたReplicaの復帰でのレプリケーションコスト上昇幅を見ると、概ね等しい程度なのではないかと思われます。

結果

ダウンタイムは変わらず1分前後で正常にフェイルオーバーされ、RPSも落ちません。
初期Primaryが落ちると、Get処理は残ったReplicaへリクエストが行くようになりCPU使用率は上がります。
(CPU使用率に余裕がない場合はここが一時的にRPSを落とすボトルネックになる可能性はありますが…)
昇格Primaryは変わらずSetしか行わないため、大きくCPU使用率は変動しません。

5. クラスタモードで MaxConnAge=10分に増やして、Set実行中にフェイルオーバ

まえおきで記載した通り、ConfigにおいてMaxConnAgeはこれまで1分で設定してきました。
MaxConnAgeとはドキュメントにもある通り、クライアントが接続をCloseする接続時間のことです。

これまでの検証ではダウンタイムが1分前後でしたが、
MaxConnAgeを10分に増やしても、ダウンタイムや切り替わり時間等に影響がないかを確認します。

実行結果は以下の通りです。

正常実行時RPS:Set 23500

17:20 フェイルオーバAPI実行
  エラー出力開始:17:20:15 (ダウン, RPS=0)
  エラー出力終了:17:21:25  (ダウンタイム復帰)
 昇格Primary1台で稼働中RPS: 24500~25500

17:29 元Primary復帰
イベント(コンソール)
2020年2月3日月曜日 17時20分04秒 UTC+9  Test Failover API called for node group 0001
2020年2月3日月曜日 17時21分30秒 UTC+9  Failover to replica node dev-loadtest-0001-002 completed
2020年2月3日月曜日 17時23分14秒 UTC+9  Recovering cache nodes 0001
2020年2月3日月曜日 17時29分05秒 UTC+9  Finished recovery for cache nodes 0001

初期Primary:dev-loadtest-001(青)
 

結果

正常にフェイルオーバし、ダウンタイムも変わらず1分程度となりました。
go-redisのMaxConnAgeはフェイルオーバに影響しないことが分かります。

6. クラスタモードでSetとGetを実行中にReplica追加

動作させながらReplicaを追加した場合、ダウンタイムや挙動がどのようになるかを検証します。
また、これまでconfigで動作するノードのエンドポイントをAddrsに記載していましたが、
記載なく追加した場合に正常にノードを認識するかも確認しました。

方法としては、
Set・Getの負荷を掛けながら、手動でコンソールから他ノードと同条件のReplicaを追加します。
Primary1台、Replica2台の状態で稼働中に、Replicaを1台追加しました。

結果は以下のようになりました。

14:40 SetとGet開始
14:50 Replica作成 命令(コンソールより手動)
14:55 Replica追加、マスタヘルスチェック追加
14:56 Replicaのパフォーマンス安定
エラー出力なし
イベント(コンソール)
2020年2月3日月曜日 14時50分27秒 UTC+9  Increase replica count started for replication group dev-loadtest on 2020-02-03T05:50:27.155Z
2020年2月3日月曜日 14時55分30秒 UTC+9  Cache cluster created
2020年2月3日月曜日 14時55分30秒 UTC+9  This cache cluster does not support persistence (ex: 'appendonly'). Please use a different instance type to enable persistence.
2020年2月3日月曜日 14時55分30秒 UTC+9  Added cache node 0001 in availability zone ap-northeast-1a
2020年2月3日月曜日 14時56分09秒 UTC+9  Increase replica count completed for replication group dev-loadtest on 2020-02-03T05:56:09.009Z

Primary:dev-loadtest-001(青)
 
 
 

手動で追加してから約15分後に追加され、
マスタヘルスチェックや、CPU使用率、レプリケーションバイト数、
ラグなど見ても正常に接続されていることが確認できました。
また、その間エラー件数は0件であったのでダウンタイムも存在しません。
Replicaが合流する瞬間1~2分Primaryの送信ネットワーク量がスパイク的に上がりますが、
Replicaにデータを渡して接続しているためかと思われます。

Configへエンドポイントの追加は行っていませんが、Primaryのエンドポイントが登録されていれば正常に挙動することを確認しました。

結果

configへの追加等必要なく、
手動でReplicaを追加するとエラーやダウンタイムなく、15分ほどで正常に追加が行われました。
ただし、合流時のレプリケーションには若干の負荷が掛かるため、
データ量が多かったりPrimaryのCPU使用率が元々圧迫されている場合は、追加への時間が15分以上掛かる可能性はあります。

また、詳細な検証結果は記載していませんが、
Primary1台のみでReplicaを0台で稼働させた状態からReplicaを2台追加する検証も行い、
問題なく追加が行われた事を確認しています。

7. クラスタモードでSetとGetを実行中にReplica削除

追加とは逆に、負荷が掛かっている状況で手動でReplicaを削除した場合の挙動を検証しました。
Primary1台、Replica3台で稼働中に、Replicaを1台削除します。

結果は以下の通りです。

15:15 SetとGet開始
15:30 Replica削除 命令(コンソールより手動)
15:33 メトリクスのパラメータ変化開始
15:36 削除Replica  削除完了
イベント(コンソール)
2020年2月3日月曜日 15時30分53秒 UTC+9  Decrease Replica count request approved and started for replication group dev-loadtest on 2020-02-03T06:30:53.474Z.
2020年2月3日月曜日 15時36分35秒 UTC+9  Decrease Replica count operation completed for replication group dev-loadtest on 2020-02-03T06:36:35.467Z.

Primary:dev-loadtest-001(青)
削除Replica:メトリクスから削除されてしまい表示されていないので注意
 
 

エラーやダウンタイムはなく、削除操作を行ってから6分後に正常に削除が行われました。
削除された分の負荷は他のノードヘ分散されています。
完全に削除される前に他のノードへリクエストが自動で分散されるようになるため、
こちらで特に実装等に気をつけなくても安全に切り替わりエラーなく削除されていることが分かります。

また、configにエンドポイントに記載が残っている状態でも問題ありませんでした。

結果

configへの削除や特別な実装がなくても、安全にエラーやダウンタイムなく6分ほどで正常に削除が行われます。

また、詳細な検証結果は記載していませんが、
Primary1台、Replica2台の状態からReplicaを2台とも削除する検証も行い、
こちらも問題なく削除と、Primary1台がSetとGetを両方請け負う事になった事を確認しています。

ちなみにフェイルオーバではないPrimaryの手動削除は実行できません。

イベント(コンソール)
Decrease Replica count operation failed because the request included deletion of one or more masters: dev-loadtest-0001-002 for replication group dev-loadtest

まとめ

負荷検証

  • Redisのインスタンスタイプによる性能の劇的な違いはありません。
  • Replica数を増やした時の挙動は、Setのパフォーマンスは落ちますが、取得では安定して比例的なパフォーマンスの向上が見込めます。
  • Scoreは分散が小さい方がパフォーマンスが良いです。
  • 当然ですが一括取得する件数は少ないほうが良いです。

障害検証

  • 非クラスタモード、クラスタモードの両方においてフェイルオーバ時、 ダウンタイムは1分前後 あるものの、リソースに余裕がある場合は フェイルオーバ前後でRedisの処理性能は変わりません 。
  • レプリケーションコストはPrimaryとReplica両方に掛かる ので考慮しておく必要があります。
  • go-redisのMaxConnAgeはフェイルオーバの挙動に影響しません。
  • 動作中のReplica 追加・削除はダウンタイムなく、configのエンドポイント変更なども不要 です。
  • configにはPrimaryのエンドポイントさえ記載していれば、Replicaのエンドポイントを自動で認識してくれます。(クラスタモード時)
  • Replica追加や削除はReplica0台->2台, Replica2台->3台、Replica3台->2台、Replica2台->0台のいずれの場合もダウンタイムなく正常に行われます。

以上が検証結果になります。

おわりに

まとめのみ読んでいただいても問題ありませんが、
これまでの検証を順に見ていくことでRedisの挙動がある程度想定出来るようになると思いますので、
是非お時間のある時にご覧いただければと思います。

また、細心の注意を払って検証を行いましたが、誤りや理解解釈の違い等があれば是非お知らせください。