コンテンツに移動
データベース

Cloud Spanner の DEADLINE_EXCEEDED エラーを解決するための手順ガイド

2022年3月23日
https://storage.googleapis.com/gweb-cloudblog-publish/images/GCP_Twitter_Card-20001000_jGrfo57.max-2000x2000.png
Google Cloud Japan Team

※この投稿は米国時間 2022 年 3 月 23 日に、Google Cloud blog に投稿されたものの抄訳です。

Cloud Spanner API にアクセスすると、「期限を超過」エラーが原因でリクエストに失敗することがあります。このエラーは、あらかじめ構成されているタイムアウト時間内にレスポンスが取得されなかったことを示します。

期限を超過エラーは、Cloud Spanner インスタンスの過負荷、最適化されていないスキーマやクエリなど、さまざまな理由で発生します。今回の投稿では、期限を超過エラーが発生する可能性があるシナリオをいくつか紹介するとともに、こうした問題を調査して解決するためのヒントについて説明します。

Cloud Spanner の期限と再試行ルール

Cloud Spanner の期限と再試行ルールは、他の多くのシステムと異なります。Cloud Spanner では、レスポンスが有効とされる最長時間としてユーザーが期限を指定する必要があります。同じオペレーションを即座に再試行するためだけに期限を人為的に短くすることは推奨されていません。オペレーションがいつまでも完了しない原因となるためです。これを踏まえると、以下の戦略はむしろ逆効果であり、Cloud Spanner 内部の再試行の動作に悪影響を及ぼします。

  • 再試行しても成功の結果を返せないため、完了に 2 秒かかるオペレーションの期限を 1 秒に設定しても意味がありません。

  • オペレーションをキャンセル、再試行すると試行のたびに無駄な作業が発生します。これらが原因となり、ユーザー インスタンスに多大な負荷が余計にかかることになります。

DEADLINE_EXCEEDED エラーとは

ユーザーがいずれかの Cloud Spanner クライアント ライブラリを使用すると、基盤となる gRPC レイヤーが通信、マーシャリング、マーシャリングの解除、期限の適用を処理します。ユーザー アプリケーションは期限を使用してリクエストが完了するまでの待機時間を指定できます。待機時間が過ぎると DEADLINE_EXCEEDED エラーでリクエストが終了されます。

以下のガイドでは、サポートされている各 Cloud Spanner クライアント ライブラリで期限(タイムアウト)を指定する方法を紹介しています。Cloud Spanner クライアント ライブラリでは、次の構成ファイルで定義されているデフォルトのタイムアウト ポリシー設定と再試行ポリシー設定が使用されます。

gRPC の期限の詳細についてはこちらをご覧ください。

DeadlineExceeded エラーの一般的なケースの調査と解決策

Cloud Spanner インスタンス

Cloud Spanner インスタンスはユーザー固有のワークロードに合わせて適切に構成する必要があります。以降のセクションでは、構成の問題を特定して解決する方法について説明します。

Cloud Spanner インスタンスの CPU 負荷の確認

CPU 使用率が推奨されている正常なしきい値を超えると、リクエストのレイテンシが大幅に増加することがあります。Cloud Spanner の CPU 使用率は Cloud Console に用意されているモニタリング コンソールで確認できます。インスタンスの CPU 使用率に基づいてアラートを作成できます。

解決策

以下のガイドでは、インスタンスの CPU 使用率を下げるための手順を紹介しています。

リクエストのエンドツーエンド レイテンシの内訳の確認

リクエストがクライアントから Cloud Spanner サーバー、バックエンドへと送られていくなかで、クライアント ライブラリから Google Front End、Google Front End から Cloud Spanner API Front End、Cloud Spanner API Front End から Cloud Spanner Database といった、複数のデータホップが発生します。これらのステージのいずれかでネットワークの問題があると、期限を超過エラーが表示されることがあります。

各ステージのレイテンシをキャプチャできます(レイテンシ ガイドを参照)。以下のガイドに沿って操作することで、レイテンシの問題の診断方法に関する詳細を確認できます。

解決策

取得したレイテンシの内訳をもとにして、この判断ガイドに沿ってレイテンシの問題をトラブルシューティングできます。

Data API

Cloud Spanner のデータ API の最適ではない使用パターンによっては、期限を超過エラーが発生することがあります。以降のセクションでは、こうしたパターンを確認する方法について説明します。

コストの高いクエリの確認

クライアント ライブラリで構成されている期限に従っていない、コストの高いクエリをユーザーが実行しようとしている場合があります。大規模なテーブルのフルスキャン、複数の大規模なテーブルのクロス結合、キー以外の列に対する述語付きクエリの実行(およびテーブルのフルスキャン)などが例として挙げられますが、これらに限定されません。

クエリの統計情報テーブルとトランザクションの統計情報テーブルを使用してコストの高いクエリを調査できます。平均読み取り行数、平均読み取りバイト数、平均スキャン行数など、実行に時間がかかっているクエリ / トランザクションに関する情報がこれらのテーブルに表示されます。また、クエリ実行プランを生成して、クエリの実行方法をさらに詳しく調査できます。

解決策

以下のガイドでは SQL クエリのベスト プラクティスを紹介しています。さきほど紹介した統計情報テーブルと実行プランから取得したデータを活用することで、クエリを最適化してスキーマの変更をデータベースに反映できます。こうすることでステートメントの実行時間が短縮され、場合によっては期限の超過エラーが解消されます。

ロックの競合の確認

Cloud Spanner のトランザクションは commit するためにロックを取得する必要があります。スループットが高い状態で実行されているアプリケーションでは、同じリソースでトランザクションが競合することがあります。これが原因で、ロックを取得するための待ち時間が長くなり、全体的なパフォーマンスに影響を及ぼします。その結果、読み取りリクエストと書き込みリクエストで期限を超過する場合があります。

解決策

プレーンな読み取りの場合、読み取り専用トランザクションを使用します。たとえば、特定のアルバムのすべての曲を読み取った後でアルバムのウェブページにそれらを表示する場合などに発生する、書き込みによるロックの競合を回避できます。  書き込みワークフロー、または読み取りと書き込みが混在するワークフローの場合のみ、読み取り / 書き込みトランザクションを使用することをおすすめします。ロックの統計情報テーブルを使用し、こちらのブログ投稿に沿って操作すると、レイテンシが高い読み取り / 書き込みトランザクションの根本原因を特定できます。ロックの待ち時間が最も長い行キーがこのテーブルに表示されます。こちらのトラブルシューティング ガイドでは、ロックの競合に関係する列にアクセスしているトランザクションを特定する方法を紹介しています。また、以下のガイドでは、ロックの競合を減らすためのベスト プラクティスを紹介しています。これらのガイドに沿って操作することで、トランザクション実行時間の全体的なレイテンシが改善され、期限の超過エラーが減少します。

最適化されていないスキーマの確認

最適なスキーマをデザインするには、Cloud Spanner で実行されることになるクエリについて考慮する必要があります。スキーマが最適ではないと、一部のクエリでパフォーマンスの問題が発生する場合があります。そのデメリットは小さくなく、構成された期限内にリクエストが完了しなくなります。

解決策

最適なスキーマ デザインがどのようなものかは、データベースに対して行われる読み取りと書き込みによって異なります。スキーマの仕様に関係なく、スキーマ デザインのベスト プラクティス ガイドと SQL のベスト プラクティス ガイドに沿って操作してください。これらのガイドに沿って操作することで、最も一般的なスキーマ デザインの問題を回避できます。主キーの選択、テーブルのレイアウト(アクセスを高速化するためのインターリーブ テーブルの使用)、パフォーマンス向上のためのスキーマの最適化、ユーザー インスタンス内で構成されたノードのパフォーマンスの把握(リージョンの上限マルチリージョンの上限)などもパフォーマンス低下の根本原因となります。

ホットスポットの確認

Cloud Spanner は分散型データベースであるため、ホットスポットが発生しないようにスキーマをデザインする必要があります(スキーマ デザインのベスト プラクティスを参照)。たとえば、単調増加する列を作成すると、ワークロードを均等に分散するために Cloud Spanner で使用できるスプリットの数が制限されます。こうしたボトルネックがタイムアウトにつながる場合があります。

解決策

さきほどのセクションで紹介した問題を解決したら、次は最適化されていないスキーマの問題に対処します。ベスト プラクティス ガイドに沿って操作することでホットスポットを防ぐこともできます。最後に、Key Visualizer を活用することで、ホットスポットを原因とするパフォーマンスの問題を解決します。

誤って構成されているタイムアウトの確認

クライアント ライブラリは、Cloud Spanner のすべてのリクエストに対応する適切なデフォルト設定を用意しています。ただし、ユーザー固有のワークロードに合わせてこうした設定の調整が必要になる場合がありますので、ユーザークエリのコストを確認し、特定のユースケースに合わせて期限を調整することをおすすめします。

解決策

大半のユースケースではデフォルトのタイムアウト設定で問題ありません。ユーザーはこれらの構成をオーバーライド(カスタム タイムアウトおよび再試行ガイドを参照)できますが、デフォルトよりもかなり短いタイムアウトを使用することは推奨されていません。ユーザー アプリケーションでタイムアウトが構成されている場合は、デフォルトをそのまま使用するか、タイムアウトを長めに構成してみることをおすすめします。

Admin API

管理リクエストは Data API に比べてコストの高いオペレーションです。CreateInstanceCreateDatabaseCreateBackups などのリクエストは結果が返されるまでに長い秒数を要することがあります。Google Cloud のクライアント ライブラリでは管理リクエストの期限が長めに設定されています(インスタンスデータベースどちらでも 60 分)。これは、クライアントで再試行 / 失敗を発生させることなく、サーバーでリクエストを完了できるようにするための措置です。

Cloud Spanner で処理する必要があるバックグラウンド作業が原因で管理オペレーションに時間がかかることもあります。たとえば、データがある既存のテーブルにセカンダリ インデックスを作成した場合、Cloud Spanner では既存の行に対してインデックス エントリをバックフィルする必要があります。

解決策

Admin API の使用中に期限を超過エラーが発生した場合は、Cloud Spanner インスタンスの CPU 負荷を確認することをおすすめします。管理オペレーションを早く完成させるためにインスタンスが過負荷になっていないことをユーザーが確認する必要があります。

Cloud Console

Cloud Console クエリページから発行されたクエリは 5 分を超過してはなりません。この時間を超える高コストクエリをユーザーが作成すると、次のようなエラー メッセージが UI に直接表示されます。

https://storage.googleapis.com/gweb-cloudblog-publish/images/20220714.max-700x700.png

失敗したクエリはバックエンドによってキャンセルされ、必要に応じてトランザクションがロールバックされる場合があります。

解決策

SQL クエリのベスト プラクティスに従ってクエリを書き換えます。

Dataflow

Apache Beam では、読み取りオペレーションのデフォルトのタイムアウト構成が 2 時間となっており、commit オペレーションではこの時間が 15 秒となっています。この構成は、スタンドアロン クライアント ライブラリよりも長い時間オペレーションを行うためのものです。ただし、作業アイテムが大きすぎる場合はタイムアウトが発生することがあります。現時点では、必要に応じてカスタマイズできるのは commit タイムアウト構成のみです。

解決策

ReadFromSpanner / クエリの実行 / Cloud Spanner からの読み取り / パーティションからの読み取りのステップで期限の超過エラーが発生している場合は、大量の行をスキャンしたのがどのクエリかをクエリの統計情報テーブルで確認することをおすすめします。その後、当該のクエリを修正することで実行時間を短縮できます。

次の例のような例外がエラーとしてユーザーに表示される場合もあります。

読み込んでいます...

作業アイテムが大きすぎるとこうしたタイムアウトが発生します。上記のケースでは次の 2 つの推奨事項が役立ちます。まず、シャッフル サービスがまだ有効になっていない場合は有効にします。次に、maxPartitionspartitionSizeBytes(詳細はこちら)など、Spanner Read の構成を微調整して、作業アイテムのサイズを小さくします。これを行う方法の例はこちらで確認できます。

トラブルシューティングに関するその他のリソース

ここまでの解決策を実施しても期限の超過エラーが解消されない場合は、エンドツーエンドのレイテンシの内訳を見ることで、サポートケースをオープンする必要があるかどうかを判断できます(完全なリストはレイテンシの問題をトラブルシューティングするを参照)。

  • Google Front End のレイテンシが高く、Cloud Spanner API のリクエストのレイテンシが低い場合はサポート チケットを起票してください。

  • Cloud Spanner API のリクエストのレイテンシが高く、クエリのレイテンシが低い場合はサポート チケットを起票してください。

以下のリソースも参考にしてみてください。


- シニア ソフトウェア エンジニア Sneha Shah
- ソフトウェア エンジニア Thiago Tasca Nunes

投稿先