作者:黄东旭
2018 年对于 TiDB 和 PingCAP 来说是一个由少年向成年的转换的一年,如果用一个关键字来概括就是「蜕变」。在这一年很欣喜的看到 TiDB 和 TiKV 在越来越多的用户使用在了越来越广泛的场景中,作为一个刚刚 3 岁多的开源项目,没有背后强大的社区的话,是没有办法取得这样的进展的。
同时在技术上,2018 年我觉得也交出了一份令人满意的答卷,TiDB 的几个主要项目今年一共合并了 4380 个提交,这几天在整理 2018 年的 Change Log 时候,对比了一下年初的版本,这 4380 个 Commits 背后代表了什么,这里简单写一个文章总结一下。
回想起来,TiDB 是最早定位为 HTAP 的通用分布式数据库之一,如果熟悉我们的老朋友一定知道,我们最早时候一直都是定位 NewSQL,当然现在也是。但是 NewSQL 这个词有个问题,到底 New 在哪,解决了哪些问题,很难一目了然,其实一开始我们就想解决一个 MySQL 分库分表的问题,但是后来慢慢随着我们的用户越来越多,使用的场景也越来越清晰,很多用户的场景已经开始超出了一个「更大的 MySQL 」的使用范围,于是我们从实验室和学术界找到了我们觉得更加清晰的定义:HTAP,希望能构建一个融合 OLTP 和 OLAP 通用型分布式数据库。但是要达成这个目标非常复杂,我们的判断是如果不是从最底层重新设计,很难达到我们的目标,我们认为这是一条更困难但是正确的路,现在看来,这条路是走对了,而且未来会越走越快,越走越稳。
另一方面,一个数据库查询引擎最核心的组件之一:优化器,在今年也有长足的进步。我们在 2017 年就已经全面引入了基于代价的 SQL 优化(CBO,Cost-Based Optimization),我们在今年改进了我们的代价评估模型,加入了一些新的优化规则,同时实现了 Join Re-Order 等一系列优化,从结果上来看,目前在 TPC-H 的测试集上,对于所有 Query,TiDB 的 SQL 优化器大多已给出了最优的执行计划。CBO 的另一个关键模块是统计信息收集,在今年,我们引入了自动的统计信息收集算法,使优化器的适应性更强。另外针对 OLTP 的场景 TiDB 仍然保留了轻量的 RBO 甚至直接 Bypass 优化器,以提升 OLTP 性能。另外,感谢三星韩国研究院的几位工程师的贡献,他们给 TiDB 引入了 Query Plan Cache,对高并发场景下查询性能的提升也很明显。另外在功能上,我们引入了 Partition Table 的支持,对于一些 Partition 特性很明显的业务,TiDB 能够更加高效的调度数据的写入读取和更新。
说到 TiDB 的底层存储 TiKV 今年也有很多让人眼前一亮的更新。在 TiKV 的基石——一致性算法 Raft 这边,大家知道 TiKV 采用的是 Multi-Raft 的架构,内部通过无数个 Raft Group 动态的分裂、合并、移动以达到动态伸缩和动态负载均衡。我们在今年仍然持续在扩展 Multi-Raft 的边界,我们今年加入了动态的 Raft Group 合并,以减轻元信息存储和心跳通信的负担;给 Raft 扩展了 Learner 角色(只同步 Log 不投票的角色) 为 OLAP Read 打下基础;给 Raft 的基础算法加入了 Pre-Vote 的阶段,让整个系统在异常网络状态下可靠性更高。
<center>Raft Group Merge</center>
第三件事情是我们开始将 TiKV 的本地存储引擎的接口彻底抽象出来,目标是能做到对 RocksDB 的弱耦合,这点的意义很大,不管是社区还是我们自己,对新的单机存储引擎支持将变得更加方便。
“……其 KV与 SQL分层的方式,刚好符合我们提供 NoSQL 存储和关系型存储的需求,另外,PingCAP 的文档齐全,社区活跃,也已经在实际应用场景有大规模的应用,公司在北京,技术交流也非常方便,事实证明,后面提到的这几个优势都是对的……”
——美图公司 Titan 项目负责人任勇全对 TiKV 的评论
在 TiDB 的设计之初,我们坚定将调度和元信息从存储层剥离出来(PD),现在看来,好处正渐渐开始显示出来。今年在 PD 上我们花了很大精力在处理热点探测和快速热点调度,调度和存储分离的架构让我们不管是在开发,测试还是上线新的调度策略时效率很高。瞬时热点一直是分布式存储的最大敌人,如何快速发现和处理,我们也有计划尝试将机器学习引入 PD 的调度中,这是 2019 会尝试的一个事情。总体来说,这个是一个长期的课题。
image<center>多租户 TiDB</center>
在使用场景上,TiDB 的使用规模也越来越大,下面这张图是我们统计的我们已知 TiDB 的用户,包括上线和准上线的用户,从 1.0 GA 后,几乎是以一个指数函数的曲线在增长,应用的场景也从简单的 MySQL Sharding 替代方案变成横跨 OLTP 到实时数据中台的通用数据平台组件。
<center>TiDB 的用户数统计</center>
简单回顾了一下过去的 2018 年,我们看看未来在哪里。
其实从我们在 2018 年做的几个比较大的技术决策就能看到,2019 年将是上面几个方向的延续。大的方向的几个指导思想是:
-
Predicable. (靠谱,在更广泛的场景中,做到行为可预测。)
-
Make it right before making it fast.(稳定,先做稳,再做快。)
-
Ease of use. (好用,简单交给用户,复杂留给自己。)
对于真正的 HTAP 场景来说,最大的挑战的是如何很好的做不同类型的 workload 隔离和数据结构根据访问特性自适应。我们在这个问题上给出了自己的答案:通过拓展 Raft 的算法,将不同的副本存储成异构的数据结构以适应不同类型的查询。
这个方法有以下好处:
-
本身在 Multi-Raft 的层面上修改,不会出现由数据传输组件造成的瓶颈(类似 Kafka 或者 DTS),因为 Multi-Raft 本身就是可扩展的,数据同步的单位从 binlog,变成 Raft log,这个效率会更高,进一步降低了同步的延迟。
-
更好的资源隔离,通过 PD 的调度,可以真正将不同的副本调度到隔离的物理机器上,真正做到互不影响。
<center>TiDB 2019 年会变成这个样子</center>
<center>Learner 在 HTAP 中的应用</center>
在执行器方面,我们会继续推进向量化,不出意外的话,今年会完成所有算子的全路径的向量化执行。
<center>TiKV 新的本地存储引擎 Titan</center>
在 Titan 走向稳定的同时,我们也在调研从头构建一个更适合 TiDB 的 OLTP workload 的存储引擎,前面说到 2018 年做了抽象 TiKV 的本地存储引擎的事情就是为了这个打基础,当然我们仍然会走 LSM-Tree 的路线。这里多提一句,其实很多人都误解了 LSM-Tree 模型的真正优势,在我看来并不是性能,而是:做到可接受的性能的同时,LSM-Tree 的实现非常简单可维护,只有简单的东西才可以依赖,这个决定和我们在 Raft 与 Paxos 之间的选择偏好也是一致的。另外 LSM-Tree 的设计从宏观上来说,更加符合「冷热分层」以适配异构存储介质的想法,这个我相信是未来在存储硬件上的大趋势。
差不多就这些吧,最后放一句我特别喜欢的丘吉尔的一句名言作为结尾。
Success is not final, failure is not fatal: it is the courage to continue that counts.
成功不是终点,失败也并非终结,最重要的是继续前进的勇气。