未来数据库趋势-Tidb

引言

  • 未来数据库趋势:大一统,就像《魔戒》中说的 :ONE RING TO RULE THEM ALL,就是一套解决方案去解决扩展性,ACID,高性能,稳定性,大数据,机器学习计算能力(HATP+分布式)。

  • 目前大多数的科研论文陷入跑分思维,在一个特定的 Workload下,然后把 Oracle 摁在地上摩擦,这样的论文有很多。但是大家回头看看 Oracle 还是王者。

  • 紧跟现实应用场景(这是典型的工程思维,科研应该在理论上有所突破)

未来发展的基石

  • 硬件的发展:SDD,多核CPU,万兆网卡,虚拟化。
  • 数据库这个行业里面很多的假设,在现在新的硬件的环境下其实都是不成立的。
  • 为什么 B-Tree 就一定会比 LSM-Tree 要快呢?不一定,我跑到 Flash 或者 NVMe SSD 、Optane 甚至未来的持久化内存这种介质上,那数据结构设计完全就发生变化了。过去可能需要投入很多精力去做的数据结构,现在可以采用暴力算法。
  • 分布式理论的发展,如raft

未来趋势

1. log is the new database

  • Hyper实验中正常的 SQL 语句的执行时间,比如说直接把一语句放到另外一个库里去执行,耗时最多。逻辑日志存放时,耗时大概能快 23%,存放物理日志时能快 56%。所以TiDB 里的 TiFlash 其实同步的是 Raft 日志,而并不是同步 Binlog 或者其他。
  • Aurora同步的是 redo log 。其实他的好处也很明显,也比较直白,就是 I/O 更小,网络传输的 size 也更小,所以就更快。
  • 多raft 组

    2. Vectorized

  • TiDB SQL 引擎用 Volcano 模型,这个模型遍历一棵物理计划的树,不停的调 Next,每一次 Next 都是调用他的子节点的 Next,然后再返回结果。这个模型有几个问题:第一是每一次都是拿一行,导致 CPU 的 L1、L2 缓存利用率很差,没有办法利用多 CPU 的 Cache。第二,在真正实现的时候,它内部的架构是一个多级的虚函数调用。大家知道虚函数调用在 Runtime 本身的开销是很大的,在《MonetDB/X100: Hyper-Pipelining Query Execution》(http://cidrdb.org/cidr2005/papers/P19.pdf) 里面提到,在跑 TPC-H 的时候,Volcano 模型在 MySQL 上跑,大概有 90% 的时间是花在 MySQL 本身的 Runtime 上,而不是真正的数据扫描。所以这就是 Volcano 模型一个比较大的问题。第三,如果使用一个纯静态的列存的数据结构,大家知道列存特别大问题就是它的更新是比较麻烦的, 至少过去在 TiFlash 之前,没有一个列存数据库能够支持做增删改查。那在这种情况下,怎么保证数据的新鲜?这些都是问题。
  • TiDB SQL 引擎的 Volcano 模型,已经从一行一行变成了一个 Chunk 一个 Chunk,每个 Chunk 里面是一个批量的数据,所以聚合的效率会更高。
  • TiDB 中算子推到 TiKV 来做, TiKV会成为一个全向量化的执行器的框架。

3. Workload Isolation

  • 尽可能地把 OLTP 跟 OLAP 隔离开。
  • Google Spanner做le一个新的数据结构,来替代 Bigtable-Like SSTable 数据结构,这个数据结构叫 Ressi《Spanner: Becoming a SQL System》。其实表面上看还是行存,但内部也是一个 Chunk 变成列存这样的一个结构。
  • 但即使是换一个新的数据结构,也没有办法很好做隔离,因为毕竟还是在一台机器上,在同一个物理资源上。最彻底的隔离是物理隔离。

TiFlash 用了好几种技术来去保证数据是更新的。一是增加了 Raft Leaner,二是把 TiDB 的 MVCC 也实现在了 TiFlash 的内部。第三在 TiFlash 接触了更新(的过程),在 TiFlash 内部还有一个小的 Memstore,来处理更新的热数据结果,最后查询的时候,是列存跟内存里的行存去 merge 并得到最终的结果。

  • TiFlash 的核心思想就是通过 Raft 的副本来做物理隔离。这个有什么好处呢?这是我们今天给出的答案,但是背后的思考,到底是什么原因呢?为什么我们不能直接去同步一个 binlog 到另外一个 dedicate 的新集群上(比如 TiFlash 集群),而一定要走 Raft log?最核心的原因是,我们认为 Raft log 的同步可以水平扩展的。因为 TiDB 内部是 Mult-Raft 架构,Raft log 是发生在每一个 TiKV 节点的同步上。
  • 大家想象一下,如果中间是通过 Kafka 沟通两边的存储引擎,那么实时的同步会受制于中间管道的吞吐。比如一部分一直在更新,另一边并发写入每秒两百万,但是中间的 Kafka 集群可能只能承载 100 万的写入,那么就会导致中间的 log 堆积,而且下游的消费也是不可控的。而通过 Raft 同步, Throughput 可以根据实际存储节点的集群大小,能够线性增长。这是一个特别核心的好处。

4. SIMD

  • 现代的 CPU 会支持一些批量的指令,比如像 _mm_add_epi32,可以一次通过一个 32 位字长对齐的命令,批量的操作 4 个累加。看上去只是省了几个 CPU 的指令,但如果是在一个大数据量的情况下,基本上能得到 4 倍速度的提升。
  • I/O不是瓶颈,未来的瓶颈在于CPU
  • 怎么去用新的硬件,去尽可能的把计算效率提升,这是未来数据库发展的重点。比如说我怎么在数据库里 leverage GPU 的计算能力,因为如果 GPU 用的好,其实可以很大程度上减少计算的开销。
  • 所以,如果在单机 I/O 这些都不是问题的话,下一个最大问题就是怎么做好分布式,这也是为什么Tidb一开始就选择了一条看上去更加困难的路:做一个 Share-nothing 的数据库,并不是像 Aurora 底下共享一个存储。

5. Dynamic Data placement

  • 今天其实看不到未来十年数据增长是怎样的,十年前大家不能想到现在我们的数据量有这么大。

  • 所以新的架构或者新的数据库,一定要去面向我们未知的 Scale 做设计。比如大家想象现在有业务 100T 的数据,目前看可能还挺大的,但是有没有办法设计一套方案去解决 1P、2P 这样数据量的架构?

  • 在海量的数据量下,怎么把数据很灵活的分片是一个很大的学问。

  • 分库分表的 Router 是静态的。如果出现分片不均衡,比如业务可能按照 User ID 分表,但是发现某一地方 / 某一部分的 User ID 特别多,导致数据不均衡。

  • TiDB 彻底把分片从数据库里隔离了出来,放到了另外一个模块里。分片应该是根据业务的负载、根据数据的实时运行状态,来决定这个数据应该放在哪儿。这是传统的静态分片不能相比的,不管传统的用一致性哈希,还是用最简单的对机器数取模的方式去分片(都是不能比的)。

  • 在这个架构下,甚至未来我们还能让 AI 来帮忙。把分片操作放到 PD 里面,它就像一个 DBA 一样,甚至预测 Workload 给出数据分布操作。比如课程报名数据库系统,系统发现可能明天会是报名高峰,就事先把数据给切分好,放到更好的机器上。这在传统方案下是都需要人肉操作,其实这些事情都应该是自动化的。

  • Dynamic Data placement 好处首先是让事情变得更 flexible ,对业务能实时感知和响应。另外还有一点,为什么我们有了 Dynamic Placement 的策略,还要去做 Table Partition。Table Partition相当于业务已经告诉我们数据应该怎么分片比较好,我们还可以做更多针对性的优化。这个 Partition 指的是逻辑上的 Partition ,是可能根据你的业务相关的,比如说一张表存着 2018 年的数据,虽然还是 TiDB 通过 PD 去调度,但是我知道你 Drop 这个 Table 的时候,一定是 Drop 这些数据,所以这样会更好,而且更加符合用户的直觉。但这样架构仍然有比较大的挑战。当然这个挑战在静态分片的模型上也都会有。

  • 比如说围绕着这个问题,怎么更快的发现数据的热点,比如说我们的调度器,如果最好能做到,比如突然来个秒杀业务,我们马上就发现了,就赶紧把这块数据挪到好的机器上,或者把这块数据赶紧添加副本,再或者把它放到内存的存储引擎里。这个事情应该是由数据库本身去做的。所以为什么我们这么期待 AI 技术能够帮我们,是因为虽然在 TiDB 内部,用了很多规则和方法来去做这个事情,但人工的规则不是万能的。

6. Storage and Computing Seperation

说存储计算分离本质:存储依赖的物理资源,跟计算所依赖的物理资源并不一样。

  • 比如计算可能需要很多 CPU,需要很多内存来去做聚合,存储节点可能需要很多的磁盘和 I/O,如果全都放在一个组件里 ,调度器就会很难受:我到底要把这个节点作为存储节点还是计算节点?
  • 在这块,可以让调度器根据不同的机型(来做决定),是计算型机型就放计算节点,是存储型机型就放存储节点。

7. Everything is Pluggable

  • 每一层我们未来都会去对外暴露一个非常抽象的接口,能够去 leverage 不同的系统的好处。 F1 Query 这篇论文,基本表述了一个大规模的分布式系统的期待,架构的切分非常漂亮。

8. Distributed Transaction

  • ACID 事务肯定是必要的,除了 Google 用了原子钟,Truetime 非常牛。
  • 当然,时间戳,不管是用硬件还是软件分配,仍然是现今的最好方法。
  • 因为如果要摆脱中心事务管理器,时间戳还是很重要的。所以在这方面的挑战就会变成:怎么去减少两阶段提交带来的网络的 round-trips?或者如果有一个时钟的 PD 服务,怎么能尽可能的少去拿时间戳?
  • Tidb把 Percolator 模型做了一些优化,能够在数学上证明,可以少拿一次时钟数学证明的过程已经开源,用TLA+ 数学工具做了证明( https://github.com/pingcap/tla-plus/blob/master/OptimizedCommitTS/OptimizedCommitTS.tla)。
  • Follower Read。很多场景读多写少,读的业务压力很多时候是要比写大很多的,Follower Read 能够帮我们线性扩展读的性能,而且在我们的模型上,因为==没有时间戳== ,所以能够在一些特定情况下保证不会去牺牲一致性。

9. Cloud-Native Architecture

  • 多租户没有做在 TiDB 的系统内部,因为其设计理念是「数据库就是数据库」,它并不是一个操作系统,不是一个容器管理平台。
  • 模块和结构化是更清晰一种==软件工程==的方式。
  • Kubernetes 在这块已经做的足够好了,未来 K8s 会变成集群的新操作系统,会变成一个 Linux。比如说如果单机时代做一个数据库,会在数据库里面内置一个操作系统吗?肯定不会。
  • 所以在模块抽象的边界,可以依赖 K8s 。《Large-scale cluster management at Google with Borg》这篇论文里面提到了一句话,BigTable 其实也跑在 Borg 上。

reference

  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2015-2021 John Doe
  • PV: UV:

请我喝杯咖啡吧~

微信