# Raft 日志复制

__*Raft 日志复制*__
__*raft log*__
__*raft 日志*__
__*entry*__

![`smart`](./student-guide/diagram/RaftLogReplication01_aa_001_20220511.png)
-------------------------------------------------------------
下面, 我们描述日志复制:

当客户端（例如 TiDB server ）需要写入某个数据的时候, 会将操作发送给 `Leader` 角色的 `Region`, 这个操作在 TiKV 里面我们叫做 `Propose`。

Leader 会将操作编码成一个 `entry`, 写入到自己的 `Raft Log` 里面, 这个过程我们叫做 `Append`。

对于 `Raft Log`, 我们可以这样简单理解它的格式, 一个 `TiKV` 会有多个 `Regions`, 我们在 `Raft Log` 中会使用 `Region` 的 `ID` 作为 `key` 的前缀, 然后再带上 `Raft Log ID` 来唯一标识一条 `Raft Log`。
- 譬如, 假设现在有两个 `Region`, `ID` 分别为 4 和 5, 那么 `Raft Log` 的格式如下:
```
4_1, log { PUT key = 1, name = tom }
4_2, log { PUT key = 2, name = andy }
4_3, log { PUT key = 1, name = jack }
...
4_N, log { DEL key = 3 }
5_1, log { PUT key = 100, name = tim }
5_2, log { PUT key = 100, name = jim }
5_3, log { PUT key = 200, name = tony }
...
5_N, log { PUT key = 100, name = mark }
```

Leader 也会通过 `Raft` 算法将 `entry` 复制到其他的 `Follower` 上, 这个操作我们叫做 `Replicate`。

`Follower` 收到这个 `entry` 之后也会同样进行 `Append` 操作, 并且会告知 Leader 成功（`Append` 指的是将 `entry` 写入自己的 `Raft Log` 中, 并不是应用这个 `entry`）。

当 Leader 发现这个 `entry` 已经被大多数节点 `Append`, 就认为这个 `entry` 已经是 `Committed` 的了, 然后就可以将 `entry` 里面的操作解码出来, 执行并且应用到数据持久化存储引擎中, 这个操作我们叫做 `Apply`。
