# 数据的读取 ReadIndex Read

__*TiKV 读取*__
__*数据读取*__
__*ReadIndex Read*__
__*ReadIndex*__

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

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

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

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

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

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


