クラウド・コンピューティングは、水平スケーリング・アーキテクチャによって巨大な範囲のワークロードに対応できるという約束で繁栄している。しかし、ホスト間で容易に細分化できないタスクが発生した場合、水平スケーリングは役に立ちません。Redisを扱う場合、ホットキーとホットシャードはあまりにも一般的な例です。
ホットキーとは何ですか?
理論的に完璧な世界では、トラフィックはキャッシュ内のすべてのキーに均等に分散される。現実の世界では、トラフィックが少数のキーに偏って集中することがよくある。これらはしばしば「ホット・キー」と呼ばれます。このような場合、スケーラブルなシステムであっても、特に少数のキーに高い書 き込み負荷がかかると、ボトルネックになることが多くなります。
ホットシャードとは?
ElastiCache Redisのデフォルトの “Production “構成のように、Redisをクラスタモードで実行する場合、データは複数の “Shard “に分割されます。各シャードは単一のホスト・ノードに収まる必要があります。シャードは複製されることがあり、冗長性と読み取りサービスのための追加リソースを提供しますが、書き込みは依然として「プライマリ」ノードだけの責任であり、シャードの容量は使用するノードのサイズによって決まります。
あるキーをどのシャードが担当すべきかを決めるために、RedisはキーのCRC16を取り出し、それを使って数値の「ハッシュ・スロット」を割り当てる。クラスタ内の各シャードは、これらのスロットの独立したサブセットを担当します。
「ホットシャード」と呼ばれる状態は、これらのシャードの1つが総トラフィックのうち不釣り合いなシェアを受けている場合に発生します。これは、そのシャード内にホット・キーが存在するためか、あるいはスロット配置が不運なために、実際のデータの公平な部分よりも大きな部分がシャードに割り当てられているためです。
ホットキー/ホットシャードはなぜ重要なのか?
ホットキーとホットシャードは、私たちのスケーリング能力を阻害します。これは通常、働き過ぎのホストでのリソースの枯渇として現れます。
CPUの飽和
ホットキーとシャードは、しばしばサービングホストに負荷をかけ、利用可能な計算時間を飽和させ、過負荷による待ち時間の増大とエラーをもたらします。
特にRedisでは、すべての処理をシングルスレッドで実行するため、マルチコアホストを効果的に活用できません。
メモリの飽和
ホットキーとシャードは、サービングホストのメモリ使用率にもストレスを与えます。
Redisでは、”最良の “シナリオは、コンフィギュレーションが適切で、データを退避させるか、新しい書き込みを拒否することです。さらに悪いケースでは、Redisがホストのメモリ制限を超えて強制終了され、ダウンタイムやデータ損失が発生する可能性があります。
ネットワークの飽和
ホットキーとシャードはネットワークの過負荷にもつながります。リクエストに対応するために必要な帯域幅は、サービングホストで利用可能な帯域幅を単純に超えてしまいます。
Redisでは、レプリケーションが有効になっている場合、プライマリがリクエストを処理するために使用する帯域幅に加えて、下流のレプリカにもデータを送信する必要があるため、書き込みには乗数的に多くの帯域幅が使用されることを覚えておくことが重要です。
Redisでホットキーの影響を軽減するには?
Redisの書き込みパフォーマンスによってホットキーに問題が発生している場合、利用可能な最良の選択肢は、多くの場合、クライアントアプリケーションの変更によってキーへの書き込み量を減らすことです。書き込みは最終的に単一のホストのパフォーマンスによって制限されるため、Redis内の問題に対処するために利用可能な唯一の手段は、ホストを垂直方向にスケールすることです。
ホットキーの読み取り性能に問題がある場合、一般的な最初の緩和策は、シャードのレプリケーション係数を増やすことで、追加のレプリカに読み取り負荷を分散させることです。あるいは、下流のRedisコンシューマーにキャッシュレイヤーを導入することで、読み取り負荷を軽減できる場合も多くあります。
Redisのホットシャードの影響を軽減するには?
負荷分散のためにハッシュスロットを割り当て直す
Redisでは、どのシャードがどのハッシュスロットを担当するかを指定することができます。ハッシュスロットを再割り当てすることで、シャード間のトラフィックのバランスを取ることができます。
しかし、この方法には大きな欠点があります。手作業が多く、バランスを保つために継続的なメンテナンスが必要なのです。さらに、オフラインでしか実行できず、ダウンタイムが必要です。ElastiCacheはオンライン・クラスタ上で機能する印象的なスロット・リバランシング機能を開発したが、それはシャード間でスロットを均等に分配することしかできません。
負荷がキー間で予測可能に分散され、大きな変動がないと予想される場合、負荷のバランスをとるために1回限りの作業を行えば、配当が得られるかもしれません。
クラスタ全体のスケール
Redisクラスタにシャードを追加することで、ホットシャードを緩和することができます。追加のシャードにトラフィックを分割すると、ホットシャードに要求される作業が減り、問題が解決されることが多いのですが、同じ量のトラフィックを処理するためにより多くのノードが必要になり、その多くが比較的アイドル状態になる可能性があるため、効率が悪くなります。
結論として
ホットキーとホットシャードは、Redisを扱う上で難しい課題だ。クラスターを過剰にプロビジョニングしてキースペースのごく一部をサポートするか、クライアント・アプリケーションをより均等にトラフィック・バランスが取れるように作り直すか、岩と岩の間で立ち往生することが多くあります。
Momentoでは、ホットキー(およびホットシャード)を舞台裏で処理するためにインフラストラクチャを最適化しています。キャッシュへのトラフィックが変化しても、ダウンタイムやメンテナンス・ウィンドウを必要とせず、スケーリング処理をお任せいただけます。