保存数据
待解决的问题
- 基本要求:保证数据不丢不错
- 能否支持跨数据中心的容灾
- 写入速度是否够快?
- 数据保存下来后,是否方便读取?
- 保存的数据如何修改?如何支持并发的修改?
- 如何原子地修改多条记录?
数据的存储模型
Key-Value
TiKV选择的是Key-Value模型,并提供有序的便利方法。
简单来讲,可以将 TiKV 看做一个巨大的 Map,其中 Key 和 Value 都是原始的 Byte 数组,在这个 Map 中,Key 按照 Byte 数组总的原始二进制比特位比较顺序排列。
因为键值对是按照Key的二进制顺序来存储的,所以也就是找到某一个Key的位置后,可以不断的调用Next方法递增的获取比这个Key大的Key-Value。
RocksDB
任何持久化的存储引擎,数据终归要保存在磁盘上,TiKV 也不例外。
TiKV 没有选择直接向磁盘上写数据,而是把数据保存在 RocksDB 中,具体的数据落地由 RocksDB 负责。
RocksDB是一个非常优秀的开源单机存储引擎,有Facebook的团队在做持续的优化,可以认为RocksDB是一个单机的Key-Value Map。
Raft
前述已经已经解决了数据高效可靠的本地存储。但如何保证单机失效的情况下,数据不丢失,不出错?
简单来说,我们需要想办法把数据复制到多台机器上,这样一台机器挂了,我们还有其他的机器上的副本;复杂来说,我们还需要这个复制方案是可靠、高效并且能处理副本失效的情况。听上去比较难,但是好在我们有 Raft 协议。Raft 是一个一致性算法,它和 Paxos 等价,但是更加易于理解。
在分布式系统的Raft算法中详细说明了Raft算法的原理,并做了动画演示,文末也有Raft论文的地址。
PingCAP的首席架构师唐刘的文章详细的解释了他们对Raft协议所做的大量优化。
总结一下,通过单机的 RocksDB,我们可以将数据快速地存储在磁盘上;通过 Raft,我们可以将数据复制到多台机器上,以防单机失效。数据的写入是通过 Raft 这一层的接口写入,而不是直接写 RocksDB。