持続的な接続性の問題 - Amazon ElastiCache

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

持続的な接続性の問題

ElastiCache を用いて永続的な接続性の問題のトラブルシューティングを行う際に、次の項目を確認する必要があります。

セキュリティグループ

セキュリティグループは、ElastiCache クライアント (EC2 インスタンス、 AWS Lambda 関数、Amazon ECS コンテナなど) と ElastiCache キャッシュを保護する仮想ファイアウォールです。セキュリティグループはステートフルです。つまり、着信トラフィックまたは発信トラフィックが許可されると、そのトラフィックに対する応答は、その特定のセキュリティグループのコンテキストで自動的に承認されます。

ステートフル機能では、セキュリティグループがすべての許可された接続を追跡し続ける必要があり、追跡される接続には制限があります。制限に到達すると、新しい接続は失敗します。クライアント側または ElastiCache 側で制限にヒットしたかどうかを確認する方法については、トラブルシューティングのセクションを参照してください。

クライアントと ElastiCache クラスターに同時に単一のセキュリティグループを割り当てるか、それぞれに個別のセキュリティグループを割り当てることができます。

どちらの場合も、ソースからの ElastiCache ポート上の TCP 発信トラフィックと、同じポート上の ElastiCache への着信トラフィックを許可する必要があります。デフォルトのポートは、Memcached では 11211、Valkey または Redis OSS では 6379 です。デフォルトで、セキュリティグループはすべてのアウトバウンドトラフィックを許可します。この場合、ターゲットセキュリティグループのインバウンドルールのみが必要です。

詳細については、「Amazon VPC の ElastiCache クラスターにアクセスするためのアクセスパターン」を参照してください。

ネットワーク ACL

ネットワークアクセスコントロールリスト (ACL) は、ステートレスルールです。トラフィックを成功させるには、両方向 (インバウンドとアウトバウンド) で許可する必要があります。ネットワーク ACL は、特定のリソースではなく、サブネットに割り当てられます。ElastiCache とクライアントリソースに同じ ACL を割り当てることは可能です。特に、それらが同じサブネットにある場合です。

デフォルトでは、ネットワーク ACL はすべてのトラフィックを許可します。ただし、トラフィックを拒否または許可するようにカスタマイズすることは可能です。さらに、ACL ルールの評価はシーケンシャルです。つまり、トラフィックに一致する最も小さい番号を持つルールで、それが許可または拒否されます。Valkey または Redis OSS トラフィックを許可する最小構成は次のとおりです。

クライアント側のネットワーク ACL:

  • インバウンドルール:

  • ルール番号: 好ましくは拒否ルールよりも低い。

  • [タイプ]: [カスタム TCP ルール]。

  • [Protocol]: TCP

  • [Port Range]: 1024~65535

  • [ソース]: 0.0.0.0/0 (または ElastiCache クラスターサブネット用の個別ルールを作成する)

  • [許可/拒否]: 許可

  • アウトバウンドルール:

  • ルール番号: 好ましくは拒否ルールよりも低い。

  • [タイプ]: [カスタム TCP ルール]。

  • [Protocol]: TCP

  • [Port Range]: 6379

  • [ソース]: 0.0.0.0/0 (または ElastiCache クラスターサブネット。特定の IP を使用すると、フェイルオーバーやクラスターのスケーリング時に問題が発生する可能性があることに注意してください)

  • [許可/拒否]: 許可

ElastiCache ネットワーク ACL:

  • インバウンドルール:

  • ルール番号: 好ましくは拒否ルールよりも低い。

  • [タイプ]: [カスタム TCP ルール]。

  • [Protocol]: TCP

  • [Port Range]: 6379

  • [ソース]: 0.0.0.0/0 (または ElastiCache クラスターサブネット用の個別ルールを作成する)

  • [許可/拒否]: 許可

  • アウトバウンドルール:

  • ルール番号: 好ましくは拒否ルールよりも低い。

  • [タイプ]: [カスタム TCP ルール]。

  • [Protocol]: TCP

  • [Port Range]: 1024~65535

  • [ソース]: 0.0.0.0/0 (または ElastiCache クラスターサブネット。特定の IP を使用すると、フェイルオーバーやクラスターのスケーリング時に問題が発生する可能性があることに注意してください)

  • [許可/拒否]: 許可

詳細については、「ネットワーク ACL」を参照してください。

ルートテーブル

ネットワーク ACL と同様に、各サブネットは異なるルートテーブルを持つことができます。クライアントと ElastiCache クラスターが異なるサブネットにある場合は、ルートテーブルが互いに到達できることを確認してください。

複数の VPC、動的ルーティング、またはネットワークファイアウォールを含む、より複雑な環境は、トラブルシューティングが困難になることがあります。「ネットワーク接続性の検証」を参照して、ネットワーク設定が適切であることを確認してください。

DNS 解決

ElastiCache は、DNS 名に基づいてサービスエンドポイントを提供します。使用可能なエンドポイントは、ConfigurationPrimaryReader、および Node エンドポイントです。詳細情報については、「接続エンドポイントの検索」を参照してください。

フェイルオーバーまたはクラスターの変更の場合、エンドポイント名に関連付けられたアドレスが変更され、自動的に更新されます。

カスタム DNS 設定 (VPC DNS サービスを使用しない) は、Elasticache が提供する DNS 名を認識しない場合があります。dig (以下を参照) または nslookup のようなシステムツールを使用して、システムが ElastiCache エンドポイントを正常に解決できることを確認します。

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com example-001.xxxxxx.0001.use1.cache.amazonaws.com. 1.2.3.4

VPC DNS サービスを介して名前解決を強制することもできます。

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com @169.254.169.253 example-001.tihewd.0001.use1.cache.amazonaws.com. 1.2.3.4

サーバー側の診断に関する問題の特定

ElastiCache エンジンからの CloudWatch メトリクスおよびランタイム情報は、接続の問題の潜在的な原因を特定するための一般的なソースまたは情報です。適切な分析は、通常、次の項目から始まります。

  • CPU 使用率: Valkey と Redis OSS はマルチスレッドアプリケーションです。ただし、各コマンドの実行は単一の (メイン) スレッドで行われます。このため、ElastiCache はメトリクス CPUUtilization および EngineCPUUtilization を提供します。EngineCPUUtilization は Valkey または Redis OSS プロセス専用の CPU 使用率を提供し、CPUUtilization はすべての vCPUs 全体の使用率を提供します。複数の vCPU を持つノードは、通常、CPUUtilizationEngineCPUUtilization で異なる値を持ち、ここで 2 番目が一般的に高くなります。高い EngineCPUUtilization は、リクエスト数の上昇や、完了までに多くの CPU 時間を要する複雑なオペレーションが原因である可能性があります。両方を特定するには、以下を使用します。

    • リクエスト数の上昇: EngineCPUUtilization パターンに一致する他のメトリクスでの上昇がないか確認します。役に立つメトリクスは次のとおりです。

      • CacheHitsCacheMisses: 成功したリクエスト数、またはキャッシュで有効な項目を見つけられなかったリクエスト数。ヒットに対するミスの比率が高い場合、アプリケーションは実りのないリクエストで時間とリソースを浪費しています。

      • SetTypeCmdsGetTypeCmds: EngineCPUUtilization と相関しているこれらのメトリクスは、SetTypeCmds によって測定された書き込みリクエスト、または GetTypeCmds によって測定された読み取りに対して負荷が著しく高いかどうかを理解するのに役立ちます。負荷が主に読み取りである場合、複数のリードレプリカを使用すると、複数のノード間でリクエストをバランスさせ、プライマリを書き込み用に取っておくことができます。クラスターモードが無効のクラスターでは、ElastiCache リーダーエンドポイントを使用してアプリケーションに追加の接続設定を作成することで、リードレプリカの使用が可能になります。詳細情報については、「接続エンドポイントの検索」を参照してください。読み取りオペレーションは、この追加の接続に送信する必要があります。書き込みオペレーションは、通常のプライマリエンドポイントを介して実行されます。クラスターモードが有効の場合、リードレプリカをネイティブにサポートするライブラリを使用することをお勧めします。適切なフラグを使用すると、ライブラリはクラスタートポロジ、レプリカノードを自動的に検出し、READONLY Valkey または Redis OSS コマンドを介して読み取りオペレーションを有効にし、読み取りリクエストをレプリカに送信します。

    • 昇格された接続数:

      • CurrConnectionsNewConnections: CurrConnection はデータポイント収集時に確立された接続の数であり、NewConnections はその期間に作成された接続数を示します。

        接続の作成と処理は、多くの CPU オーバーヘッドの発生を意味します。さらに、新しい接続の作成に必要な TCP スリーウェイハンドシェイクは、全体的な応答時間に悪影響を及ぼします。

        1 分あたり数千の NewConnections がある ElastiCache ノードは、最適ではない、接続が少数のコマンドのみで作成および使用されることを示します。確立された接続を維持し、新しいオペレーションのために接続を再使用することがベストプラクティスです。これは、クライアントアプリケーションが接続プーリングまたは永続的な接続をサポートし、適切に実装している場合に可能です。接続プーリングでは、currConnections の数には大きなバリエーションがないので、NewConnections をできる限り低くする必要があります。Valkey または Redis OSS は、少数の currConnections で最適なパフォーマンスを提供します。CurrConnection を数十または数百のオーダーで維持すると、クライアントバッファのような個別の接続や、接続に役立つ CPU サイクルをサポートするためのリソースの使用量が最小限になります。

    • ネットワークスループット:

      • 帯域幅の決定: ElastiCache ノードのネットワーク帯域幅は、ノードサイズに比例します。アプリケーションの特性が異なるため、結果はワークロードに応じて異なる場合があります。たとえば、小さなリクエストの割合が高いアプリケーションは、ネットワークのスループットよりも CPU 使用率に影響を及ぼす傾向がありますが、キーが大きいほどネットワーク使用率が高くなります。そのため、制限をよりよく理解するために、実際のワークロードでノードをテストすることをお勧めします。

        アプリケーションからの負荷をシミュレートすると、より正確な結果が得られます。ただし、ベンチマークツールは、制限についての良いアイデアを提供することができます。

      • リクエストが主に読み取りの場合、読み取りオペレーションでレプリカを使用すると、プライマリノードの負荷が軽減されます。ユースケースが主に書き込みの場合、多くのレプリカを使用するとネットワークの使用が増大します。プライマリノードに書き込まれるすべてのバイトについて、N バイトがレプリカに送信され、ここで N はレプリカの数になります。書き込み負荷の高いワークロードのベストプラクティスは、クラスターモードを有効にして ElastiCache for Redis OSS を使用することです。これにより、書き込みを複数のシャード間で分散したり、より多くのネットワーク機能を備えたノードタイプにスケールアップしたりできます。

      • CloudWatch メトリクスの NetworkBytesInNetworkBytesOut は、ノードに出入りするデータ量をそれぞれ提供します。ReplicationBytes は、データ複製専用のトラフィックです。

      詳細については、「ネットワーク関連の制限」を参照してください。

    • 複雑なコマンド: Redis OSS コマンドは単一のスレッドで提供されます。つまり、リクエストは順番に処理されます。単一のスローコマンドは、他のリクエストや接続に影響を及ぼし、タイムアウトが発生する可能性があります。複数の値、キー、またはデータ型に作用するコマンドの使用は、慎重に行う必要があります。接続は、パラメータの数や入出力値のサイズに応じて、ブロックまたは終了できます。

      評判の悪い例は、KEYS コマンドです。これは、指定されたパターンを検索するキースペース全体をスイープし、その実行中に他のコマンドの実行をブロックします。Redis OSS は、コマンドの複雑さを記述するために「Big O」表記法を使用しています。

      キーコマンドには O(N) 時間の複雑さがあり、ここで N はデータベース内のキーの数になります。したがって、キーの数が多いほど、コマンドは遅くなります。KEYS は、さまざまな方法で問題を引き起こす可能性があります。検索パターンが使用されていない場合、コマンドは利用可能なすべてのキー名を返します。数千または数百万の項目を含むデータベースでは、巨大な出力が作成され、ネットワークバッファがフラッディングします。

      検索パターンを使用すると、パターンに一致するキーのみがクライアントに戻ります。ただし、エンジンはキースペース全体のスイープを続けるので、コマンドを完了する時間は同じになります。

      KEYS の代替は、SCAN コマンドです。これは、キースペースを反復し、特定の数の項目の反復を制限して、エンジン上の長引くブロックを回避します。

      スキャンには COUNT パラメータがあり、反復ブロックのサイズを設定するために使用されます。デフォルト値は 10 (1 回の反復あたり 10 個のアイテム) です。

      データベース内の項目数に応じて、小さな COUNT 値のブロックは、フルスキャンを完了するために多くの反復を必要とし、値を大きくすると、各反復でエンジンをビジー状態でより長く維持します。小さなカウント値は大きなデータベースで SCAN をより遅くしますが、値を大きくすると KEYS で説明されたものと同じ問題が生じる可能性があります。

      例として、10 のカウント値がある SCAN コマンドの実行は、100 万個のキーがあるデータベースでの 100,000 回の繰り返しを必要とします。平均ネットワークラウンドトリップ時間が 0.5 ミリ秒の場合、リクエストの転送に約 50,000 ミリ秒(50 秒)が費やされます。

      一方、カウント値が 100,0000 であった場合、1 回の反復が必要で、転送に費やされる時間はわずか 0.5 ミリ秒です。ただし、コマンドがすべてのキースペースのスイープを終了するまで、エンジンは他のオペレーションのために完全にブロックされます。

      KEYS に加えて、いくつかの他のコマンドは、正しく使用されない場合、潜在的に有害になります。すべてのコマンドのリストとそれぞれの時間の複雑さを確認するには、「Valkey and Redis OSS commands」にアクセスしてください。

      潜在的な問題の例:

      • Lua スクリプト: Redis OSS は組み込み Lua インタプリタを提供し、サーバー側でのスクリプトの実行を可能にします。Valkey および Redis OSS の Lua スクリプトはエンジンレベルで実行され、定義上アトミックです。つまり、スクリプトの実行中に他のコマンドやスクリプトは実行できません。Lua スクリプトは、複数のコマンド、意思決定アルゴリズム、データ解析などをエンジン上で直接実行する可能性を提供します。スクリプトのアトミック性とアプリケーションのオフロードの機会は魅力的ですが、スクリプトは小さなオペレーションでは注意を払って使用する必要があります。ElastiCache では、Lua スクリプトの実行時間は 5 秒に制限されています。キースペースに書き込まれていないスクリプトは、5 秒後に自動的に終了します。データの破損や不整合を避けるため、スクリプトの実行が 5 秒以内に完了せず、実行中に書き込みがあった場合、ノードはフェイルオーバーします。トランザクションは、Redis OSS の複数の関連するキー変更の一貫性を保証する代替手段です。トランザクションは、コマンドのブロックの実行を可能にし、既存のキーの変更を監視します。トランザクションの完了前に監視キーのいずれかが変更された場合、すべての変更は破棄されます。

      • アイテムの一括削除: DEL コマンドは、削除するキー名である複数のパラメータを受け入れます。削除オペレーションは同期的であり、パラメータのリストが大きい場合、または大きなリスト、セット、ソートされたセット、またはハッシュ (いくつかのサブ項目を保持するデータ構造) が含まれている場合、多くの CPU 時間がかかります。言い換えれば、単一のキーを削除しても、多くの要素がある場合、多くの時間がかかることがあります。DEL の代替は UNLINK です。これは、Redis OSS 4 以降で利用可能な非同期コマンドです。いつでも可能な限り、DELUNLINK より優先される必要があります。ElastiCache for Redis OSS 6x 以降、 lazyfree-lazy-user-delパラメータは、有効になっているUNLINKときにDELコマンドを のように動作させます。詳細については、「Redis OSS 6.0 パラメータの変更」を参照してください。

      • 複数のキーに作用するコマンド: DEL は、複数の引数を受け入れるコマンドとして前述されており、実行時間はそれに正比例します。ただし、Redis OSS には、同様に機能する多くのコマンドが用意されています。例として、MSETMGET を使用すると、一度に複数の String キーを挿入または取得できます。これらの使用は、複数の個別の SET または GET コマンドに固有のネットワーク遅延を低減するために有益である可能性があります。ただし、パラメータの広範なリストは CPU 使用率に影響します。

        CPU 使用率だけが接続の問題の原因ではありませんが、複数のキーで単一または少数のコマンドを処理するのに時間がかかりすぎると、他のリクエストが失敗し、CPU 使用率が増加する可能性があります。

        キーの数とそのサイズは、コマンドの複雑さ、また結果として完了時間に影響します。

        複数のキーに対して作用できるコマンドのその他の例: HMGETHMSETMSETNXPFCOUNTPFMERGESDIFFSDIFFSTORESINTERSINTERSTORESUNIONSUNIONSTORETOUCHZDIFFZDIFFSTOREZINTER または ZINTERSTORE

      • 複数のデータ型に作用するコマンド: Redis OSS はまた、そのデータ型に関係なく、1 つまたは複数のキーに作用するコマンドを提供します。ElastiCache for Redis OSS には、このようなコマンドをモニタリングKeyBasedCmdsするための メトリクスが用意されています。このメトリクスは、選択した期間における次のコマンドの実行を合計します。

        • O(N) の複雑さ:

          • KEYS

        • O(1)

          • EXISTS

          • OBJECT

          • PTTL

          • RANDOMKEY

          • TTL

          • TYPE

          • EXPIRE

          • EXPIREAT

          • MOVE

          • PERSIST

          • PEXPIRE

          • PEXPIREAT

          • UNLINK (O(N) により、メモリを再利用します。しかし、メモリ再利用タスクは分離されたスレッドで発生し、エンジンをブロックしません

        • データ型によって異なる複雑さの時間:

          • DEL

          • DUMP

          • RENAME は O(1) の複雑さがあるコマンドとみなされますが、DEL を内部で実行します。実行時間は、名前が変更されたキーのサイズによって異なります。

          • RENAMENX

          • RESTORE

          • SORT

        • 大きなハッシュ: ハッシュは、複数のキー値サブ項目がある単一のキーを可能にするデータ型です。各ハッシュは 4.294.967.295 項目を格納することができ、大きなハッシュでのオペレーションは費用がかかる可能性があります。KEYS と同様に、ハッシュは O(N) 時間の複雑さがある HKEYS コマンドを持ち、ここで N はハッシュ内の項目数になります。長時間実行されるコマンドを避けるために、HSCANHKEYS より優先される必要があります。HDELHGETALLHMGETHMSET および HVALS は、大きなハッシュで注意して使用する必要があるコマンドです。

      • 他の大きなデータ構造: ハッシュに加えて、他のデータ構造では CPU 集中的になる可能性があります。セット、リスト、ソートされたセット、およびハイパーログログも、そのサイズと使用されるコマンドによっては、操作に多くの時間がかかることがあります。これらのコマンドの詳細については、「Valkey and Redis OSS commands」を参照してください。

ネットワーク接続性の検証

DNS 解決、セキュリティグループ、ネットワーク ACL、およびルートテーブルに関連するネットワーク設定を確認した後、VPC Reachability Analyzer とシステムツールを使用して接続性を検証できます。

Reachability Analyzer は、ネットワーク接続性をテストし、すべての要件と許可が満たされているかどうかを確認します。以下のテストでは、VPC で使用可能な ElastiCache ノードの 1 つの ENI ID (Elastic Network Interface ID) が必要です。それを見つけるには、以下の操作を行います。

  1. https://console.aws.amazon.com/ec2/v2/home?#NIC: にアクセスします。

  2. ElastiCache クラスター名または以前 DNS 検証から取得した IP アドレスでインターフェイスリストをフィルタリングします。

  3. ENI IDを書き留めるか、保存してください。複数のインターフェイスが表示されている場合は、説明を読んで、適切な ElastiCache クラスターに属していることを確認し、そのうちの 1 つを選択します。

  4. 次のステップに進みます。

  5. 解析パス (https://console.aws.amazon.com/vpc/home?#ReachabilityAnalyzer) を作成し、次のオプションを選択します。

    • ソースタイプ: ElastiCache クライアントが Amazon EC2 インスタンスで実行されている場合はインスタンスを選択し、awsvpc ネットワークを使用する AWS Fargate Amazon ECS などの別のサービスを使用している場合はネットワークインターフェイスを選択し AWS Lambda、それぞれのリソース ID (EC2 インスタンスまたは ENI ID) を選択します。

    • [送信先タイプ]: [ネットワークインターフェイス] を選択し、リストから [Elistiache ENI] を選択します。

    • 送信先ポート: ElastiCache for Redis OSS の場合は 6379、ElastiCache for Memcached の場合は 11211 を指定します。これらはデフォルト設定で定義されたポートであり、この例では、変更されていないことを前提としています。

    • [Protocol]: TCP

分析パスを作成し、結果まで数分待ちます。ステータスが到達不能の場合は、解析の詳細を開き、[解析エクスプローラ] で、リクエストがブロックされた場所の詳細を確認してください。

到達可能性テストに合格した場合は、OS レベルでの検証に進みます。

ElastiCache サービスポートで TCP 接続を検証するには: Amazon Linux で、Nping はパッケージの nmap で利用可能で、ElastiCache ポート上で TCP 接続をテストでき、また接続を確立するためにネットワークラウンドトリップ時間を提供することもできます。以下に示すように、これを使用して、ネットワーク接続性と ElastiCache クラスターへの現在のレイテンシーを検証します。

$ sudo nping --tcp -p 6379 example.xxxxxx.ng.0001.use1.cache.amazonaws.com Starting Nping 0.6.40 ( http://nmap.org/nping ) at 2020-12-30 16:48 UTC SENT (0.0495s) TCP ... (Output suppressed ) Max rtt: 0.937ms | Min rtt: 0.318ms | Avg rtt: 0.449ms Raw packets sent: 5 (200B) | Rcvd: 5 (220B) | Lost: 0 (0.00%) Nping done: 1 IP address pinged in 4.08 seconds

デフォルトでは、nping は、5 つのプローブをそれらの間で 1 秒の遅延で送信します。オプション「-c」を使用してプローブ数を増やし、「—delay」を使用して新しいテストを送信するための時間を変更できます。

nping でのテストが失敗し、[VPC Reachability Analyzer] テストに合格した場合は、オペレーティングシステムレベルで考えられる、ホストベースのファイアウォールルール、非対称ルーティングルール、またはその他の制限を確認するよう、システム管理者に依頼してください。

ElastiCache コンソールで、[転送時の暗号化] が ElastiCache クラスターの詳細で有効になっていることを確認してください。転送中の暗号化が有効になっている場合は、次のコマンドを使用して TLS セッションを確立できるかどうかを確認します。

openssl s_client -connect example.xxxxxx.use1.cache.amazonaws.com:6379

接続と TLS ネゴシエーションが成功すると、広範な出力が期待されます。最後の行で利用可能な戻りコードを確認してください。値は 0 (ok) である必要があります。openssl が何か異なるものを返す場合は、https://www.openssl.org/docs/man1.0.2/man1/verify.html#DIAGNOSTICS でエラーの理由を確認します。

すべてのインフラストラクチャおよびオペレーティングシステムのテストに合格しても、アプリケーションがまだ ElastiCache に接続できない場合は、アプリケーション設定が ElastiCache 設定に準拠しているかどうかを確認してください。よくある間違いは次のとおりです。

  • アプリケーションが ElastiCache クラスターモードをサポートしておらず、ElastiCache でクラスターモードが有効になっています。

  • アプリケーションが TLS/SSL をサポートしておらず、ElastiCache で転送時の暗号化が有効になっています。

  • アプリケーションは TLS/SSL をサポートしていますが、正しい設定フラグまたは信頼できる証明権限がありません。

ネットワーク関連の制限

  • 最大接続数: 同時接続にはハード制限があります。各 ElastiCache ノードでは、すべてのクライアントで最大 65,000 の同時接続が可能です。この制限は、CloudWatch で CurrConnections メトリクスを介して監視できます。ただし、クライアントにはアウトバウンド接続にも制限があります。Linux では、次のコマンドを使用して、許可されているエフェメラルポート範囲を確認してください。

    # sysctl net.ipv4.ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999

    前の例では、同じ送信元から、同じ送信先 IP (ElastiCache ノード) およびポートへの 28231 の接続が許可されます。次のコマンドは、特定の ElastiCache ノード (IP 1.2.3.4) に存在する接続の数を示します。

    ss --numeric --tcp state connected "dst 1.2.3.4 and dport == 6379" | grep -vE '^State' | wc -l

    この数値が大きすぎると、接続リクエストを処理しようとしてシステムが過負荷になることがあります。接続をより適切に処理するために、接続プーリングや永続的な接続などの技術の実装を検討することをお勧めします。いつでも可能な限り、接続プールを設定して、接続の最大数を数百に制限します。また、タイムアウトやその他の接続例外を処理するためのバックオフロジックは、問題が発生した場合に接続チャーンを避けるようにすることをお勧めします。

  • ネットワークトラフィックの制限: 次の Redis OSS の CloudWatch メトリクスを使用して、ElastiCache ノードでヒットしている、可能性のあるネットワーク制限を特定します。

    • NetworkBandwidthInAllowanceExceeded/NetworkBandwidthOutAllowanceExceeded: スループットが集約された帯域幅制限を超えたためにシェーピングされたネットワークパケット。

      プライマリノードに書き込まれるすべてのバイトが N 個のレプリカに複製されることに注意することが重要で、ここで N はレプリカの数になります。小さなノードタイプ、複数のレプリカ、および集中的な書き込みリクエストがあるクラスターは、レプリケーションのバックログに対処できない場合があります。このような場合は、スケールアップ (ノードタイプを変更する)、スケールアウト (クラスターモードが有効なクラスターにシャードを追加する)、レプリカの数を減らす、または書き込み数を最小限に抑えることがベストプラクティスです。

    • NetworkConntrackAllowanceExceeded: ノードに割り当てられたすべてのセキュリティグループで追跡される接続の最大数を超過したため、パケットがシェーピングされます。この期間中、新しい接続が失敗する可能性があります。

    • NetworkPackets PerSecondAllowanceExceeded: 1 秒あたりの最大パケット数を超えています。非常に小さなリクエストの高いレートに基づくワークロードは、最大帯域幅よりも前にこの制限にヒットした可能性があります。

    上記のメトリクスは、ノードがネットワーク制限にヒットしていることを確認するための理想的な方法です。ただし、制限はネットワークメトリクスのプラトーによっても特定できます。

    プラトーが長期間にわたって観察される場合、レプリケーションの遅れ、キャッシュで使用されるバイト数の増加、解放可能なメモリの低下、高いスワップおよび CPU 使用率がそれに続きます。また、Amazon EC2 インスタンスには、[ENA ドライバーメトリクス] を介して追跡できるネットワーク制限があります。拡張ネットワーキングサポートおよび ENA ドライバー 2.2.10 以降を備えた Linux インスタンスは、次のコマンドを使用して制限カウンターを確認できます。

    # ethtool -S eth0 | grep "allowance_exceeded"

CPU 使用率

CPU 使用率メトリクスは調査の開始点であり、次の項目は ElastiCache 側で発生する可能性のある問題を絞り込むのに役立ちます。

  • Redis OSS SlowLogs: ElastiCache のデフォルト設定では、完了に 10 ミリ秒以上かかった最後の 128 個のコマンドが保持されます。スローコマンドの履歴は、エンジンランタイム中は保持され、障害や再起動時に失われます。リストが 128 エントリに達すると、古いイベントは削除され、新しいイベントのためのスペースが開きます。スローイベントのリストとスローとみなされる実行時間のサイズは、[カスタムパラメータグループ] のパラメータ slowlog-max-len および slowlog-log-slower-than を介して変更できます。スローログのリストは、エンジンで SLOWLOG GET 128 を実行して取得でき、ここで 128 は最後に報告された 128 のスローコマンドになります。各エントリには以下のフィールドがあります。

    1) 1) (integer) 1 -----------> Sequential ID 2) (integer) 1609010767 --> Timestamp (Unix epoch time)of the Event 3) (integer) 4823378 -----> Time in microseconds to complete the command. 4) 1) "keys" -------------> Command 2) "*" ----------------> Arguments 5) "1.2.3.4:57004"-> Source

    上記のイベントは 12 月 26 日 19:26:07 (UTC) に起こり、完了までに 4.8秒(4.823ms)かかり、クライアント 1.2.3.4 からリクエストされた KEYS コマンドによって発生しました。

    Linux では、タイムスタンプはコマンド date で変換できます。

    $ date --date='@1609010767' Sat Dec 26 19:26:07 UTC 2020

    Python の場合:

    >>> from datetime import datetime >>> datetime.fromtimestamp(1609010767) datetime.datetime(2020, 12, 26, 19, 26, 7)

    または、PowerShell を搭載した Windows の場合:

    PS D:\Users\user> [datetimeoffset]::FromUnixTimeSeconds('1609010767') DateTime : 12/26/2020 7:26:07 PM UtcDateTime : 12/26/2020 7:26:07 PM LocalDateTime : 12/26/2020 2:26:07 PM Date : 12/26/2020 12:00:00 AM Day : 26 DayOfWeek : Saturday DayOfYear : 361 Hour : 19 Millisecond : 0 Minute : 26 Month : 12 Offset : 00:00:00Ticks : 637446075670000000 UtcTicks : 637446075670000000 TimeOfDay : 19:26:07 Year : 2020

    短時間 (同じ分以下) での多くのスローコマンドは、懸念の理由になります。コマンドの性質と、それらを最適化する方法を確認してください (前の例を参照)。O(1) の時間の複雑さがあるコマンドが頻繁に報告される場合は、前述の CPU 使用率が高いかどうかについて他の要因を確認してください。

  • レイテンシーメトリクス: ElastiCache for Redis OSS は、さまざまなクラスのコマンドの平均レイテンシーをモニタリングするための CloudWatch メトリクスを提供します。データポイントは、カテゴリ内のコマンドの実行総数を期間内の合計実行時間で割って計算されます。レイテンシーメトリクスの結果は、複数のコマンドの集合であることを理解することが重要です。1 つのコマンドで、メトリクスに大きな影響を与えずに、タイムアウトのような予期しない結果が発生する可能性があります。このような場合、スローログイベントはより正確な情報源になります。次のリストには、使用可能なレイテンシーメトリクスと、それらに影響する各コマンドが含まれています。

    • EvalBasedCmdsLatency: Lua スクリプトコマンド evalevalsha に関連しています;

    • GeoSpatialBasedCmdsLatency: geodistgeohashgeoposgeoradiusgeoradiusbymembergeoadd;

    • GetTypeCmdsLatency: データ型に関係なく、コマンドを読み取ります;

    • HashBasedCmdsLatency: hexistshgethgetallhkeyshlenhmgethvalshstrlenhdelhincrbyhincrbyfloathmsethsethsetnx;

    • HyperLogLogBasedCmdsLatency: pfselftestpfcountpfdebugpfaddpfmerge;

    • KeyBasedCmdsLatency:異なるデータ型に基づいて作用できるコマンド: dumpexistskeysobjectpttlrandomkeyttltypedelexpireexpireatmovepersistpexpirepexpireatrenamerenamenxrestoreKsortunlink;

    • ListBasedCmdsLatency: lindex、llen、lrange、blpop、brpop、brpoplpush、linsert、lpop、lpush、lpushx、lrem、lset、ltrim、rpop、rpoplpush、rpush、rpushx;

    • PubSubBasedCmdsLatency: psubscribe、publish、pubsub、punsubscribe、subscribe、unsubscribe;

    • SetBasedCmdsLatency: scardsdiffsintersismembersmemberssrandmembersunionsaddsdiffstoresinterstoresmovespopsremsunionstore;

    • SetTypeCmdsLatency: データ型に関係なく、コマンドを書き込みます;

    • SortedSetBasedCmdsLatency: zcardzcountzrangezrangebyscorezrankzrevrangezrevrangebyscorezrevrankzscorezrangebylexzrevrangebylexzlexcountzaddzincrbyzinterstorezremzremrangebyrankzremrangebyscorezunionstorezremrangebylexzpopmaxzpopminbzpopminbzpopmax;

    • StringBasedCmdsLatency: bitcountgetgetbitgetrangemgetstrlensubstrbitposappendbitopbitfielddecrdecrbygetsetincrincrbyincrbyfloatmsetmsetnxpsetexsetsetbitsetexsetnxsetrange;

    • StreamBasedCmdsLatency: xrangexrevrangexlenxreadxpendingxinfoxaddxgroupreadgroupxackxclaimxdelxtrimxsetid;

  • Redis OSS ランタイムコマンド:

    • info commandstats: エンジンの起動後に実行されたコマンドのリスト、累積実行数、合計実行時間、およびコマンドごとの平均実行時間を提供します。

    • client list: 現在接続されているクライアントのリスト、およびバッファの使用状況、最後に実行されたコマンドなどの関連情報を提供します。

  • バックアップとレプリケーション: より前のバージョンの ElastiCache for Redis OSS では、分岐プロセスを使用してバックアップを作成し、レプリカとの完全な同期を処理します。 2.8.22 このメソッドは、書き込み集中的なユースケースのために多くのメモリオーバーヘッドが発生する可能性があります。

    ElastiCache Redis OSS 2.8.22 以降、 AWS は分岐なしのバックアップとレプリケーションの方法を導入しました。新しい方法は、障害を防ぐために書き込みを遅らせる場合があります。どちらの方法でも、CPU 使用率が高い期間が発生し、応答時間が長くなり、その結果、実行中にクライアントのタイムアウトが発生する可能性があります。バックアップウィンドウの間にクライアントの障害が発生したか、または SaveInProgress メトリクスが期間内で 1 であったかどうかを常に確認してください。クライアントの問題やバックアップ障害の可能性を最小限にするために、使用率の低い期間でバックアップウィンドウをスケジュールすることをお勧めします。

サーバー側からの接続が終了している

デフォルトの ElastiCache for Redis OSS 設定では、クライアント接続は無期限に確立されます。ただし、状況によっては、接続の終了が望ましい場合があります。例:

  • クライアントアプリケーションのバグにより、接続が忘れられ、アイドル状態で確立されたままになることがあります。これは「接続リーク」と呼ばれ、その結果は CurrConnections メトリクスで観測される確立された接続の数の着実な増加となります。この動作は、クライアント側または ElastiCache 側で飽和状態になる可能性があります。クライアント側からの即時修正が不可能な場合、一部の管理者は ElastiCache パラメータグループに「タイムアウト」値を設定します。タイムアウトは、アイドル接続が持続するために許容される時間 (秒単位) です。クライアントが期間内にリクエストを送信しない場合、接続がタイムアウト値に達するとすぐにエンジンは接続を終了します。タイムアウト値が小さいと、不要な切断が発生する場合があり、クライアントはそれらを適切に処理して再接続する必要があり、遅延が発生します。

  • キーの格納に使用されるメモリは、クライアントバッファと共有されます。大きなリクエストまたは応答があるスロークライアントは、バッファを処理するために多くの量のメモリを要求する場合があります。デフォルトの ElastiCache for Redis OSS 設定では、通常のクライアント出力バッファのサイズは制限されません。maxmemory の制限にヒットした場合、エンジンはバッファの使用量を満たすために項目を削除しようとします。メモリが非常に低い状況では、ElastiCache for Redis OSS は、メモリを解放してクラスターの状態を維持するために、大きなクライアント出力バッファを消費するクライアントを切断することを選択する場合があります。

    カスタム設定を用いてクライアントバッファのサイズを制限することができ、制限をヒットしているクライアントは切断されます。ただし、クライアントは予期しない切断を処理できる必要があります。通常のクライアントのバッファサイズを処理するパラメータは次のとおりです。

    • client-query-buffer-limit: 単一の入力リクエストの最大サイズ;

    • client-output-buffer-limit-normal-soft-limit: クライアント接続のソフトリミット。client-output-buffer-limit-normal-soft-seconds で定義されている秒数より大きなソフトリミットを超えたままである場合、またはハードリミットをヒットした場合、接続は終了します。

    • client-output-buffer-limit-normal-soft-seconds: client-output-buffer-limit-normal-soft-limit を超えている接続で許容される時間

    • client-output-buffer-limit-normal-hard-limit: この制限をヒットした接続は直ちに終了します。

    通常のクライアントバッファに加えて、次のオプションは、レプリカノードと Pub/Sub (Publish/Subscribe) クライアントのバッファを制御します。

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-replica-soft-seconds;

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-pubsub-soft-limit;

    • client-output-buffer-limit-pubsub-soft-seconds;

    • client-output-buffer-limit-pubsub-hard-limit;

Amazon EC2 インスタンスのクライアント側のトラブルシューティング

クライアント側の負荷と応答性は、ElastiCache へのリクエストにも影響する可能性があります。断続的な接続性またはタイムアウトの問題のトラブルシューティングを行う際には、EC2 インスタンスおよびオペレーティングシステムの制限を慎重に確認する必要があります。観察すべきいくつかの重要なポイント:

  • CPU:

    • EC2 インスタンスの CPU 使用率: CPU が飽和していない、または 100% 近くではないことを確認します。履歴分析は CloudWatch を介して実行できますが、データポイントの詳細度は 1 分(詳細モニタリングが有効の場合)または 5 分です。

    • [バースト可能な EC2 インスタンス] を使用する場合は、CPU クレジット残高が枯渇していないことを確認してください。この情報は、CPUCreditBalance CloudWatch メトリクスで入手できます。

    • 高い CPU 使用率の期間が短くなると、CloudWatch での 100% の使用率に反映されずにタイムアウトが発生する可能性があります。このような場合は、topps および mpstat のようなオペレーティングシステムツールによるリアルタイムの監視が必要です。

  • ネットワーク

    • インスタンスの機能に応じて、ネットワークスループットが許容可能な値未満であるかどうかを確認してください。詳細については、「Amazon EC2 のインスタンスタイプ」を参照してください。

    • ena 拡張ネットワークドライバーのインスタンスで、タイムアウトまたは超えられた制限がないか [ENA 統計] を確認してください。次の統計情報は、ネットワーク制限の飽和状態を確認するのに役立ちます。

      • bw_in_allowance_exceeded/bw_out_allowance_exceeded: 過剰なインバウンドまたはアウトバウンドのスループットのためにシェーピングされたパケット数;

      • conntrack_allowance_exceeded: セキュリティグループの [接続追跡制限] のためにドロップされたパケット数。この制限が飽和すると、新しい接続は失敗します。

      • linklocal_allowance_exceeded: インスタンスメタデータ、VPC DNS 経由の NTP への過剰なリクエストによりドロップされたパケット数。制限は、すべてのサービスで毎秒 1024 パケットです。

      • pps_allowance_exceeded: 1 秒あたりの過剰なパケット比率のためにドロップされたパケット数。PPS 制限は、ネットワークトラフィックが 1 秒あたり数千または数百万の非常に小さなリクエストで構成されている場合にヒットする可能性があります。ElastiCache トラフィックは、GET の代わりに MGET のような一度に複数のオペレーションを実行するパイプラインやコマンドを介してネットワークパケットをより効果的に利用できるように最適化できます。

1 つのリクエストを完了するのにかかった時間の解読

  • ネットワーク上: Tcpdump および Wireshark (コマンドラインでは tshark) は、リクエストがネットワークを走行し、ElastiCache エンジンをヒットしてリターンを得るのにかかった時間を理解するための便利なツールです。次の例では、次のコマンドで作成された 1 つのリクエストを強調表示します。

    $ echo ping | nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com 6379 +PONG

    上記のコマンドと並行して、tcpdump が実行中であり、次のように返されました。

    $ sudo tcpdump -i any -nn port 6379 -tt tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 1609428918.917869 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [S], seq 177032944, win 26883, options [mss 8961,sackOK,TS val 27819440 ecr 0,nop,wscale 7], length 0 1609428918.918071 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [S.], seq 53962565, ack 177032945, win 28960, options [mss 1460,sackOK,TS val 3788576332 ecr 27819440,nop,wscale 7], length 0 1609428918.918091 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918122 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [P.], seq 1:6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 5: RESP "ping" 1609428918.918132 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [F.], seq 6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918240 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [.], ack 6, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918295 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [P.], seq 1:8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 7: RESP "PONG" 1609428918.918300 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 8, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 1609428918.918302 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [F.], seq 8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918307 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 9, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 ^C 10 packets captured 10 packets received by filter 0 packets dropped by kernel

    上記の出力から、TCP スリーウェイハンドシェイクが 222 マイクロ秒 (918091~917869) で完了し、ping コマンドが送信され、173 マイクロ秒 (918295~918122) で返されたことを確認できます。

    リクエストから接続を閉じるまで、438 マイクロ秒 (918307~917869) かかりました。これらの結果では、ネットワークとエンジンの応答時間が良好であることを確認し、調査は他のコンポーネントに焦点を当てることができます。

  • オペレーティングシステム上: Strace は、OS レベルでのタイムギャップを特定するのに役立ちます。実際のアプリケーションの分析では、より広範で特殊なアプリケーションプロファイラやデバッガを使用することをお勧めします。次の例は、基本オペレーティングシステムコンポーネントが予期したとおりに動作しているかどうかを示しています。そうでない場合、さらに調査が必要になることがあります。同じ Redis OSS PING コマンドを strace で使用すると、次の結果が得られます。

    $ echo ping | strace -f -tttt -r -e trace=execve,socket,open,recvfrom,sendto nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com (http://example.xxxxxx.ng.0001.use1.cache.amazonaws.com/) 6379 1609430221.697712 (+ 0.000000) execve("/usr/bin/nc", ["nc", "example.xxxxxx.ng.0001.use"..., "6379"], 0x7fffede7cc38 /* 22 vars */) = 0 1609430221.708955 (+ 0.011231) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709084 (+ 0.000124) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709258 (+ 0.000173) open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709637 (+ 0.000378) open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709923 (+ 0.000286) open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.711365 (+ 0.001443) open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 3 1609430221.713293 (+ 0.001928) socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3 1609430221.717419 (+ 0.004126) recvfrom(3, "\362|\201\200\0\1\0\2\0\0\0\0\rnotls20201224\6tihew"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 155 1609430221.717890 (+ 0.000469) recvfrom(3, "\204\207\201\200\0\1\0\1\0\0\0\0\rnotls20201224\6tihew"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 139 1609430221.745659 (+ 0.027772) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 1609430221.747548 (+ 0.001887) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.747858 (+ 0.000308) sendto(3, "ping\n", 5, 0, NULL, 0) = 5 1609430221.748048 (+ 0.000188) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.748330 (+ 0.000282) recvfrom(3, "+PONG\r\n", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 7 +PONG 1609430221.748543 (+ 0.000213) recvfrom(3, "", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 0 1609430221.752110 (+ 0.003569) +++ exited with 0 +++

    上記の例では、コマンドは完了に 54 ミリ秒を若干超える時間がかかりました (752110 - 697712 = 54398 マイクロ秒)。

    nc のインスタンス化と名前解決 (697712 から 717890 まで) には多くの時間 (約 20ms) がかかりました。その後、TCP ソケットの作成には 2ms (745659 から 747858)、リクエストに対する応答の送信と受信には 0.4ms (747858 から 748330) が必要でした。