大規模リージョンでの TiKV性能チューニングのベスト プラクティス
TiDB では、データはリージョンに分割され、各リージョンには特定のキー範囲のデータが格納されます。これらのリージョンは、複数の TiKV インスタンスに分散されます。データがクラスターに書き込まれると、数百万のリージョンが作成されることがあります。単一の TiKV インスタンス上のリージョンが多すぎると、クラスターに大きな負荷がかかり、パフォーマンスに影響する可能性があります。
このドキュメントでは、 Raftstore (TiKV のコア モジュール) のワークフローを紹介し、大量のリージョンがパフォーマンスに影響を与える理由を説明し、TiKV のパフォーマンスを調整する方法を示します。
Raftstoreワークフロー
TiKV インスタンスには複数のリージョンがありRaftRaftstoreマシンを駆動してリージョンメッセージを処理します。これらのメッセージには、リージョンでの読み取りまたは書き込み要求の処理、 Raftログの永続化または複製、 Raftハートビートの処理が含まれます。ただし、リージョンの数が増えると、クラスター全体のパフォーマンスに影響する可能性があります。これを理解するには、次に示すRaftstoreのワークフローを理解する必要があります。
注記:
この図はRaftstoreのワークフローを示すものであり、実際のコード構造を表すものではありません。
上の図から、TiDB サーバーからのリクエストは、gRPC およびstorageモジュールを通過した後、KV (キーと値のペア) の読み取りおよび書き込みメッセージになり、対応するリージョンに送信されることがわかります。これらのメッセージはすぐに処理されるのではなく、一時的に保存されます。Raftstoreは、各リージョンに処理するメッセージがあるかどうかをポーリングして確認します。リージョンに処理するメッセージがある場合、 Raftstore はこのリージョンのRaftステート マシンを駆動してこれらのメッセージを処理し、これらのメッセージの状態変化に応じて後続の操作を実行します。たとえば、書き込みリクエストが着信すると、 Raftステート マシンはログをディスクに保存し、他のリージョンのレプリカにログを送信します。ハートビート間隔に達すると、 Raftステート マシンはハートビート情報を他のリージョンのレプリカに送信します。
パフォーマンスの問題
Raftstoreワークフロー図から、各リージョンのメッセージは 1 つずつ処理されます。リージョンの数が多い場合、 Raftstore がこれらのリージョンのハートビートを処理するのに時間がかかり、遅延が発生する可能性があります。その結果、一部の読み取りおよび書き込み要求が時間内に処理されません。読み取りおよび書き込みの負荷が高い場合、 Raftstoreスレッドの CPU 使用率がボトルネックになりやすく、遅延がさらに増加してパフォーマンスに影響する可能性があります。
一般的に、ロードされたRaftstoreの CPU 使用率が 85% 以上になると、 Raftstore がビジー状態になり、ボトルネックになります。同時に、 propose wait duration
数百ミリ秒にまで高くなることもあります。
注記:
- 前述のように、 Raftstoreの CPU 使用率については、 Raftstore はRaftstoreスレッドです。Raftstore がマルチスレッドの場合は、CPU 使用率のしきい値 (85%) を比例して増やすことができます。
- I/O 操作はRaftstoreスレッド内に存在するため、CPU 使用率は 100% に達することはありません。
パフォーマンス監視
Grafana のTiKV ダッシュボードでは、次の監視メトリックを確認できます。
スレッドCPUパネルの
Raft store CPU
基準値:
raftstore.store-pool-size * 85%
未満。Raft Proposeパネルの
Propose wait duration
Propose wait duration
リクエストがRaftstoreに送信されてからRaftstore が実際にリクエストの処理を開始するまでの遅延です。遅延が長いということは、 Raftstoreがビジー状態であるか、追加ログの処理に時間がかかり、 Raftstore が時間内にリクエストを処理できないことを意味します。基準値: クラスターサイズに応じて50~100ms未満
Raft IOパネルの
Commit log duration
Commit log duration
は、 Raftstore が各リージョン内の大多数のメンバーにRaftログをコミットするのにかかる時間です。このメトリックの値が大きく変動する理由としては、次のことが考えられます。- Raftstoreの作業負荷は重いです。
- ログ追加操作が遅いです。
- ネットワークの混雑により、 Raftログをタイムリーにコミットできません。
基準値: 200〜500 ms未満。
パフォーマンスチューニング方法
パフォーマンスの問題の原因を突き止めたら、次の 2 つの側面から解決を試みてください。
- 単一の TiKV インスタンス上のリージョンの数を減らす
- 単一リージョンのメッセージ数を減らす
方法1: Raftstoreの同時実行性を高める
Raftstore はTiDB v3.0 以降、マルチスレッド モジュールにアップグレードされており、 Raftstoreスレッドがボトルネックになる可能性が大幅に減少しています。
デフォルトでは、 Raftstoreではraftstore.store-pool-size
から2
に設定されています。Raftstore でボトルネックが発生した場合は、実際の状況に応じてこの設定項目の値を適切に増やすことができます。ただし、不要なスレッド切り替えのオーバーヘッドが発生しないように、この値を高く設定しすぎないことをお勧めします。
方法2: 休止状態リージョンを有効にする
実際の状況では、読み取りおよび書き込み要求はすべてのリージョンに均等に分散されるわけではなく、いくつかの Region に集中しています。そのため、一時的にアイドル状態の Region のRaftリーダーとフォロワー間のメッセージ数を最小限に抑えることができます。これは Hibernate リージョンの機能です。この機能では、 Raftstore は必要がない場合、アイドル状態の Region のRaftステート マシンにティック メッセージを送信しません。そのため、これらのRaftステート マシンはハートビートメッセージを生成するためにトリガーされず、 Raftstoreのワークロードを大幅に削減できます。
TiKVマスターでは、Hibernate リージョンがデフォルトで有効になっています。この機能は必要に応じて設定できます。詳細については、 Hibernateリージョンを構成するを参照してください。
方法3: Region Merge
有効にする
注記:
TiDB v3.0 以降では
Region Merge
がデフォルトで有効になっています。
Region Merge
有効にしてリージョンの数を減らすこともできます。 Region Split
とは異なり、 Region Merge
スケジュールを通じて隣接する小さなリージョンを結合するプロセスです。データを削除した後、またはDrop Table
またはTruncate Table
ステートメントを実行した後、小さなリージョンや空のリージョンを結合して、リソースの消費を減らすことができます。
次のパラメータを設定してRegion Merge
有効にします。
config set max-merge-region-size 20
config set max-merge-region-keys 200000
config set merge-schedule-limit 8
詳細については、 リージョン結合およびPD 設定ファイルの次の 3 つの構成パラメータを参照してください。
Region Merge
パラメータのデフォルト設定はかなり保守的です。 PD スケジュールのベスト プラクティスで提供されている方法を参照することで、 Region Merge
プロセスを高速化できます。
方法4: TiKVインスタンスの数を増やす
I/O リソースと CPU リソースが十分な場合は、単一のマシンに複数の TiKV インスタンスをデプロイして、単一の TiKV インスタンス上のリージョンの数を減らすか、TiKV クラスター内のマシンの数を増やすことができます。
方法5: raft-base-tick-interval
を調整する
リージョンの数を減らすことに加えて、単位時間あたりのリージョンごとのメッセージ数を減らすことで、 Raftstoreへの負荷を軽減することもできます。たとえば、 raft-base-tick-interval
構成項目の値を適切に増やすことができます。
[raftstore]
raft-base-tick-interval = "2s"
上記の構成では、 raft-base-tick-interval
Raftstore が各リージョンのRaftステートマシンを駆動する時間間隔です。つまり、この時間間隔で、 Raftstore はRaftステートマシンに tick メッセージを送信します。この間隔を増やすと、 Raftstoreからのメッセージの数を効果的に減らすことができます。
ティック メッセージ間のこの間隔によって、 election timeout
とheartbeat
間の間隔も決まることに注意してください。次の例を参照してください。
raft-election-timeout = raft-base-tick-interval * raft-election-timeout-ticks
raft-heartbeat-interval = raft-base-tick-interval * raft-heartbeat-ticks
リージョンフォロワーがraft-election-timeout
間隔以内にリーダーからハートビートを受信しなかった場合、これらのフォロワーはリーダーが失敗したと判断し、新しい選出を開始します。3 は、リーダーがフォロワーにハートビートを送信する間隔です。したがって、 raft-heartbeat-interval
の値を増やすと、 Raftステートマシンから送信さraft-base-tick-interval
ネットワークメッセージの数は減りますが、 Raftステートマシンがリーダーの障害を検出する時間が長くなります。
方法6:リージョンのサイズを調整する
リージョンのデフォルト サイズは 96 MiB ですが、リージョンをより大きなサイズに設定することでリージョンの数を減らすことができます。詳細については、 リージョンパフォーマンスの調整参照してください。
注記:
カスタマイズされたリージョンサイズは、TiDB v6.5.0 より前の実験的機能です。リージョンサイズを変更する必要がある場合は、v6.5.0 以降のバージョンにアップグレードすることをお勧めします。
方法7: Raft通信の最大接続数を増やす
デフォルトでは、TiKV ノード間のRaft通信に使用される接続の最大数は 1 です。この数を増やすと、多数のリージョンの通信負荷が大きいことによるブロックの問題を軽減できます。詳細な手順については、 grpc-raft-conn-num
参照してください。
注記:
不要なスレッド切り替えのオーバーヘッドを削減し、バッチ処理による潜在的な悪影響を軽減するには、数値を
[1, 4]
の範囲内に設定することをお勧めします。
その他の問題と解決策
このセクションでは、その他の問題と解決策について説明します。
PDLeaderの切り替えが遅い
PD は、PDLeaderノードを切り替えた後に PD がすぐにリージョンルーティング サービスを再開できるように、etcd にリージョンメタ情報を保持する必要があります。リージョンの数が増えると、etcd のパフォーマンス問題が発生し、PD がLeaderを切り替えるときに PD が etcd からリージョンメタ情報を取得するのが遅くなります。数百万のリージョンがある場合、etcd からメタ情報を取得するのに 10 秒以上、場合によっては数十秒かかることがあります。
この問題に対処するため、TiDB v3.0 以降、PD ではデフォルトでuse-region-storage
有効になっています。この機能を有効にすると、PD はリージョンメタ情報をローカル LevelDB に保存し、他のメカニズムを通じて PD ノード間で情報を同期します。
PDルーティング情報が時間内に更新されない
TiKV では、pd-worker が定期的にリージョンメタ情報を PD に報告します。TiKV が再起動されるかリージョンリーダーが切り替わると、PD は統計情報を通じてリージョンapproximate size / keys
再計算する必要があります。そのため、リージョンの数が多いと、シングル スレッドの pd-worker がボトルネックになり、タスクが積み重なって時間内に処理されなくなる可能性があります。この状況では、PD は特定のリージョンメタ情報を時間内に取得できないため、ルーティング情報が時間内に更新されません。この問題は実際の読み取りと書き込みには影響しませんが、PD のスケジュールが不正確になり、TiDB がリージョンキャッシュを更新するときに複数のラウンド トリップが必要になる可能性があります。
TiKV Grafanaパネルの[タスク]の下にある[Worker の保留中のタスク]をチェックして、pd-worker にタスクが積み重なっているかどうかを確認できます。通常、 pending tasks
比較的低い値に維持する必要があります。
pd-worker はバージョン3.0.5以降、パフォーマンスが向上するように最適化されています。同様の問題が発生した場合は、最新バージョンにアップグレードすることをお勧めします。
Prometheusはメトリクスのクエリが遅い
大規模クラスターでは、TiKV インスタンスの数が増えるにつれて、Prometheus がメトリックをクエリする圧力が大きくなり、Grafana がこれらのメトリックを表示する速度が遅くなります。この問題を軽減するために、v3.0 以降ではメトリックの事前計算が構成されています。