# KV 和存储

__*Multi Raft Group*__
__*TiKV Region*__
__*RocksDB*__

![`smart`](./student-guide/diagram/TiKVRegionAndStorage_aa_001_20221005.png)

+ `KV`
+ `Region`
+ `Raft Group`
+ `RocksDB`

-------------------------------------------------------------
- 作为数据存储系统，首要要决定的是数据的存储模型，即数据将以何种形式进行保存。TiKV 的选择是 Key-Value 模型，并提供了有序遍历方法。

- TiKV 数据存储的两个关键点：
  - 这是一个巨大的 Map（类比于C++ std::map），即存储键值对(key-value pairs)。
  - 这个 Map 中的 Key-Value pair 按照 KEY 的二进制顺序排序，也就是说，你可以 Seek 到某个 KEY 的位置，然后连续调用 Next 方法以递增的顺序获取大于此KEY的 Key-Value。

- 为了实现存储的水平扩展，数据将分布在多台机器上。TiKV 根据 Key Range 将整个 Key-Value 空间分成许多段。每个段是一系列连续的KEY，每个段称为 Region，并且会尽量保持每个 Region 中保存的数据不超过一定的大小,目前在 TiKV 中默认是 96MB。每个 Region 可以用 [startKey，endKey) 这样一个左闭右开区间来描述。将数据分成 Region 后，TiKV 将执行两个重要的操作：以 Region 为单位将数据分散到集群中的所有节点，并尝试确保每个节点上服务的 Region 数量大致相同；通过 Region 进行 Raft 复制和成员管理。

- 任何持久存储引擎都最终将数据保存在磁盘上，TiKV 也不例外。然而，TiKV 不选择直接将数据写入磁盘，而是将数据保存在 RocksDB 中，而 RocksDB 负责具体的数据落地。之所以做出这个选择，是因为开发单实例存储引擎工作量很大，尤其是要制作出高性能的单实例引擎，需要进行各种精细的优化。RocksDB 是由 Facebook 开源的非常好的单实例 KV 存储引擎，可以满足 TiKV 对单实例引擎的各种需求。在这里，我们可以将 RocksDB 简单地看作是一个独立的持久化 Key-Value 映射。

- 接下来，TiKV 的实施面临着更加困难的任务：如何确保在单个实例故障的情况下数据不会丢失或出错？

- 简而言之，需要找到一种方法将数据复制到多台机器上，以便一台机器无法服务时，其他机器上的副本仍然可以提供服务；在复杂的情况下，这种数据复制解决方案还需要可靠和高效，并能处理副本故障。TiKV 选择了 Raft 算法。Raft 是一种一致性协议。本文仅对 Raft 进行简要介绍，详细内容请参阅其论文。Raft 提供了几个重要功能：Leader 选举、成员更改（如添加副本、删除副本、转移 Leader 等）和日志复制。

- TiKV 使用 Raft 进行数据复制。每次数据更改都将放置在 Raft 日志中。通过 Raft 的日志复制功能，这些数据被安全可靠地同步到副本组的每个节点上。但是，在实际写入时，根据 Raft 协议，只需要同步复制到大多数节点，就可以安全地假定数据已成功写入。


