作者介绍: 王天宜,TiDB 社区部门架构师。曾就职于 Fidelity Investment,Softbank Investment,拥有丰富的数据库高可用方案设计经验,对 TiDB、Oracle、PostgreSQL、MySQL 等数据库的高可用架构与数据库生态有深入研究。
数据仓库是公司数据发展到一定规模后必然需要提供的一种基础服务,也是“数据智能”建设的基础环节。早期数仓多为离线模式,主要处理的是 T 1 的数据,随着互联网时代的到来,实时数据处理的场景日益增多,离线数仓已无法满足业务发展的实时性需求。为更好的解决业务场景的实时化需求,实时数仓建设已成必然趋势,这也是 HTAP 数据库的重要能力之一。
实时数仓相较于离线数仓,主要处理的是 T 0 的数据,实时性更高,完美契合业务高效运转的需求。在架构上,实时数仓通常使用 Flink 来消费 Kafka 中的数据,将数据流实时的写入数据库中。这种方案虽然解决了数据处理的时效问题,但很多时候,由于 Kafka 没有落盘机制,可能在极端的情况造成消息队列中数据丢失。
针对上述问题,笔者调研了页面上的数据库与存储引擎,发现了能彻底解决 Kafka 落盘问题的,更高效准确的实时数仓新方案。
首先,在数据库的选择上,考虑可扩展性更高的分布式数据库 TiDB,从数据库层面解决海量数据存储的问题,其次是分布式流存储引擎 Pravega,解决使用传统消息队列数据丢失问题和自动伸缩难题,提高了实时数仓系统的并行性,可用性与安全性。以下将详细分析。
TiDB 偶遇 Pravega
Pravega 是一款 DellEMC 开源的流存储项目,并已经进入 CNCF 的 sandbox 阶段。从功能上来看,除与 Apache Kafka、Apache Pulsar 相似,Pravega 提供了 stream、schema registry。除此之外,Pravega 最重要特点是: (1) 无需应用程序感知的自动伸缩能力 (auto-scaling) 和 (2) 是一个完整的存储接口,提供以 stream 为抽象的接口支持上层计算引擎统一的访问。
分布式消息传递一般都基于可靠的消息队列,在客户端应用和消息系统之间异步传递消息。提到消息队列,无论如何都无法绕过 Kafka。Kafka 是一个分布式、多分区、多副本、多订阅者,基于 Zookeeper 协调的分布式日志系统。Pravege 是在使用 Kafka 实践中总结出来的新的架构。
Pravega 重构了流式存储的架构。作为流式实时存储的解决方案,应用程序可以直接将数据持久化到 Pravega 中。也正是因为 Pravega 将数据落盘到 HDFS/S3 上,可以不再受限于数据的 retention,并且整个大数据流水线中数据只存储了一份。
Pravega 为何要再造轮子
作为一个粗浅的 Kafka 使用者,有三个问题使我感到困扰:
- 丢数据的问题,吃进的数据多,吐出的数据少,offset 提交了,会存在丢数据的风险。
- acks = all,只有当所有消费者确认保存了消息时,才会返回 ack,不会丢数据。
- acks = 1,当 leader 消费者保存消息就返回 ack,接收的 leader 如果确认后没有来得及备份就挂了,会丢数据。
- acks = 0,不等待任何确认,接收方挂掉时会丢数据。
- Kafka 数据受限于 retention,没有简单高效的 hdfs/S3 落盘方案。商业版本虽然提供了这个功能,但是数据一旦搬运后,你必须使用2套存储接口混合访问处于不同层级的数据。
- 引入 flume,可以走 kafka -> flume -> hdfs 的链路。
- 引入 kafka hadoop loader,可以走 kafka -> kafka hadoop loader -> hdfs 的链路。
- 引入 kafka-connect-hdfs,可以走 kafka -> kafka-connect-hdfs -> hdfs 的链路。
- Consumer rebalance 过程危害甚多。
- 在 consumer reblance 的过程中可能会因为增加 cunsumer 导致暂停队列的消费。
- 在 consumer reblance 的过程中可能因为提交间隔长,引发重复消费的问题。
- 暂停消费和重复消费都有可能导致消息积压,reblance 结束后存在消费突刺的问题。
那么在 Pravega 造轮子的过程中,解决了那些问题呢?以下为 Pravega 与 Kafka 的对比:
Pravega 的特别之处在于,虽然它与不少开源产品一样,也使用 Bookkeeper 去处理并行实时数据低延迟写问题,但是 Bookkeeper 在 Pravega 中只作为数据聚合写(batch write)到 HDFS/S3 的第一阶段(唯一例外是在节点意外故障后做恢复的时候)。所有对 Pravega 读都直接作用到 HDFS/S3 上以利用它们的高吞吐能力。
所以 Pravega 并不把 BookKeeper 当做数据缓存层,而只是提供了一个基于 HDFS/S3 新的存储层用来同时满足“低延时尾读尾写”和“高吞吐追赶读”的抽象。因此,不像大部分使用“分层”设计的项目那样,当数据在 BookKeeper 和 HDFS/S3 之间移动时候性能将无法保证。
回归到痛点问题
大部分的 DBA 或者运维人员最关心的有三件事:数据的正确性,系统的稳定性,以及系统的易用性。数据的正确性是 DBA 的立身之本,数据丢失,数据损坏,数据重复对于公司来说都是巨大的打击;稳定性与易用性解放了 DBA 的双手,让 DBA 从繁复的运维工作中解脱出来,有更多的时间关注与架构选型和系统适配的问题。
从这三点来看,Pravega 确实解决了绝大部分运维人员的痛点问题。Long-term retention 保证了数据的安全,Exactly-Once Semantics 保证了数据的准确性,Auto-scaling 使得维护本身变得轻松。这些特点令人更愿意对 Pravega 进行深一步的调研与适配。
TiDB 与 Pravega 的实时数仓新方案
之前,TiDB 5.0 发布后,其 MPP 架构主要是将业务负载切分成若干的任务下推到多个服务器和节点上。在每个结点的计算任务完成后,合并成最终结果交付给用户。在 TiDB 5.0 中,TiFlash 会全面补充 TiDB 的计算能力,TiDB 在 OLAP 场景下就会退化成一个 master 节点。基于 MPP 架构,用户会向 TiDB Server 发送查询 SQL,这个查询 SQL 会由共享的 TiDB 服务器来承担。这些 TiDB 服务器会进行 Join,然后交给优化器去决策。优化器会把使用行存、列存、某些索引、单机引擎、MPP 引擎,或者是使用不同组合产生不同的执行计划,都纳入到同一个代价模型中进行评估,最后选出一个最优的执行方案。
在一些订单交易系统,可能因为促销活动在短时间内迅速达到业务高峰。往往这种瞬时流量高峰需要我们能够快速的进行分析类的查询,从而在限定时间内给出反馈以影响决策。传统的实时数仓架构很难承载短时间内的流量高峰,随之的分析操作可能会需要大量的时间来完成。如果使用传统的计算引擎,可能无法做到秒级的聚合分析操作。有了 MPP 计算引擎,就可以将能预测的流量高峰转换成扩容的物理成本,做到秒级的响应。在 MPP 计算引擎的加持下,TiDB 能够更好的处理分析类型的海量数据查询。
实时数仓方案的架构
实时数仓经历了三个重要的里程碑:
- Storm 的出现打破了 MapReduce 的单一计算方式,让业务能够处理 T 0 的数据;
- Lambda 到 Kappa 架构的进化,将离线数仓转化为实时数仓;
- Flink 的出现给出了批流一体更好的实践方式。
实时数仓的架构一直是在不停变化的。很多时候,当我们刚刚选定一套架构模型的时候,数据仓库的技术栈仍在高速迭代。我们无法预测到 Lambda,Kappa之后会出现什么样的技术架构,但可以通过现在的架构窥探一二。一般来说,我们可以将实时数仓划分为四个部分:实时数据采集端,数据仓库存储层,实时计算层,实时应用层。多技术栈的融合可以帮我们构建一套无边界的大数据基础平台,帮助我们同时支撑分析挖掘,业务上线和批流处理。
需求探索:构建 Pravega Flink TiDB 的实时数仓
随着数字化转型的推进,越来越多企业正面临前所未有的数据规模,随着商业竞争的日趋加剧,无论是外部的用户还是公司内部的决策已经无法依赖时效性不佳的离线数据分析,需要更实时的数据分析,甚至是对正在发生的交易数据进行分析,以支撑更加敏捷的商业决策。
举例来说:
- 风控场景的最佳效果是防患于未然,所以事前事中和事后三个方案中,以事前预警和和事中控制效果最好。这要求风控系统一定要有实时性。
- 电商大促期间希望能够平稳及时的监控到销售的情况而非历史数据。
传统上,以 Hadoop 还是分析型数据库为基础的数据分析 / 数据仓库方案都存在着无法良好支持实时分析的障碍;类似 HBase 等 NoSQL 方案虽然可以支持很好的扩展性和实时性,但无法提供所需的分析能力;而传统单机数据库则无法提供数据分析所需的扩展性。
在集成了 TiFlash 之后,TiDB 实现了 OLTP 与 OLAP 的结合,既可以应用于事务性数据库场景,可以应用于分析性数据库场景,也可以在 OLTP 业务中划分出独立的区域完成分析类查询。借助与 Flink,TiDB 可以很好的与 Pravega 适配,提供实时的、高吞吐的、稳定的数仓系统。满足用户在大数据场景中对各类数据的分析需求。