云上的 TiDB 和 TiFlash

介绍一下 TiFlash 和 TiDB 云服务相关的一些设计思考。

TiFlash Cloud

UniPS 的设计

关于 Delta Index

快速扩容(FAP)

TiFlash 的快速新建副本(FAP)特性

使用 UniPS 替换 RaftEngine

目前 TiKV 使用 engine_traits 描述了一个可以用来作为 raftstore 的存储的 engine 所需要的接口。这些接口基本是基于 RocksDB 而抽象出来的。因此 UniPS 需要模拟出其中关键的特性,例如 WriteBatch 等。

UniPS 的性能劣于 RaftEngine,写入延迟大约是两倍。另外,scan 性能预期也比较差,但是仍有不少优化空间。

另外一点是 UniPS 目前不支持 Delete Range,所以在大批量清理 Raft 日志的时候,我们的 WriteBatch 通常会很大,从而减少

为什么 TiFlash Cloud 目前是两副本?

目前快速恢复还是实验状态。TiFlash 重启后也需要进行一些整理和追日志才能服务,可能影响 HA,这些需要时间优化。尽管如此,快速恢复依然是一个很好的特性,因为:

  1. 快速恢复在 1 wn 下,可以从本节点重启,减少 TiKV 生成 Snapshot 的负担。而这个负担在 v1 版本的 TiKV 上是比较大的。
  2. 减少宕机一个节点恢复后,集群恢复到正常 2 副本的时间。

因为基于 Raft,所以本地数据的丢失只会导致从上一个 S3 Checkpoint 开始回放。如果只有一个存储节点,会失去 HA 特性。

S3 在 TiFlash Cloud 中起到什么作用?

  1. TiFlash Cloud 会定期上传 Checkpoint 到 S3 上,Checkpoint 是一个完整的快照,可以用来做容灾。即使在存储节点宕机后,其上传的那部分数据依然可以被用来查询,可能只能用来服务 stale read?
  2. TiFlash 计算节点可以从 S3 获得数据,相比从存储节点直接获取要更为便宜。存储节点只需要提供一些比较新的数据的读取,减少压力。
  3. 快速扩容逻辑可以复用其他存储节点的数据,此时新节点并不需要从 TiKV 或者其他 TiFlash 获得全部的数据。副本迁移同理,不需要涉及全部数据的移动。

尽管如此,S3 并不是当前 TiFlash 数据的全集。本地会存在:

  1. 上传间隔时间内,还没有上传到 S3 的数据。
  2. 因为生命周期太短,在上传前就被 tombstone 的数据。
  3. 尚在内存中的数据。

我认为使用 S3,是 TiFlash 架构从 shared nothing 走向 shared storage 的一步。我觉得有几个好处:

  • S3 的 durability、ha、跨 az 的能力能省很多很多精力
  • S3 的存储比 ebs 便宜,相应的能够容忍更高的空间方法,因此可以换来更少的 GC 频率,从而节约 CPU
  • 基于 S3 的架构实现 remote compaction 会更加容易

S3 vs EBS

对于 S3 而言:

  1. 具备 99.999999999% 的持久性和 99.99% 的可用性。
    也就是说一天中的不可用时间大约在 9s 左右。
  2. 并发大概在 3500 ops 左右,相比本地磁盘是比较低的
  3. 访问延迟比较高,对于 PutObject 可能能到秒级的延迟

定价

  1. PUT/POST/LIST/COPY 0.005
  2. GET/SELECT 0.0004
  3. 存储每 GB 0.022 USD 每月

可以看到,S3 的定价相比 EBS 要便宜不少。此外,从灾备上来讲,使用 EBS 可能需要为跨 AZ 容灾付出更多的成本,而 S3 可以实现跨 AZ 容灾。

Cloud Storage Engine

目的

  • 存储成本
    不同于 TiFlash 在云上需要两副本保证 HA,TiKV 在云上需要三副本保证容错。如果这三个副本都使用 EBS,那么代价非常高昂。
    从高可用的角度来说,三副本 EBS 是没必要的,完全可以两副本 EBS,另一个副本作为 witness 存在。在 S3 上存放一份数据(SST 文件),本地 EBS 的数据可以作为 S3 数据的 Cache。
    进一步的,如果能够实现三个副本在底层的 SST 完全一样,那么 Compaction 的成本也能降低。【Q】这个我理解就得一个 Region 一个 LSM 了,类似 TiFlash 目前的设计是不太行得通的。
  • 高可用和容错
    关于 TiKV、TiDB、TiFlash 的一些思考中“高可用和持久性”的部分。
  • Region
    因为 shared nothing 版本的 TiKV 的 Snapshot 传输代价大,所以限制了 region 大小为 96MB,目前已经调整了默认值为 256MB。
    但是在云上架构中,新增副本可以通过引用 S3 上的文件来实现,成本接近于 0,所以 Snapshot 的负担就会变小。
    调大 Region Size 减少 Region 数量的优势,在 TiKV 的 partitioned raft kv 特性 中也有提及,这里就省略了。

设计细节

raft log

Raft log 需要存在 EBS 而不是 Local Disk 上,从而保证持久化。

Flush

为了 S3 上只存一个副本,所以 flush 的方案不太一样:

  • Leader flush 得到 L0,
  • Leader 将 L0 传到 S3 上
  • Raft 将这次 flush 复制给其他 follower
    如果这个过程失败了,说明中间 Leader 切换,直接 abort 即可
  • 等该 flush 被 apply 后,才会将 L0 写入到存储里面

Split

Merge