# 数据的读取 Lease Read

__*Lease Read*__

![left](./student-guide/diagram/LeaseRead01_aa_001_2022051.png)
-------------------------------------------------------------
我们回顾一下刚才介绍的 ReadIndex Read,发现其中有一个步骤（第 2 步）就是当读取请求到达当前节点后,需要本节点向其他节点发起一次 heartbeat,如果大多数节点返回了对应的 heartbeat 回应（  heartbeat response ）,那么 leader 就能够确定现在自己仍然是 leader。这个步骤需要耗费一定的网络开销,虽然单个 heartbeat 的开销比较低。Lease Read / Local Read 的优化也正是基于这个步骤开展的,它是这样进行的:

首先,在 "Raft - Leader 选举" 中我们介绍了一个概念,就是  heartbeat time interval ( leader 发送心跳间隔时间 ),要求 heartbeat time interval 小于 min ( election timeout )。也就是 leader 会每隔一个 heartbeat time interval 发送 heartbeat,我们记录这个时间点为 start,如果多数派 follower 都给了 heartbeat response（ 此时可以去确定 leader 还是此节点 ）, 由于 Raft 的选举机制,follower 会在至少 election timeout 的时间之后,才发起重新选举,所以说,就算是发生了选举,新 leader 也要在 election timeout / clock drift bound 这段时间被选举出来。那么,从 start 到 election timeout / clock drift bound,这段时间 leader 依然是本节点,我们管这段时间叫做 lease,也可以叫做租期。那么在一个 lease （租期）内,节点不需要通过发出 heartbeat 就可以确定自己依然是 leader 节点。这样一来,我们没有必要再去像 ReadIndex Read  那样,通过发送 heartbeat 来确定当前是否为 leader 了,从而提高了效率。

其次,这里我们有 2 个点需要我们注意到:

1. 各个 TiKV 服务器的 CPU clock 的时间是准的,误差不能太大,如果各个服务器的 clock 频率不同,lease 机制就会出现问题。如果这种情况,我们还可以使用 ReadIndex。

2. TiKV 实际并没有通过 heartbeat 来更新 lease,而是通过写操作。由于对于任何的写入操作,都会走一次 Raft log,所以我们在发起 （ propose ） 这次 write 请求的时候,记录下当前的时间戳 start,然后等到对应的请求 apply 之后,我们就可以续约 leader 的 lease。

最后,IndexRead 和 Lease Read 目前在 TiKV 都是支持的。