# 数据的读取 ReadIndex Read

![center](./student-guide/diagram/03-ReadIndex-Read-01-01.png)
-------------------------------------------------------------
谈到读取，TiKV 首先要保证的是线性一致性，所谓线性一致性，例如，在上午 10:00:00 我们将 key = 1，value = Tom 改为了 key = 1，value = Jack 并提交，那么也就是说从上午 10:00:00 以后，我们不可能读到 key = 1，value = Tom 了。

这里，我们先讨论从 leader 读取的情况，我们先看一下一个简化的流程：

假设我们要读取 key = 1，
- 客户端询问 PD 关于 key = 1 所在的 Region
- PD 告知 Leader 所在的 Region 位置（TiKV 节点）
- TiDB Server 将读命令发送给 leader 所在的 TiKV 节点
- Leader 节点接受读命令之后读取 KV RocksDB 然后给客户端返回数据

这时我们要解决的问题只有一个就是，当我们在确认了 leader 以后（第 2 步）一直到读取到（第 4 步）的时候能够确保此节点依然是 leader，而不会在这个过程中出现 leader 角色的切换。

所谓的 ReadIndex Read 就是解决这个问题的，我们看一下具体的流程：
- 当 TiKV 收到读请求时，将当前的日志（raft log）序号 也叫做 commit index 记录到一个变量 ReadIndex 里面。
- 之后，本节点向其他节点发起一次 heartbeat，如果大多数节点返回了对应的 heartbeat 回应（  heartbeat response ），那么 leader 就能够确定现在自己仍然是 leader。反之，我们认为当点的节点已经不是 leader 了，需要 TiDB Server 重新读取。
- 如果确认当前节点是 leader ，则等待日志（ raft log ）被应用，直到日志（ raft log ）的序号，也就是 apply index， 超过了 ReadIndex，这样就能够安全地提供一致性读了。
- 读取 leader 节点的 RocksDB，将结果返回给 TiDB Server。

到这里，我们介绍了 ReadIndex Read，后面我们要说明的  follower read 功能，也是借助它实现的。下面我们先介绍对于 ReadIndex Read 的一种优化方法，它叫 Lease Read，或者叫做 Local Read。