Amazon Web Services ブログ

Amazon ElastiCache for Redis でクラスターモードを使用する



私が AWS を気に入っている理由の 1 つは、幅広い技術的ユースケースに取り組むために使用できる多数のビルディングブロックがあることです。Amazon ElastiCache for Redis は、そうしたビルディングブロックの 1 つです。データベースキャッシュの高速化のニーズを最もよく考慮していますが、ElastiCache は非常に柔軟で高速 (マイクロ秒) です。これまでに、ElastiCache を使用して地理空間クエリを実行し、リアルタイムダッシュボードを構築する方法について説明しました。

この記事では、既存のワークロードにほとんど変更を加えることなく、信頼性と可用性を強化するためにクラスターモードを有効にした ElastiCache for Redis を活用する方法について説明します。後で説明するように、クラスターモードには、Redis クラスターの水平方向の拡大および縮小という主な利点があり、クラスターのパフォーマンスへの影響はほとんどありません。これまでに過剰または過少にプロビジョニングされている Redis クラスターに遭遇したことがあるか、その内部の仕組みをもっとよく理解したいなら、この記事をお読みください。

詳細を説明する前に、ElastiCache for Redis クラスターを起動する際の構成オプションについて簡単に説明します。次の図に示すように、(1) シングルノード、(2) クラスターモード無効、(3) クラスターモード有効の 3 つのクラスター構成のいずれかを使用することができます。モードに関係なく、特定のクラスター内のすべてのノードは、(基礎となる EC2 インスタンスに関して) 同じノードタイプおよび構成になるように設計されています。

3 つのモードは、主に信頼性、可用性、およびスケーリングの動作が異なります。本稼働のワークロードの場合は、データの保護を強化するためにレプリケーションを含む構成を使用することを検討してください。プライマリノードを除いて、何らかの理由でノードに障害が発生した場合でも、他のノードにレプリケートされているためデータは失われません。プライマリノードに障害が発生した場合は、レプリケーションのレイテンシーが原因で一部のデータが失われる可能性はあります。次の表は、ElastiCache for Redis の構成間の主な違いをまとめたものです。

シングルノード クラスターモード無効 クラスターモード有効
レプリケーション可能? いいえ はい
(ノードあたり最大 5 つのレプリカ)
はい
(ノードあたり最大 5 つのレプリカ)
データパーティション分割可能? はい いいえ
(シングルシャード)
はい
(最大 90 シャード)
スケーリング ノードタイプを変更
(垂直スケーリング)
ノードタイプを変更
(垂直スケーリング)
シャードの追加/削除とリバランス
(水平スケーリング)
マルチ AZ 可能? いいえ 少なくとも 1 つのレプリカでオプション 必須

クラスターモードでの作業

前述のように、本稼働のワークロードを構築するときは、データを簡単に再作成できない限り、レプリケーションを行う構成の使用を検討する必要があります。クラスターモードを有効にすると、クラスターのスケーリングで多くの利点が得られます。要するに、ノードタイプの拡大/縮小 (垂直方向の拡大縮小) に対して、シャードの数を拡大/縮小 (水平方向の拡大/縮小) することができます。これは、クラスターモードでは最大 90 シャードまでの非常に大容量のストレージ (場合によっては数百テラバイト) まで拡張できますが、シングルノードではインスタンスタイプの容量と同じだけのデータをメモリに保存できるだけであることを意味します。

また、クラスターモードでは、未知のストレージ要件または書き込みアクティビティが多い新しいワークロードを設計するときの柔軟性も向上します。読み取りが多いワークロードでは、読み取りレプリカを最大 5 つまで追加することで単一のシャードを拡張できますが、クラスターモードが有効になっている場合は、書き込みが多いワークロードで追加の書き込みエンドポイントを利用できます。 [ソース]

クラスターモードを有効にした ElastiCache for Redis は、キャッシュキースペースを複数のシャードに分散させることによって機能します。つまり、データとそのデータへの読み/書きアクセスは、複数の Redis ノードに分散されています。負荷をより多くのノードに分散させることで、シングルノードの場合よりも多くのメモリスペースを確保しながら、ピーク需要時の可用性を高め、ボトルネックを減らすことができます。まもなく説明しますが、クラスタリングをサポートする Redis クライアントでは、単一のエンドポイントを指定してから、クラスター内のノードに透過的に内部的にマッピングすることができます。

データのシャーディング

Redis は、すべてのキャッシュキーが「ハッシュスロット」にマッピングされるという形式のシャーディングを利用します。 クラスター内には、16,384 のハッシュスロットがあります。これらのスロットは、クラスター内のシャードの総数の間で分割されています。デフォルトでは、ElastiCache はシャードにスロットを均等に分配しますが、必要に応じて分配方法をカスタマイズすることもできます。

クラスターへのデータの書き込みまたは読み取り時に、クライアントは単純なアルゴリズム (CRC16(key) mod 16384) によって使用するハッシュスロットを計算します。ElastiCache for Redis の場合、クライアント自体がキースペースに基づいて使用するシャードを決定します。より多くの作業をクライアントで行うようにすることで、クライアントがクラスター内の任意のシャードに到達できることになり、潜在的な単一障害点を軽減します。すぐにわかるように、Redis クラスターへの最初の接続時に、クライアントは特定のハッシュキーがどのノードで見つかるかを識別するために使用できるキースペースマッピングを解決して管理します。

次の図は、Redis キースペースがどのようにして必要な数のシャードを分散し、クライアントアプリケーションがどのシャードにデータを保存するかを決定する方法を示しています。次のセクションでは、ElastiCache でクラスターモードを設定する方法を探ります。

ElastiCache for Redis クラスターの起動

ElastiCache では、AWS マネジメントコンソール、CLI、または SDK を使用して新しい Redis クラスターを速やかに簡単に起動できます。ここでは、マネジメントコンソールを使用して、新しいクラスターを起動し、クラスターモードを有効にします。

お使いのブラウザで AWS マネジメントコンソールを開き、ElastiCache に移動します。ページの中央にある青い [Create] ボタンをクリックします。このクラスターについて、Redis エンジンを選択してクラスターモードを有効にします。

次に、クラスターの名前と説明を入力します。また、エンジンのバージョンを選択することもできますが、一般的には最新バージョンの Redis エンジンを使用することをお勧めします。シャードの数とシャードあたりのレプリカも指定できます。クラスターは、それぞれが指定された数のレプリカを備えた、指定された数のシャード (ここでも最大は 90) で構成されます。それぞれ 2 つのレプリカを持つ 3 つのシャードにより、クラスター内に合計 9 つのノードとなります (3 つのプライマリ + それぞれ 2 つのレプリカ)。

ElastiCache は、ストレージとパフォーマンスのニーズに基づいて、さまざまなキャッシュインスタンスタイプを選択できます。さまざまなノードタイプを選択することで、各シャード内のノードの容量ならびにクラスターの全体的な容量を垂直方向に拡張することができます。シングルノードのスケーリングとは対照的にクラスターモードを使用することで、スケーリングによる中断の回数を減らし、ワークロードの変化するニーズにより的確に対応できるため、コストを削減できます。クラスター内のすべてのノードは同じノードタイプで構成されます。

[Advanced Redis settings] で、クラスター内のキースペースの配分を制御できます。必要に応じてカスタム配布を指定できますが、デフォルトでは、ElastiCache はキーをシャードに均等に配布します。カスタム配布は、クラスター内で少数のキーと値のペアが他のものよりも比較的大きくなると予想される場合に便利です。配布をカスタマイズすることで、1 つ以上の大きなオブジェクトを独自のシャードにプッシュすることができます。

クラスターのネットワーク、バックアップ、セキュリティを設定したら、ページ下部の [Create] をクリックして新しいクラスターの作成を開始します。クラスターは、数分以内に利用可能になります。

クラスターへの接続

クラスターが「available」になると、使用準備完了です。AWS マネジメントコンソールに表示されている設定エンドポイントを使用してクラスターに接続できます。たとえば、Redis CLI を使用してクラスターに接続し、クラスター内のキースペース/スロットに関する情報を照会することができます。

$ redis-cli -c -h mycluster.cache.amazonaws.com -p 6379

mycluster:6379> CLUSTER SLOTS
1) 1) (integer) 0
   2) (integer) 5461
   3) 1) "172.31.26.164"
      2) (integer) 6379
      3) "bb550a5c91a35d88caa9e636bffa1830093d4895"
   4) 1) "172.31.49.34"
      2) (integer) 6379
      3) "0200ff55ccc7e5cb6b4387443ebdb9652af23504"
   5) 1) "172.31.8.200"
      2) (integer) 6379
      3) "31646876f16baaab749043c406e06d0553287655"
2) ...
3) ...

mycluster:6379> CLUSTER KEYSLOT foo
(integer) 12182

上記の応答から、0〜5461 の範囲のハッシュスロットを持つキーが、IP アドレス 172.31.26.164 で利用可能な Redis ノードに保存されていることがわかります (後続のエントリはそのノードのポートと一意の識別子です)。そのノードのレプリカは、IP アドレス 172.31.49.34 と 172.31.8.200 にあります。クラスターの他の 2 つのシャードについても同様のデータが返されます。マネジメントコンソールでスロット範囲を見つけることもできます。

通常、この情報を直接操作する必要はありませんが、Redis クライアントに不可欠な情報 (ハッシュスロットとノード間のマップ) が提供されます。Redis CLI と同様に、使用する Redis SDK がいずれもクラスタリングをサポートしている必要があります。Amazon ElastiCache チームがサポートの拡大に取り組んでいますが、すべての SDK がクラスタリングをサポートしているわけではありません。特に、SDK は次の 2 つの機能を実装する必要があります: (1) キーハッシュアルゴリズムのサポート、(2) スロットからノードへのマッピングの維持。現在、JavaRubyGoPython、およびその他のプログラミング言語がクラスタリングをサポートしています。

たとえば Python では、クラスターモードで ElastiCache for Redis に接続するのは以下のように簡単です。

pip install redis
>>> import redis
# 各ノードを指定できますが、クライアントはクラスター内のノードを
# 自動的に検出することもできます。
>>> client = redis.Redis(host='mycluster.cache.amazonaws.com', port=6379)

# スロットマッピングを取得する (「CLUSTER SLOTS」と同等)
>>> client.cluster('slots')
# キー 「foo」のハッシュスロットを計算
>>> client.cluster('keyslot', 'foo')
12182
# Redis クライアント SDK がこのマッピングを管理するので、
# どのシャードに保存されるかに関係なくキーを設定できます。
>>> client.set('foo', 'bar')
True
>>> client.get('foo')
'bar'

クラスターのスケーリング

アプリケーションが成長したり人気が高まったりするにつれて、ElastiCache クラスターの容量を増やす必要があるかもしれません。クラスターモードでは、シングルノードを垂直方向にスケーリングするのではなく、シャードを追加または削除して水平方向にスケーリングできます。この方法では、再起動が不要なのでクラスターの可用性が向上しますが、プロセス中にパフォーマンスに多少の影響が出る可能性があります。

概念的には、クラスターの水平方向のスケーリングはサーバー側で理解するのが簡単です。単にシャードが追加または削除されます。新しいノードの準備ができたら、クラスターは設定されたとおりにノード間でキースペースを再割り当てする、またはバランスをとる必要があります。ElastiCache for Redis を使用している場合、リバランスは自動的に行われます。

前述のように、クライアントは、キースペースのノードへの独自のマッピングを維持する必要があります。クライアントがどのようにリバランスを処理するかは、キーマッピングが変更されたという通知がないという点で多少異なります。代わりに、クライアントによって実行される次の操作で、クラスターはキーが移動したことを通知します。

$ redis-cli -c -h mycluster.cache.amazonaws.com -p 6379

mycluster:6379> GET foo
-MOVED 12182 172.31.8.18:6379

この場合、操作自体は 2 段階のプロセスであり、操作全体を完了するためにレイテンシーが発生する可能性がありますが、クライアントは更新されたキーマッピングを認識しています。この後、クライアントは以前と同じように動作できるようになり、クラスター内の使用可能なシャードを完全に利用できるようになります。

テスト実行: クラスターのスケーリングの前後

ElastiCache は、クラスターの使用状況を監視するのに役立つ、いくつかのメトリクスAmazon CloudWatch に公開します。これらの中には、ElastiCache のパフォーマンスに関する優れた洞察を提供するものがあり、ワークロードを理解していると、クラスターがスケーリングから恩恵を受ける場合を特定するのに役立ちます。

スケーリングの実際を示すために、下の図に示す単純なテストハーネスを作成しました。テストハーネスには、クラスターモードが有効になっている新しい ElastiCache for Redis クラスターが含まれています。この新しいクラスターは、1 つのシャードと、cache.r5.large のノードタイプで開始します。AWS Lambda 関数を使用して、データをクラスターに読み書きします。この関数は、それらの操作の応答時間を取得し、結果を Amazon CloudWatch に書き込みます。AWS Fargate タスクで実行されている定評のある負荷テストツール Artillery を使用して、Application Load Balancer にトラフィックを送り、この関数を呼び出します。このテストでは、それぞれの関数呼び出しが ElastiCache への新しい接続を開くことに注意してください。Lambda のベストプラクティスは、呼び出し間で実行環境が再利用されるときにその接続を再利用することです。

このテストハーネスを使用すると、たとえば ElastiCache にセッションデータを保存するウェブサイトの負荷をシミュレートすることができます。Artillery を使用して、さまざまな程度の負荷を生成し、ElastiCache からのセッションデータの書き込みおよび読み取りを行うシナリオをいくつか実行します。ウェブサイトの人気が高まるにつれて (少なくともシミュレーションでは)、パフォーマンスを向上させるためにクラスターを拡張する必要があることがわかります。

そのようなシミュレーションの結果が、上の CloudWatch ダッシュボードに表示されています。約 15 分後、使用量が増え (クラスターはパフォーマンスの問題を示していませんでしたが)、レイテンシーメトリクスの記録を続けながら、クラスターに新しいシャードを追加しました。新しいシャードが作成された後、ElastiCache は自動的に 2 つのシャード間でキースペースをリバランスし、マネジメントコンソールに進行状況を表示しました…

…リバランスが完了するまで。

上記のように、ElastiCache への読み取りと書き込みの両方の応答時間を Lambda 関数で取得して、このデータを CloudWatch Logs に書き込みました。CloudWatch Logs Insights を使用して、データを 30 秒単位でグループ化し、パーセンタイルを計算してこれらの操作のレイテンシーを把握しました。

平均または広いデータ分布を変化させる 1 つまたは 2 つの異常値が存在する可能性があるため、レイテンシーなどのメトリクスを評価する場合にパーセンタイルは平均より役立ちます。下のチャートには、p50、p90、p95 が含まれています。こうしたメトリクスは、たとえば、特定の時間枠内のリクエストの 95% が、報告されたメトリクスより短い時間で処理されたことを意味します (例、10:06 の開始から 30 秒以内に、読み取りの 95% がネットワークレイテンシーを含めて 1.2 ミリ秒以内に Redis から Lambda 関数に返されています)。

読み取り (2ms 以下) と書き込み (6ms 以下) の両方について、p90 と p95 の測定値の全体的な一貫性に注意することが重要です。ElastiCache は高速であるだけでなく、読み取りおよび書き込み操作の処理においても一貫して高速です。前述のように、このシミュレーションは cache.m5.large ノードタイプを使用して実行されました。結果はノードタイプによって異なることがあります。

結論

Amazon ElastiCache for Redis を使用すると、一般的なインメモリデータストアを簡単にデプロイして実行できます。クラスタモード有効を使用すると、クラスタの可用性に影響を与えたり、シングルノードの最大容量を超えたりすることを心配せずに、キャッシュの容量を簡単に増減できます。

前述したように、ElastiCache for Redis はキースペースマッピングの管理をクライアントにプッシュします。このアプローチにより、潜在的な単一障害点が軽減されると同時に、サーバーは最小限のレイテンシーで高いスループットを達成することに集中できます。キースペースを管理する際の複雑さは、通常クライアントによって吸収されます。AWS チームは、互換性のあるクライアント SDK の拡大に積極的に取り組んでいます。

ElastiCache は、基本的なキャッシュ以外にもさまざまなユースケースで役立ちます。クラスタモードでは、Redis を数百 TB の容量と高い書き込みレベルへ拡張できます。この機能をどのように活用しているか、ぜひご覧ください。AWS ElastiCache フォーラムで、フィードバックをお寄せください。


著者について

Josh Kahn は、アマゾン ウェブ サービスのソリューションアーキテクトです。 彼は、AWS を使用している場合にソリューションの価値を向上させる手助けとなるために、AWS の顧客と協力してデータベースプロジェクトの指導や技術支援を行っています。