Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 23 additions & 20 deletions follower-read.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,26 @@ aliases: ['/docs-cn/dev/follower-read/','/docs-cn/dev/reference/performance/foll

# Follower Read

为了高可用和数据安全,TiKV 中的数据有多个副本,其中有一个 leader 和多个 follower,默认情况下读写都发生在 leader 上,Follower Read 功能使得 follower 可以提供读取能力
在 TiDB 中,为了保证高可用和数据安全,TiKV 会为每个 Region 保存多个副本,其中一个为 leader,其余为 follower。默认情况下,所有读写请求都由 leader 处理。Follower Read 功能允许在保持强一致性的前提下,从 Region 的 follower 副本读取数据,从而分担 leader 的读取压力,提升集群整体的读吞吐量

Follower Read 功能适用于以下场景:
在执行 Follower Read 时,TiDB 会根据拓扑信息选择合适的副本。具体来说,TiDB 使用 `zone` label 判断一个副本是否为本地副本:当 TiDB 与目标 TiKV 的 `zone` label 相同时,TiDB 认为该副本是本地副本。更多信息可参考[通过拓扑 label 进行副本调度](schedule-replicas-by-topology-labels.md)。

- 希望通过 follower 打散读热点。
- 希望通过读取本地副本节省流量。
通过让 follower 参与数据读取,Follower Read 可以实现以下目标:

> **说明:**
>
> TiDB 使用 `zone` label 来判断本地副本,当目标 TiKV 和 TiDB 的 `zone` label 相同时,TiDB 认为这是一个本地的 TiKV,详情可以参考[通过拓扑 label 进行副本调度](schedule-replicas-by-topology-labels.md)文档。
- 分散读热点,减轻 leader 负载。
- 在多可用区或多机房部署中,优先读取本地副本以减少跨区流量。

## 适用场景

## 概述
Follower Read 适用于以下场景:

Follower Read 功能是指在强一致性读的前提下使用 Region 的 follower 副本来承载数据读取的任务,从而提升 TiDB 集群的吞吐能力并降低 leader 负载。Follower Read 包含一系列将 TiKV 读取负载从 Region 的 leader 副本上 offload 到 follower 副本的负载均衡机制。TiKV 的 Follower Read 可以保证数据读取的一致性,可以为用户提供强一致的数据读取能力。
- 读请求量大、存在明显读热点的业务。
- 多可用区部署中,希望优先读取本地副本以节省带宽的场景。
- 在读写分离架构下,希望进一步提升集群整体读性能的场景。

> **注意:**
>
> 为了获得强一致读取的能力,在当前的实现中,follower 节点需要向 leader 节点询问当前的执行进度(即 `ReadIndex`),这会产生一次额外的网络请求开销,因此目前 Follower Read 的主要优势在于大量读取数据场景以及将集群中的读请求与写请求隔离开,并提升整体的读吞吐量
> 为确保读取结果的强一致性,Follower Read 在读取前需要与 leader 通信以确认当前的提交进度(即执行 Raft `ReadIndex` 操作),该过程会带来一次额外的网络交互。因此,当业务中存在大量读请求或需要读写隔离时,Follower Read 的效果最为显著;但对于低延迟的单次查询,性能提升可能不明显

## 使用方式

Expand All @@ -40,15 +41,15 @@ set [session | global] tidb_replica_read = '<目标值>';

默认值:leader

该变量用于设置期待的数据读取方式。从 v8.5.4 开始只对只读 SQL 生效
该变量用于设置期待的数据读取方式。从 v8.5.4 开始,该变量仅对只读 SQL 语句生效

通过读取本地副本节省流量的使用场景推荐的设置为
在需要通过读取本地副本节省跨区流量的场景下,推荐如下配置

- 默认值 `leader` 的性能最好。
- `closest-adaptive` 在最小性能损失的前提下尽可能节省流量。
- `closest-replicas` 可以节省最多的流量
- `closest-replicas` 可以最大程度地节省网络流量

对于其他正在使用的其他配置,可参照下表映射关系修改为推荐配置。
如果当前正在使用其他配置,可参考下表修改为推荐配置:

| 正在使用配置 | 推荐修改的配置 |
| ------------- | ------------- |
Expand Down Expand Up @@ -82,13 +83,13 @@ set [session | global] tidb_replica_read = '<目标值>';

## 基本监控

通过观察相关监控,可以帮助判断是否需要使用 Follower Read 和打开 Follower Read 之后的效果
通过观察相关监控,可以帮助判断是否需要使用 Follower Read 以及开启 Follower Read 后的效果

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个小节没有写去哪里观察哪个监控指标,可以判断是否需要使用 Follower Read 以及开启 Follower Read 后的效果。

## 实现机制

在 Follower Read 功能出现之前,TiDB 采用 strong leader 策略将所有的读写操作全部提交到 Region 的 leader 节点上完成。虽然 TiKV 能够很均匀地将 Region 分散到多个物理节点上,但是对于每一个 Region 来说,只有 leader 副本能够对外提供服务,另外的 follower 除了时刻同步数据准备着 failover 时投票切换成为 leader 外,没有办法对 TiDB 的请求提供任何帮助。

为了允许在 TiKV 的 follower 节点进行数据读取,同时又不破坏线性一致性和 Snapshot Isolation 的事务隔离,Region 的 follower 节点需要使用 Raft `ReadIndex` 协议确保当前读请求可以读到当前 leader 节点上已经 commit 的最新数据。在 TiDB 层面,Follower Read 只需根据负载均衡策略将某个 Region 的读取请求发送到 follower 节点。
Follower Read 包含一系列将 TiKV 读取负载从 Region 的 leader 副本上 offload 到 follower 副本的负载均衡机制。为了允许在 TiKV 的 follower 节点进行数据读取,同时又不破坏线性一致性和 Snapshot Isolation 的事务隔离,Region 的 follower 节点需要使用 Raft `ReadIndex` 协议确保当前读请求可以读到当前 leader 节点上已经 commit 的最新数据。在 TiDB 层面,Follower Read 只需根据负载均衡策略将某个 Region 的读取请求发送到 follower 节点。

### Follower 强一致读

Expand All @@ -98,22 +99,24 @@ TiKV follower 节点处理读取请求时,首先使用 Raft `ReadIndex` 协议

### Follower 副本选择策略

由于 TiKV 的 Follower Read 不会破坏 TiDB Snapshot Isolation 事务隔离级别,因此 TiDB 在第一次选取副本时会根据 `tidb_replica_read` 的要求进行选择。从第二次重试开始,TiDB 会以完成读取为优先目标,因此当选中的 follower 节点出现无法访问的故障或其他错误时,会切换到 leader 提供服务。
Follower Read 不会破坏 TiDB 的事务隔离级别(Snapshot Isolation)。TiDB 在第一次选取副本时会根据 `tidb_replica_read` 的配置进行选择。从第二次重试开始,TiDB 会优先保证读取成功,因此当选中的 follower 节点出现无法访问的故障或其他错误时,会切换到 leader 提供服务。

#### `leader`

- 选择 leader 副本进行读取,不考虑副本位置。

#### `closest-replicas`

- 当和 TiDB 同一个 AZ 的副本是 leader 节点时,不使用 Follower Read。
- 当和 TiDB 同一个 AZ 的副本不是 leader 节点时,使用 Follower Read。

#### `closest-adaptive`

- 如果预估的返回结果不够大,使用 `leader` 策略,不进行 Follower Read。
- 如果预估的返回结果足够大,使用 `closest-replicas` 策略。

### Follower Read 的性能开销

因为 Follower Read 需要一次额外的 `ReadIndex` 来保证强一致,所以会不可避免的消耗更多的 TiKV CPU。
因为一次 Follower Read 不管读取多少数据,都需要一次 `ReadIndex`,所以在小的 worklo查询ad 中,Follower Read 的性能损耗较为明显,同时因为对小查询进行本地读取能节省的流量有限,所以我们更加推荐在较大查询的场景使用 Follower Read。
为了保证数据强一致性, Follower Read 不管读取多少数据,都需要执行一次 `ReadIndex`,这将不可避免的消耗更多的 TiKV CPU 资源。因此,在小查询(如点查)场景下,Follower Read 的性能损耗相对更明显。同时,因为对小查询进行本地读取能节省的流量有限,更推荐在大查询或批量读取场景中使用 Follower Read。

使用 `closest-adaptive` 时,会自动对较小的查询不使用 Follower Read,在各种 workload 中相比 `leader` 策略的 TiKV CPU 的额外开销一般在 +10% 之内。
当 `tidb_replica_read` 为 `closest-adaptive` 时,TiDB 针对小查询时不会使用 Follower Read,从而在各种工作负载下中相比 `leader` 策略的 TiKV CPU 的额外开销一般在 +10% 之内。
2 changes: 1 addition & 1 deletion system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -4811,7 +4811,7 @@ EXPLAIN FORMAT='brief' SELECT COUNT(1) FROM t WHERE a = 1 AND b IS NOT NULL;
- 类型:枚举型
- 默认值:`leader`
- 可选值:`leader`、`follower`、`leader-and-follower`、`prefer-leader`、`closest-replicas`、`closest-adaptive` 和 `learner`。其中,`learner` 从 v6.6.0 开始引入。
- 这个变量用于控制 TiDB 的 Follower Read 功能的行为。从 v8.5.4 开始,该变量只对只读 SQL 生效
- 这个变量用于控制 TiDB 的 Follower Read 功能的行为。从 v8.5.4 开始,该变量仅对只读 SQL 语句生效
- 关于使用方式与实现原理,见 [Follower Read](/follower-read.md)。

### `tidb_request_source_type` <span class="version-mark">从 v7.4.0 版本开始引入</span>
Expand Down
Loading