引言
混合事务分析处理(HTAP)数据库要求隔离处理事务查询和分析查询,以消除它们之间的干扰。要实现这一点,有必要维护为这两种查询类型指定的数据的不同副本。然而,为存储系统中的分布式副本提供一致的视图是一项挑战,在存储系统中,分析请求可以大规模地、高可用性地从事务工作负载中高效地读取一致的新数据。
为了应对这一挑战,我们建议扩展基于复制状态机的一致性算法,为HTAP工作负载提供一致的副本。基于这种新颖的思想,我们提出了一个基于raft的HTAP数据库:TiDB。在数据库中,我们设计了一个由行存储和列存储组成的multi-Raft存储系统。行存储是基于Raft算法构建的。它是可伸缩的,可以实现高可用性事务请求的更新。特别是,它异步地将Raft日志复制到learners中,learners将元组的行格式转换为列格式,形成一个可实时更新的列存储。列存储允许分析查询有效地读取新鲜且一致的数据,并且与行存储上的事务具有很强的隔离性。基于该存储系统,我们构建了一个SQL引擎来处理大规模分布式事务和昂贵的分析查询。SQL引擎最佳地访问行格式和列格式的数据副本。我们还包括一个强大的分析引擎TiSpark,以帮助TiDB连接到Hadoop生态系统。综合实验表明,TiDB在一个专注于HTAP工作负载的基准测试下实现了各自的高性能。
1 介绍
关系数据库管理系统(RDBMS)因其关系模型、强大的事务保证和SQL接口而流行。它们在传统应用程序(如业务系统)中被广泛采用。但是,老的RDBMS不提供可伸缩性和高可用性。因此,在21世纪初,互联网应用程序更喜欢NoSQL系统,如谷歌Bigtable和DynamoDB。NoSQL系统放宽了一致性要求,并提供了高可伸缩性和可替代的数据模型,如键值对、图和文档。然而,许多应用程序还需要强大的事务、数据一致性和SQL接口,因此出现了NewSQL系统。像CockroachDB和谷歌Spanner这样的NewSQL系统为联机事务处理(OLTP)读/写工作负载提供了NoSQL的高可伸缩性,并且仍然为事务保持ACID保证。此外,基于sql的联机分析处理(OLAP)系统正在迅速发展,就像许多SQL-on-Hadoop系统一样。
这些系统遵循“one size does not fit all”范式,为OLAP和OLTP的不同目的使用不同的数据模型和技术。然而,开发、部署和维护多个系统的成本非常高。此外,实时分析最新版本的数据也很有吸引力。这在工业界和学术界产生了混合OLTP和OLAP (HTAP)系统。HTAP系统应该像NewSQL系统一样实现可伸缩性、高可用性和事务一致性。此外,HTAP系统需要有效地读取最新数据,以保证OLTP和OLAP请求在新鲜度和隔离性两个额外要求下的吞吐量和延迟。
新鲜度表示分析查询如何处理最近的数据。实时分析最新数据具有巨大的商业价值。但是,在一些HTAP解决方案中,例如基于提取-转换-加载(ETL)处理的解决方案,不能保证这一点。通过ETL进程,OLTP系统定期刷新一批最新的数据到OLAP系统。ETL耗时数小时或数天,因此无法提供实时分析。ETL阶段可以通过将最新的更新流式传输到OLAP系统来取代,以减少同步时间。然而,由于这两种方法缺乏全局数据治理模型,因此考虑一致性语义更为复杂。与多个系统接口会带来额外的开销。
隔离性指的是为单独的OLTP和OLAP查询保证隔离的性能。一些内存数据库(如HyPer)允许分析查询从同一服务器上的事务处理中读取最新版本的数据。尽管这种方法提供了新的数据,但它不能同时实现OLTP和OLAP的高性能。这是由于数据同步损失和工作负载干扰造成的。通过在HyPer和SAP HANA上运行HTAP基准测试CH-benCHmark来研究这种影响。研究发现,当系统协同运行分析查询时,其可达到的最大OLTP吞吐量会显著降低。SAP HANA吞吐量降低了至少三倍,HyPer降低了至少五倍。在MemSQL中也得到了类似的结果。此外,如果内存数据库仅部署在单个服务器上,则无法提供高可用性和可伸缩性。
为了保证独立的性能,有必要在不同的硬件资源上运行OLTP和OLAP请求。主要的困难是在单个系统中维护来自OLTP工作负载的OLAP请求的最新副本。此外,系统需要在多个副本之间保持数据一致性。注意,维护一致的副本也是可用性所必需的。高可用性可以使用众所周知的共识算法来实现,例如Paxos和Raft。它们基于复制状态机来同步副本。可以扩展这些一致性算法,为HTAP工作负载提供一致的副本。据我们所知,这个想法以前还没有被研究过。
根据这个想法,我们提出了一个基于raft的HTAP数据库:TiDB。它为Raft共识算法引入了专用节点(称为learners)。Learners异步复制来自leader节点的事务日志,为OLAP查询构造新的副本。特别是,learners将日志中的行格式元组转换为列格式,以便副本更适合于分析查询。这种日志复制对运行在领导节点上的事务性查询的开销很小。而且,这种复制的延迟非常短,可以保证OLAP的数据新鲜度。我们使用不同的数据副本分别处理OLAP和OLTP请求,以避免它们之间的干扰。我们还可以基于行格式和列格式的数据副本来优化HTAP请求。TiDB基于Raft协议,提供高可用性、可伸缩性和数据一致性。
TiDB提供了一种创新的解决方案,帮助基于共识算法的NewSQL系统进化为HTAP系统。NewSQL系统通过复制其数据库(如谷歌Spanner和CockroachDB)来确保OLTP请求的高可用性、可伸缩性和数据持久性。它们通过来自共识算法的复制机制在数据副本之间同步数据。基于日志复制,NewSQL系统可以提供专用于OLAP请求的列式副本,这样它们就可以像TiDB一样隔离地支持HTAP请求。我们的贡献总结如下。
- 我们提出建立一个基于共识算法的HTAP系统,并实现了一个基于raft的HTAP数据库TiDB。它是一个开源项目,为HTAP工作负载提供高可用性、一致性、可伸缩性、数据新鲜度和隔离性。
- 我们将learner角色引入到Raft算法中,为实时OLAP查询生成列式存储。
- 我们实现了一个multi-Raft存储系统,并优化了它的读写,以便系统在扩展到更多节点时提供高性能。
- 我们为大规模HTAP查询定制了一个SQL引擎。引擎可以最佳地选择使用基于行的存储和列式存储。
- 我们进行了全面的实验,使用HTAP基准测试来评估TiDB在OLTP、OLAP和HTAP方面的性能。
本文的其余部分组织如下。我们在第2节中描述了主要思想——基于raft的HTAP,并在第3节中说明了TiDB的体系结构。TiDB的multi-Raft存储和HTAP引擎将在第4节和第5节详细介绍。实验评估在第6节中提出。我们在第7节中总结了相关工作。最后,我们在第8节对本文进行总结。
2 基于RAFT的HTAP
Raft和Paxos等共识算法是构建一致、可扩展和高可用性分布式系统的基础。它们的优势在于,可以使用复制状态机在服务器之间实时可靠地复制数据。我们调整了这个功能,以便针对不同的HTAP工作负载将数据复制到不同的服务器上。通过这种方式,我们保证OLTP和OLAP工作负载彼此隔离,而且OLAP请求具有最新的一致的数据视图。据我们所知,以前没有使用这些共识算法来构建HTAP数据库的工作。
由于Raft算法被设计为易于理解和实现,因此我们将重点放在实现可用于生产上的HTAP数据库的Raft扩展上。在高层次上,我们的想法如下:使用行格式将数据存储在多个Raft组中,以提供事务性查询。每个小组由一个领导和追随者组成。我们为每个组添加了一个learner角色,异步复制来自leader的数据。这种方法开销低,并且保持数据一致性。复制到learner的数据被转换为基于列的格式。扩展了查询优化器,以探索访问基于行和基于列的副本的物理计划。
在标准的Raft组中,每个follower都可以成为leader来处理和编写请求。因此,简单地增加更多的追随者不会独立资源。此外,添加更多的追随者将影响组的性能,因为leader必须等待来自更大的quorum节点的响应才能响应客户机。因此,我们在Raft共识算法中引入了一个learner角色。learner不参与leader选举,也不是日志复制的法定人数的一部分。从leader到learner的日志复制是异步的;在响应客户端之前,leader不需要等待成功。在读取时,leader和learner之间的强一致性被强制执行。通过设计,leader和learner之间的日志复制滞后很低。
事务性查询需要高效的数据更新,而连接或聚合等分析查询需要读取列的子集,但这些列需要读取大量的行。基于行的格式可以利用索引有效地服务于事务性查询。基于列的格式可以有效地利用数据压缩和矢量化处理。因此,在复制到Raft learner时,数据从基于行的格式转换为基于列的格式。此外,learner可以部署在单独的物理资源中。因此,事务查询和分析查询在隔离的资源中处理。
图-Raft组中增加列存learners角色
我们的设计还提供了新的优化机会。由于数据在基于行的格式和基于列的格式之间保持一致,因此我们的查询优化器可以生成访问其中一个或两个存储的物理计划。
我们提出了扩展Raft以满足HTAP数据库的新鲜度和隔离性要求的想法。为了使HTAP数据库能用于生产,我们克服了许多工程挑战,主要包括:
- 如何构建一个可扩展的Raft存储系统来支持高度并发的读/写?如果数据量超过了Raft算法管理的每个节点上的可用空间,我们需要一个分区策略来在服务器上分发数据。此外,在基本的Raft流程中,请求是顺序处理的,任何请求都必须经过Raft节点的仲裁批准才能响应客户端。此过程涉及网络和磁盘操作,因此非常耗时。这种开销使得leader成为处理请求的瓶颈,特别是在大型数据集上。
- 如何以低延迟将日志同步到learner中以保持数据新鲜?正在进行的事务可能会生成一些非常大的日志。这些日志需要在learner中快速重播和具体化,以便可以读取新的数据。将日志数据转换为列格式可能会由于模式不匹配而遇到错误。这可能会延迟日志同步。
- 如何在保证性能的情况下高效地处理事务性和分析性查询?大型事务性查询需要读写分布在多个服务器上的大量数据。分析查询也消耗大量资源,不应该影响在线事务。为了减少执行开销,他们还需要在行格式存储和列格式存储上选择最优计划。
在下面的部分中,我们将详细介绍TiDB的设计和实现,以解决这些挑战。
3 架构
在本节中,我们将描述TiDB的高级结构。TiDB支持MySQL协议,可以被MySQL兼容的客户端访问。它有三个核心组件:分布式存储层、Placement Driver(PD)和计算引擎层。
图-TiDB架构
分布式存储层由行存储(TiKV)和列存储(TiFlash)组成。逻辑上,存储在TiKV中的数据是一个有序的键值映射。每个元组被映射成一个键值对。键由它的表ID和行ID组成,值是实际的行数据,其中表ID和行ID是唯一的整数,行ID来自主键列。例如,包含四列的元组被编码为:
Key:{
table{
tableID} record{
rowID}}
Value: {
col0, col1, col2, col3}
为了向外扩展,我们采用范围分区策略,将大的键值映射拆分为许多连续的范围,每个范围称为一个Region。每个区域都有多个副本,以实现高可用性。Raft共识算法用于保持每个Region的副本之间的一致性,形成Raft组。不同Raft组的领导将数据从TiKV异步复制到TiFlash。TiKV和TiFlash可以部署在单独的物理资源中,从而在处理事务查询和分析查询时提供隔离。
Placement Driver(PD)负责管理Regions,包括提供每个键的Region和物理位置,并自动移动Region以平衡工作负载。PD也是我们的时间戳oracle(TSO),提供严格递增和全局唯一的时间戳。这些时间戳也用作我们的事务ID。为了增强鲁棒性和性能,PD可以包含多个PD成员。PD没有持久状态,并且在启动时,PD成员从其他成员和TiKV节点收集所有必要的数据。
计算引擎层是无状态的,是可扩展的。我们定制的SQL引擎有一个基于成本的查询优化器和一个分布式查询执行器。TiDB实现了一个基于Percolator的两阶段提交(2PC)协议,以支持事务处理。查询优化器可以根据查询最优地选择从TiKV和TiFlash中读取。
TiDB的体系结构