33

TiDB 的 HTAP 之路:过去,现在和将来

 4 years ago
source link: https://www.tuicool.com/articles/byIfyiZ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

imiIZfR.jpg!web

分享嘉宾:申砾 PingCAP 技术VP

编辑整理: Hoh Xil

内容来源:大数据开源技术论坛 · 01

出品社区: DataFun

注:欢迎转发,转发请注明出处。

TiDB 有很多故事

每个故事都可以有多个视角,这是一个从 AP 视角讲 HTAP 故事的分享,当然还有技术讨论

我们开始 做 TiDB 时只是想做 TP 数据库,替换 MySQL 分库分表方便用户使用,但是后续用 使用中 发现,除了 TP 功能之外,还有很多分析场景也期望数据库来解决。 今天主要讲一下 TiDB 在 HTAP 这个领域过去的探索、现在状态和将来的计划。

从 TiDB 的上古时代说起

muMbYn7.jpg!web

最开始做的低版本就是想实现水平扩展:数据存储进来将数据分片,加节点能够解决存储空间不够的问题,支持 MySQL 的语法、协议和行为,方便用户将数据存储进去。比如在多个节点中单个节点失效时,保证整个集群还是能够提供服务,做一个实现高可用、分布式的数据库。

BRbuiuJ.jpg!web

上图是 TiDB 的架构,TiKV 是将数据存储进去,PD 是其调度节点,数据从 DistSQL 写进去。从外面就是 MySQL 服务,调用 MySQL 相关协议进行数据同步下一个 TiDB,这样只要加节点就能实现无限存储,前期测试扩展到几十 T 甚至上百 T 都是可以实现的。早期更多的是类似于一个存储系统,计算能力较弱。相对于 MySQL,MySQL 是小号 T 恤,而 TiDB 是大号 T 恤,其他功能尽可能接近。

QfqyaaM.jpg!web

用户反馈体验很好,先前需要分库分表,现在不需要分库分表,当业务场景很多时,推动一次业务变更非常困难,拥有一个简单扩展的数据库能解决很多问题。但是在早期对一个数据库而言,尤其是存储交易数据的数据库而言,用户会对其安全性不放心。因此可以存储一些边缘场景,如存日志数据,当其数据丢失可以从 Hadoop 中恢复。但用户反馈数据库挺好,可以做一些数据分析,而前期我们的想法是想做一个承载交易数据的数据库,而三四个用户前期都是做分析的。如游戏客户将游戏投放到广告页面,分析广告投放的效果或者分析流水型的数据分析,当时做了一个并行的 hash join,而 MySQL 没有 hash join,运行还挺快的。

后来从 TP 领域贴近用户场景中,解决有些现有数据库无法解决的问题,如将上百个分片的 MySQL 数据同步,做一些规则变换允许用户进行裁剪和过滤,随着用户增多,越来越多的数据同步过来,对数据库的承载能力也是一个考验。

j6zIRvM.jpg!web

在进行数据同步过程中需要进行计算,在 TiDB alpha 阶段计算很简单,包括优化器、执行引擎都很粗糙。我们在此基础下进行优化,1.0 beta 版本的时候做了一个分布式计算框架,让 TiKV 能够承载一部分计算开销,在 TiDB 进行 SQL 优化,选择一部分算子,尽可能多的将算子推到 TiKV 中,将数据从本地导出,在本地做 filter、聚合、limit 等流式算子,然后将数据返回到 TiDB Server 中做一个最终的聚合,同时我们做了很多自己的 join,可以在很多传感器中调用 MySQL,运行效率比较快,能够允许用户在数据量大的时候增加节点,提高计算并发解决问题。

我们分析了用户用我们产品的初衷,在产品早期让用户相信产品是稳定的是很难的事情,除了使用还有数据库运维、日常处理等都需要学习。如游戏运营人员分析游戏日志时分了很多 MySQL 库,写很多 SQL 操作,多个数据库将数据取出来放到 Excel 中,然后通过 Excel 公式进行最后的数据聚合,这样做非常麻烦,现在使用 TiDB 可以直接聚合,非常简单方便。能够实现无障碍跨分片操作,不用额外操作,同时还有实时性,以前是很多 MySQL 数据通过 ETL 拉出来放到 Hadoop 中,再用 Hive 计算,虽然计算能力强,但无论是 ETL 实时性也好,还是维护流水线的复杂度,都很难实时。使用 TiDB 后没有这些操作后可以专注于业务,更加方便,当数据丢失还有备库,这种方式叫中台,可以实现海量存储汇聚。

Everyone Happy Now ?

vqIfuiQ.jpg!web

这样实现后还是出现了一些问题,在简单的 TP 场景下,点查联系、低频率写入对优化器负担较小,对执行引擎也没什么压力。但是用户在 AP 场景中越用越深,数据量越来越多,一些场景中,会遇到问题,比如一些 Query 跑得慢,还有就是会遇到 OOM。因为计算是在 TiKV 上经过聚合、filter 后还需要在 TiKV server 中单点聚合,可能会遇到 CPU 瓶颈,TiKV 内存小,使用也不精细,还有就是没有自动算子选择,还是手动设置,对用户来说很不方便;还有就是只能通过 MySQL 协议和外界交互,没有和其他数据库平台打通,还是需要 ETL 将数据从 TiDB 中通过 MySQL 协议读取写到其他地方或者通过 Spark、JDBC 连接数据库。

不匹配的算力

随着用户越来越多,场景也越来越多,TiDB 的存储扩展能力是非常强的,能存储很多数据,但是早期版本中,计算能力相对存储能力偏弱。这方面不光包括复杂的计算如何去处理,也包括整个计算的负载怎么去分配;存储的调度相对简单,但是计算的调度很难分配,这样导致一些业务出现问题。

N7JVZ3U.jpg!web

Rn26JbM.jpg!web

我们的数据最终都要汇聚到一个 TiDB 上做聚合、join 等操作,每个 TiDB 间无法交换数据,当两个大表做 hash join 时,如果使用内存过多会出现 OOM 的问题,如果通过分布式 join 就能很好解决这个问题。TiKV 间也不能交换数据,只是相对于多个 Map 加一个 Reduce 的模式;还有就是 join 和 Distinct 无法推到 TiKV 上做,在 TiKV 只能进行流式计算。

TiSpark

ueEBzqI.jpg!web

那么解决方案可以是自己去做执行优化算子,借鉴 Spark、Hive 等专业分析引擎,运用所有节点集群,做一个真正的 MPP 执行引擎;或者借用一些现有的成熟的分析系统,更好地运用存储进来的数据。我们的选择是借助 TiSpark,在 Spark 中加入 TiDB driver,Spark 在优化器中有部分扩展点,可以将一部分查询优化截取出来,告诉优化器哪些可以做优化哪些算子不能优化,最后返回所需要的数据格式,将 table scan、 inner scan、聚合等简单操作通过 driver 让 TiKV 做初步数据预处理,再将数据返回 Spark 做更重的 join。这样不仅有了一个很好的计算平台,也有了一个良好的计算生态。TiSpark 具有完整继承 Apache Spark 生态圈,无缝衔接大数据生态圈、成熟的分布式计算平台等优点。

应用 TiSpark 比较重的用户是易果生鲜,先前应用的是 SQL Server、MySQL,想做数据分析,维护的是 ETL 流水线。应用 TiSpark 后基本能做到实时分析,将多个数据源的数据汇总到一个 TiDB 集群中与各种下游分析需求对接,能做实时分析。实现中台数据汇总加实时数据分析。

uIRzIrB.jpg!web

iIFzmyy.jpg!web

应用 TiSpark 并不能解决所有问题,运行速度并不是很快,不能利用底层的统计信息做更精细的分析,再者在做有一定并发能力但并不复杂的场景时,分析能力不强,如利用 TiDB 做点查,有少量 key 的点查还是很快的,但是在 Spark 中并发达不到那么高,其 job 启动、调度并不轻量。其次其运维和使用没有 TiDB 简单,因为 TiDB 的接口管理使用与 MySQL 类似。

除了 TiSpark 之外,我们在 TiDB 本身也做了很多工作,优化 TiDB 优化器,早期做大数据分析要写很多 join 算子 hint、并发度多少、聚合算子选择都需要人为选择。一步步优化,从 RBO 到 CBO 到更好的 CBO,不但包括优化器本身、data 模型、plan 搜索,以及如何快速搜集大量统计信息,利用搜集的、扫描的真实数据信息来修正现有的统计信息。在执行模型方面,由一个纯的经典火山模型变成 Batch 加部分向量化的的执行引擎,当优化器预测基础 size 比较大时,在算子之间调用时,不是一次拿一条而是一次拿一批,batch size 可以实时调节,降低了内存消耗,因为内存分配次数比分配大小更重要些,对整个性能会有很好的优化。在 batch 内部通过 Apache Arrow 格式实现,数据会有一定的压缩,更经典,更重要的是可以对内存使用进行记账,分批次记账比一条条记账更高效;同时对部分算子进行向量化处理,后期将向图形向量化方向发展。TiDB 是一个混合负载机制,目的也是做一个通用负载数据库,不想借助其他特许硬件;同时也支持分区表,对数据进行裁剪。

TiDB 2.0 和 1.0 对比,TPC-H benchmark 结果中 query 运行速度明显要快很多,有些查询在1.0版本中无法查询现在也可以查询。 但是在2.0中有些查询比较慢,原因是在 hash 聚合是一个单线程算子。 在分析中比较重要的算子就是聚合和 join,join tpch 中占一半,聚合占三分之一。 我们的目标就是希望 TiDB 在不借助 Spark 情况下也能和主流分析工具媲美。 在 TiDB 2.1 版本中,我们做了进一步的优化,特别是多线程的聚合算子,对 TPC-H 结果带来了进一步的提升。

核心矛盾

vuuYfuV.jpg!web

TiDB 2.1 版本在很多分析场景中已经跑的不错,但是在面对需要对大表进行全表扫描时,行存模式明显不满足需求,无论是 scan 或者简单 filter 或者 IO 压力都明显不如内存。还有在 HTAP 场景中需要解决 AP 负载不影响 TP 负载。TiDB 内部提供的解决方案就是让分析的负载优先级更低,可以运行低优先 SQL,还有就是依据优先级做作业调度等,还有就 TiDB 实例可以无限拓展,可以一部分给 TP 用,一部分给 AP 用,但是最终 TiKV 对磁盘、网络的占用还是无法避免;还有就是大查询执行下,有几个在线小查询,也没有 CPU 抢占机制;这些问题都是无法避免的。

TiFlash

bQFJ7jJ.jpg!web

TP 和 AP 之间对于存储格式的偏好不同,TP 一定要行存,需要低延迟,而 AP 一定要列存。一些数据库尝试过一个集群中同时有行存和列存,比如 Oracle 有列存插件。我们也开发了一个新项目——TiFlash,简单来说是一个 TiKV 的列存扩展。可以通过 Raft 日志将 TiKV 使用的数据实时同步出来,通过 Raft log 将数据同步到 TiFlash 实例,它会将行存的数据转到列存,然后存到本地列存引擎中。开发借用了部分 ClickHouse 代码,因为 ClickHouse 是一个以速度见长的引擎,在向量化方面做的比较细。通过 Raft 日志可以同步 TiKV 上所有数据,包括 MVCC、事务状态,能够实现数据的事务一致性读取,唯一影响的是 TiKV 要同步一分日志过来,Raft learner 只会一次写入不会参与投票,对线上写入延迟影响不大。

aiqym22.jpg!web

TiFlash 当前版本架构:数据从 TiDB 集群中写入进来后,通过 Raft 日志同步到 TiFlash 节点,通过 Spark 进行数据读取。TiFlash 以 Raft Learner 方式接入 Raft Group,使用异步方式传输数据,对 TiKV 产生非常小的负担。当数据同步到 TiFlash 时,会被从行格式拆解为列格式。在读取时会有一个校验机制,在读数据时会进行一个 RaftCommand 判断是否有读取数据,当数据同步到读取请求发送时间点的进度时,TiFlash 才提供读取。虽然有一次 Command,但是如果分析比较重,整个负载还是比较小的。

a2QVJnA.jpg!web

TiFlash 的下一个版本会做计算的融合,将入口切换转为一个,实现 TiDB 可以同时读取行存和列存副本。有些 SQL 部分选择列存部分选择行存,交给优化器来选择,原理是将列存当做一个特殊的索引,让列存读到与行存一样的数据。目前 TiFlash 已经进入 beta 版,在一些用户那边已经开始进行 PoC,预计在年内发布第一个正式版本。

yEnEzq7.jpg!web

目前的 TiDB

yIBBfqu.jpg!web

将存储引擎的数据通过 Raft learner 同步出去可以做更多的事情,保证日志是一个近实时同步方式。计算引擎也可以替换成不同的东西,寄存到自己的引擎中做自己的事情。希望用这套场景解决 AP 与 TP 相互干扰的状况,帮助用户简化使用。在 TP 中统计信息收集比较麻烦,当数据有上百亿表,这种收集统计信息是非常耗时的,当统计信息不准可能会导致业务选错索引。对于这种不需要完全实时,也不要求百分百准确的统计信息收集工作,可以让其后台执行,交给 TiFlash 引擎来做。

存储集群不再区分是何种引擎,是一个行列共存的存储引擎。可以实现数据实时同步,可以实现快速将几 T 或者几十 T 的数据快速导入集群中。有了这么多组件后维护起来比较麻烦,可以使用 TiDB Operator,让 K8s 帮助管理实例。

还有哪些问题?

uYfiiiZ.jpg!web

目前的架构已经足够强大,但是还有些问题没解决。Spark+TiFlash 架构中,底层引擎还不支持 MR 模型,Spark 的 MR 模型还是略重,跑起来速度一般。后期希望自己写一套 MPP 引擎,让 TiFlash 节点之间可以交换数据,减少 Spark 端的工作任务,加快查询速度;还有 SQL 语句推下去做计算,统一协处理器层,让 TiKV 和 TiFlash 都能组成 MPP 集群。同一套代码,同一套引擎,让 TiFlash 也支持 SQL 行为,这样才能接上 MySQL 引擎。

还有写入还是要借助 TiKV,通过 TiDB 和 TiKV 写入行存,Raft 日志同步到列存中,在写入过程中吞吐不够,将数据从行存转入列存流水线较长,开销也会加大。

RRZ3amB.jpg!web

另一个就是需要加强写入,TiDB 对一次性写入的数据大小是有限制的,我们希望提供一套快速且支持大数据量的写入,支持几个 G 的数据原子写入。TiFlash+TiDB 能解决海量数据计算问题,但是计算后不能将数据原子写回,会导致整条业务逻辑不通。有了大数据量回写之后,TiFlash 可以承担 ETL 的功能。

fMzAJn7.jpg!web

最后就是可以用不同引擎解决不同问题,就像将行存列存引擎接到 TiKV 中来解决不同的问题,我们还可以添加更多的引擎。此外通过更好的调度,将不同的引擎调度到不同的机器实例上,实现完美的负载隔离,并且分散不同类型的业务负载到不同类型的引擎。

PPT 下载:

请关注社区公众号,后台回复【 TiDB

jYfemia.jpg!web

嘉宾介绍

申砾 ,PingCAP   技术  VP TiDB Tech Lead ,前网易有道、 360  搜索资深研发。

——END——

文章推荐:

视频:TiDB 的 HTAP 之路:过去,现在和将来

深入了解 TiDB SQL 优化器

Apache Doris : 一个开源 MPP 数据库的架构与实践

关于 DataFun:

DataFun 定位于最实用的数据智能平台,主要形式为线下的深度沙龙、线上的内容整理。希望将工业界专家在各自场景下的实践经验,通过 DataFun 的平台传播和扩散,对即将或已经开始相关尝试的同学有启发和借鉴。

DataFun 的愿景是:为大数据、人工智能从业者和爱好者打造一个分享、交流、学习、成长的平台,让数据科学领域的知识和经验更好的传播和落地产生价值。

DataFun 成立至今,已经成功在全国范围内举办数十场线下技术沙龙,有超过三百位的业内专家参与分享,聚集了数万大数据、算法相关领域从业者。

nQry6nn.jpg!web

您的「在看」,我的动力!:point_down:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK