Cloud Spanner 利用時の高遅延の原因を調査する
(2022年1月11日追記: 以下の内容をもとに加筆した記事が Google Cloud ブログに投稿されましたのでこちらをご覧ください。)
GCP サポートの藤井です。
日本のお客様の間でも Cloud Spanner のご利用が広まり、それにともなって Cloud Spanner ご利用時の高遅延の原因に関するお問い合わせも、最近よくいただくようになりました。
今回は、遅延の原因を切り分ける方法や、遅延を改善するための Tips を紹介させていただきます。
高遅延と Cloud Spanner の関連性を確認する
Cloud Console や Cloud Monitoring 内の Spanner のメトリクス上で高遅延が確認できる場合は、Cloud Spanner エンドツーエンドのレイテンシ ガイドにある 「3. Cloud Spanner API」 と 「4. Cloud Spanner Database」 のいずれかが原因となっており、Cloud Spanner のレイヤーで調査と対応を行います。
逆に Cloud Spanner のメトリクス上で高遅延が確認できない場合は、遅延の原因は Cloud Spanner へ到達する前の段階で起こっていると考えたほうがよいです。
クライアント側からの計測値として、Cloud Spanner の処理で高遅延が観測された場合、そのタイミングで以下についてご確認ください。
- 他のサービスへの通信も遅くなっていなかったか。
- クライアントのマシンでリソースの枯渇が起こっていなかったか。
- 遅延が発生するマシンに偏りがないか。
特に、クライアントに原因があった場合の例としては、
- CPU 使用率が急激にあがるタイミングで高遅延が発生していた(マシン内の他の処理に原因があるかもしれない)。
- Disk I/O の制限に引っかかっていた。
- エフェメラルポートの枯渇により TCP コネクションが確立できずタイムアウト(または高遅延)を起こしていた。
- DNS での名前解決で遅延が発生していた。
などがございます。
また、先程のレイテンシガイド内の Google Front End のレイテンシをキャプチャするにある方法に従って、「2. Google Front End」が 「3. Cloud Spanner API」 を介して「4. Cloud Spanner Database」 よりレスポンスを得始めるまでの時間が計測できます。
もし、ここで高遅延が見られる場合は、GCP 側で調査する必要が出てきます。(ただ、Cloud Spanner のメトリクス上で高遅延がなく、GFE のレイヤーで高遅延が起こる状態は非常に稀です。)
なお、この GFE におけるレイテンシには TCP/SSL handshake は含まれません。クライアント側で高遅延の原因がわからず、また GFE や Cloud Spanner のメトリクスでも高遅延の原因がわからない場合は、パケットキャプチャを取得し、TCP/SSL handshake で予期せぬ時間がかかっていないかを調べる必要があるかもしれません。(これも非常に稀なケースです。)
Cloud Spanner で起こっている高遅延の原因を確認する
Cloud Spanner のメトリクス上で高遅延が発生する場合、まず考えられるのがノード数の不足です。
高 CPU 使用率に関するアラートに推奨値が掲載されていますので、Cloud Console 上でご確認できる CPU 使用率が推奨値内に収まっていることをご確認ください。なお、CPU 使用率に余裕がある状況であれば、優先度の高いタスクは優先度の低いタスクの影響を受けない一方、CPU 使用率が 100% に近くなると、優先度の低いタスクの処理も優先度の高いタスクに影響を及ぼしますのでご注意ください。
CPU 使用率が高い場合は、高 CPU 使用率の調査に沿って、原因となっているクエリを絞り込むことができると思います。
全体の CPU 使用率は高くないのに、高遅延が発生する場合は、ホットスポット問題(特定の領域にのみ高負荷がかかっている)、またはロック待ちが考えられます。
ホットスポットに関しては、Key Visualizer を使用して、頻繁にアクセスしているキーをご確認ください。Cloud Spanner で最適化が起こり遅延が解消していくこともありますが、キー設計やトラフィックのパターンによっては、その最適化では解決できないこともあります。詳細はスキーマ設計をご覧ください。
ロック待ちの調査に関しては、ロックの統計情報のご利用をおすすめします。なお、時間経過とともに詳細情報は取れなくなりますので、問題発生直後に SPANNER_SYS.LOCK_STATS_TOP_MINUTE や SPANNER_SYS.LOCK_STATS_TOP_10MINUTE のテーブルを調査いただく方が、調査の効果は高まります。
また、最近クエリやトランザクションにタグ付けができるようになりました。この機能と、統計情報テーブルを組み合わせることで、高遅延の原因になっているクエリの特定が効率的に行えると思います。
高遅延を抑えるための Tips
上記の方法で、多くの場合は高遅延の原因と対応方針は見えてくると思います。最後に、統計情報や Key Visualizer では気づきにくい遅延の要因を抑える Tip をいくつか紹介いたします。
ステイル読み取りを採用する
Cloud Spanner は、読み取りに対しても、強整合性をデフォルトで担保しています。しかしながら、若干古い情報でも許容される場合には、たった 1 秒程度のステイル読み取りを許容するだけでも大幅にパフォーマンスが改善することがあります。特に更新頻度の高い行を読み取る場合には、効果を実感できるのではないかと思います。
STORING 句を使用して、インデックス内に列のデータを保持する
SELECT 文実行時に FORCE_INDEX により使用するインデックスを指定する場合、STORING 句を使用することで、読み取り時に、インデックスの検索のみで読み取りを完了させ、元テーブルを結合して参照する必要がなくなります。
クエリプラン ビジュアライザを使って、気になるクエリを実行し、Scan Index の latency と、その上位にある Distributed Union や Distributed Cross Apply の latency で乖離が大きい場合は、STROING 句の使用の効果が高いと思います。
データ削除を Partitioned DML で行う
定期的にデータを削除したいといったユースケースもあるかもしれません。その場合には、Partitioned DML を使って削除すれば、削除処理が分散して実行されるため、ロックする範囲を局所化でき、他のトランザクションへの影響を抑えることができます。ただし、注意点としては冪等性が保たれる処理に対して使う必要があります。(実行される度に、結果がどんどん変わってしまうような処理には向きません。)
最後に、p99 での数秒レベルの遅延は起こり得る
99 percentile のレイテンシーが数秒高まったということで、お問い合わせをいただくことがございますが、これはシステム構成上避けられないものもあります。最初に述べたレイテンシ ガイドにある 「3. Cloud Spanner API」は、メンテナンスのため再起動されることがあります。各リージョン内で段階的に行われますが、たまたま再起動が必要なサーバーをリクエストが経由していた場合には、session の引き継ぎが別のサーバーに行われ、その処理に数秒を要します。サーバーの再起動やメンテナンスは、サービス全体の質向上には欠かせない作業であるため、このテイル部分での数秒のレイテンシー増加を抑えることはあいにくできません。
以上となります。これまで把握できていなかった高遅延の原因究明と対策の一助になれば幸いです。