Follower Read
このドキュメントでは、 Follower Read を使用してクエリ パフォーマンスを最適化する方法について説明します。
導入
TiDB はリージョン基本単位として、クラスター内のすべてのノードにデータを配布します。リージョンには複数のレプリカを含めることができ、レプリカはリーダーと複数のフォロワーに分かれています。リーダーのデータが変更されると、TiDB はフォロワーに同期的にデータを更新します。
デフォルトでは、TiDB は同じリージョンのリーダーでのみデータの読み取りと書き込みを行います。リージョンで読み取りホットスポットが発生すると、リージョンリーダーがシステム全体の読み取りボトルネックになる可能性があります。このような状況では、Follower Read機能を有効にすると、リーダーの負荷を大幅に軽減し、複数のフォロワー間で負荷を分散することでシステム全体のスループットを向上させることができます。
いつ使うか
読み取りホットスポットを減らす
アプリケーションにTiDB ダッシュボード キー ビジュアライザー ページのホットスポットリージョンがあるかどうかを視覚的に分析できます。「メトリック選択ボックス」をRead (bytes)
またはRead (keys)
に選択すると、読み取りホットスポットが発生しているかどうかを確認できます。
ホットスポットの処理の詳細については、 TiDB ホットスポット問題の処理参照してください。
読み取りホットスポットが避けられない場合、または変更コストが非常に高い場合は、Follower Read機能を使用して、フォロワーリージョンへの読み取り要求のバランスをより適切にロードしてみてください。
地理的に分散した展開のレイテンシーを削減
TiDB クラスターが複数の地区またはデータセンターにまたがって展開されている場合、リージョンの異なるレプリカは異なる地区またはデータセンターに分散されます。この場合、 Follower Read をclosest-adaptive
またはclosest-replicas
に設定して、TiDB が現在のデータセンターからの読み取りを優先できるようにすることができます。これにより、読み取り操作のレイテンシーとトラフィック オーバーヘッドが大幅に削減されます。実装の詳細については、 Follower Read参照してください。
Follower Readを有効にする
- SQL
- Java
Follower Read を有効にするには、変数tidb_replica_read
(デフォルト値はleader
) をfollower
、 leader-and-follower
、 prefer-leader
、 closest-replicas
、またはclosest-adaptive
に設定します。
SET [GLOBAL] tidb_replica_read = 'follower';
この変数の詳細についてはFollower Read使用状況参照してください。
JavaでFollower Read を有効にするには、 FollowerReadHelper
クラスを定義します。
public enum FollowReadMode {
LEADER("leader"),
FOLLOWER("follower"),
LEADER_AND_FOLLOWER("leader-and-follower"),
CLOSEST_REPLICA("closest-replica"),
CLOSEST_ADAPTIVE("closest-adaptive"),
PREFER_LEADER("prefer-leader");
private final String mode;
FollowReadMode(String mode) {
this.mode = mode;
}
public String getMode() {
return mode;
}
}
public class FollowerReadHelper {
public static void setSessionReplicaRead(Connection conn, FollowReadMode mode) throws SQLException {
if (mode == null) mode = FollowReadMode.LEADER;
PreparedStatement stmt = conn.prepareStatement(
"SET @@tidb_replica_read = ?;"
);
stmt.setString(1, mode.getMode());
stmt.execute();
}
public static void setGlobalReplicaRead(Connection conn, FollowReadMode mode) throws SQLException {
if (mode == null) mode = FollowReadMode.LEADER;
PreparedStatement stmt = conn.prepareStatement(
"SET GLOBAL @@tidb_replica_read = ?;"
);
stmt.setString(1, mode.getMode());
stmt.execute();
}
}
Followerノードからデータを読み取る場合、 setSessionReplicaRead(conn, FollowReadMode.LEADER_AND_FOLLOWER)
メソッドを使用してFollower Read機能を有効にします。これにより、現在のセッションでLeaderノードとFollowerノード間の負荷を分散できます。接続が切断されると、元のモードに復元されます。
public static class AuthorDAO {
// Omit initialization of instance variables...
public void getAuthorsByFollowerRead() throws SQLException {
try (Connection conn = ds.getConnection()) {
// Enable the follower read feature.
FollowerReadHelper.setSessionReplicaRead(conn, FollowReadMode.LEADER_AND_FOLLOWER);
// Read the authors list for 100000 times.
Random random = new Random();
for (int i = 0; i < 100000; i++) {
Integer birthYear = 1920 + random.nextInt(100);
List<Author> authors = this.getAuthorsByBirthYear(birthYear);
System.out.println(authors.size());
}
}
}
public List<Author> getAuthorsByBirthYear(Integer birthYear) throws SQLException {
List<Author> authors = new ArrayList<>();
try (Connection conn = ds.getConnection()) {
PreparedStatement stmt = conn.prepareStatement("SELECT id, name FROM authors WHERE birth_year = ?");
stmt.setInt(1, birthYear);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Author author = new Author();
author.setId( rs.getLong("id"));
author.setName(rs.getString("name"));
authors.add(author);
}
}
return authors;
}
}
続きを読む
ヘルプが必要ですか?
不和またはスラック 、またはサポートチケットを送信するについてコミュニティに質問してください。