TiDB原理解析系列(一)---Why Do We Use it
TiDB
是PingCAP
公司设计的开源分布式NewSQL
数据库。由于它兼容MySQL
协议,并支持绝大多数SQL
功能(比如joins
,subqueries
, transaction
等)。业务能够直接通过MySQL connector
去使用它来替换MySQL
。
TiDB
适合场景:
-
数据量大,
MySQL
复杂查询很慢。Online DDL
影响业务的使用。 -
MySQL
单机容量或者性能达到瓶颈,不想分库分表或者使用数据库中间件等对业务侵入性较大、对业务有约束的Sharding
方案。 -
有高并发实时写入、实时查询、实时统计分析的需求。
-
有分布式事务、多数据中心的数据
100%
强一致性、auto-failover
的高可用的需求。
TiDB
与MySQL
相比,有什么优势,让它更适合上述场景?接下来将从以下六个方面进行对比。
1.TiDB
实现分布式的SQL
引擎和存储
MySQL
水平扩展一般是主从复制,典型的就是一主多从模式。但这种只适合读多写少的业务。碰到大写入量的业务,这种模式反而会成为瓶颈。那么就必须寻求其他的分布式方案,有以下两种思路:
- 基于修改
MySQL
的分布式方案。通过MySQL
的Server
把InnoDB
变成分布式数据库,但由于MySQL
生成的执行计划是单机的,这不是一个分布式的Plan
。不了解底层分布式存储,是无法选择一个最高效率的执行计划。 - 基于中间件方式的分布式方案,比如ProxySQL。做一款中间件需要考虑很多,比如通过解析
SQL
解析出ShardKey
,然后根据ShardKey
分发请求,再合并结果。另外在中间件这层还需要维护Session
并保存缓存结果。大多数方案并不支持分布式Transaction
,不支持跨节点Join
,无法处理复杂Plan
,也不会处理Subqueries
。同时业务需要维护ShardKey
,不支持ORM
导致业务开发效率降低。
以上MySQL
的问题是由传统架构模式本身带来的,而TiDB
的模式是不一样的。它在TiDB Server
层实现了分布式的SQL引擎,依赖TiKV
来提供分布式存储和分布式事务支持,分布式的设计也方便做水平扩展。以上MySQL
分布式方案带来的问题,TiDB
都能做很好的解决,这是架构本身带来的优势。

如上图所示,TiDB
集群主要分为以下三个组件:
-
TiDB Server
TiDB Server
负责接收SQL
请求,处理SQL
相关的逻辑,并通过PD
找到存储计算所需数据的TiKV
地址,与TiKV
交互获取数据,最终返回结果。TiDB Server
本身并不存储数据,只负责计算,可以无限水平扩展。通过负载均衡组件(如LVS
、HAProxy
或F5
)对外提供统一的接入地址。 -
PD Server
Placement Driver
(简称PD
)是整个集群的管理模块。其主要工作有三个:一是存储集群的元信息(某个Key
存储在哪个 TiKV节点);二是对TiKV
集群进行调度和负载均衡(如数据的迁移、Raft group leader
成员变更等);三是分配全局唯一且递增的事务ID
(支持分布式事务)。 -
TiKV Server
image.png
TiKV Server
负责存储数据,从外部看TiKV
是一个分布式的提供事务的Key-Value
存储引擎。存储数据的基本单位是 Region
,每个Region
负责存储一个Key Range
(从StartKey
到EndKey
的左闭右开区间)的数据,每个TiKV
节点会负责多个Region
。TiKV
使用Raft
协议做复制,保持数据的一致性和容灾。副本以Region
为单位进行管理,不同节点上的多个Region
构成一个Raft Group
。数据在多个TiKV
之间的负载均衡由PD
调度,是以Region
为单位进行调度。
2.TiDB
金融级的高可用
MySQL
的复制方式是半同步或者是异步,半同步也可以降级成异步。也就是说任何时候数据出了问题是不敢切换的,因为有可能是异步复制,有一部分数据还没有同步过来,这时候切换数据就不一致了。多数据中心的复制和数据中心的容灾,MySQL
在这上面是做不好的。
而TiDB/TiKV/PD
的三个组件都能容忍部分实例失效,并且不影响整个集群的可用性,支持跨中心部署。
下面分别说明这三个组件的单个实例失效后的服务状态,以及如何进行恢复。
-
TiDB Server
TiDB Server
是无状态的,推荐至少部署两个实例。当单个实例失效时,会影响正在这个实例上进行的服务,从应用的角度看,会出现单次请求失败的情况,重新连接成功后即可继续获得服务。单个实例失效后,可以重启这个实例或者部署一个新的实例。 -
PD Server
PD
是一个集群,通过Raft
协议保持数据的一致性,单个实例失效时,如果这个实例不是Raft
的leader
,那么服务完全不受影响;如果这个实例是Raft
的leader
,会重新选出新的Raft leader
,自动恢复服务。PD
在选举的过程中无法对外提供服务,这个时间大约是3秒钟。推荐至少部署三个PD
实例,单个实例失效后,重启这个实例或者添加新的实例。 -
TiKV Server
TiKV
是一个集群,通过Raft
协议保持数据的一致性(副本数量可配置,默认保存三副本),并通过PD
做负载均衡调度。单个节点失效时,会影响这个节点上存储的所有Region
。对于Region
中的Leader
结点,会中断服务,等待重新选举;对于Region
中的Follower
节点,不会影响服务。当某个TiKV
节点失效,并且在一段时间内(默认10
分钟)无法恢复,PD
会将其上的数据迁移到其他的TiKV
节点上。
3.TiDB
存储引擎RocksDB
MySQL
默认存储引擎从2010年起就一直是InnoDB
,InnoDB
使用B+
树数据结构,这与传统的商业数据库相似。TiDB
使用RocksDB
作为TiKV
的存储引擎。
读写性能的测试对比:
-
RocksDB
读性能只有InnoDB-Compress
性能的70%
。但在高并发下,RocksDB
平均响应时间表现要比InnoDB-Compress好
。但与未压缩的InnoDB
还是差不少。 -
RocksDB
写性能表现优异,QPS
大概是InnoDB-Compress
的10
倍。
RocksDB
优势是在于处理大型数据集,因为它可以更有效地压缩数据并且插入数据性能优秀。
6亿4千万数据导入MySQL
,InnoDB
未经压缩大小为160GB
,InnoDB-Compress
为86GB
,RocksDB
为62GB
。
TiDB
更加适合大规模数据场景。数据条数少于5000w
的场景下通常用不到TiDB
,单机MySQL
能满足的场景也不需要用到TiDB
。

4.TiDB
更好的解决了Online DDL
问题
业务发展迅速,应用模式频繁更改是常态。相应地,数据库访问模式和Schema
也随之变化。DDL
是SQL
的一类,主要作用是创建和更改数据的Schema
信息,最常见的操作包括:加减列、更改列类型、加减索引等。5.6
版本以后,MySQL
内部开始支持Online DDL
。但MySQL
的Online DDL
方案始终没有解决下面问题:MySQL
主备副本之间通过Binlog
同步,主的Schema
变更成功后,才会写BinLog
同步给备库,然后备库才开始做DDL
。假设一个DDL
变更需要一个小时,那么备库最多可能会延迟两倍的变更时间。若变更期间,主库发生故障,备库数据还未追平,则无法提供服务的。
TiDB
使用Google F1
论文介绍的协议实现在线DDL。Tikv
基本不感知DDL
操作。对于Tikv
来说,所有的操作都是PUT/GET/DELETE
,所以副本间的变更也与普通DML
没有差异。任何时候,只要底层raft
协议能正常work
,三副本高可用和强一致就能得到保证。这个方案虽然Schema
变更比较麻烦,但对于Tikv
存储层特别友好,不用感知DDL
,共用一套机制保证高可用和强一致。不会出现类似MySQL
主备延迟和主备Schema
不一致问题。DDL
更改也被分解成更小的转换阶段,这样它们可以防止数据损坏场景,并且系统允许单个节点一次最多支持一个DDL
版本。
5.TiDB
提供一站式HTAP
解决方案
MySQL
团队把注意力放在优化联机事务处理(OLTP
)查询的性能上。也就是说,MySQL
团队花费更多的时间使简单查询执行得更好,而不是使所有或复杂查询执行得更好。这种方法没有错,因为许多应用程序只使用简单的查询。
TiDB
设计目标在处理混合事务/分析处理(HTAP
)的性能上。对于那些希望对数据进行实时分析的应用来说,这是一个主要的卖点,因为它消除了在MySQL
数据库和分析数据库之间进行的批量加载。一份存储同时处理OLTP & OLAP
,无需传统繁琐的ETL
过程。
6.TiDB
可视化监控与告警
这一点对运维非常友好。MySQL
将关键监控指标放在内存表中,获取它需要通过SQL
查询,可视化与告警部分都需要额外开发。而TiDB提供Metrics接口,使用 Prometheus
记录组件中各种操作的详细信息,使用Grafana
进行可视化展示。无须其他开发额外,根据需要,即可配置定制化自己的监控图表和报警。

总结
在替代MySQL
的场景中,TiDB
与MySQL
相比更加适合大数量的场景;同时也补充了MySQL
的不足,比如处理Online DDL
问题;在MySQL
不适合的场景中,比如HTAP
场景中也能发挥很好的优势。如果你想更多了解TiDB
作者的初衷,参阅How do we build TiDB。