自今年9月Apache Pulsar从Apache软件基金会毕业成为顶级项目以来,Pulsar受到大家越来越多的关注。在这其中,我们看到的一个有趣的现象 -- Pulsar不仅被用于消息系统,而且还被用来存储数据流。这是因为Pulsar提供了良好的可扩展存储架构和层级存储功能。用户对Pulsar中存储的数据的查询需求应运而生。此外,一些用户希望能够在数据到达时即时查询数据,快速响应,而不必等待数据移动到像数据库这样的外部系统。这一反馈促成了Pulsar SQL的发展。
Pulsar SQL是一个在Apache Pulsar 2.2.0中首次亮相的新特性,它允许用户使用SQL接口高效地查询存储在Pulsar中的数据流。
在这篇文章中,我们不仅会介绍Pulsar SQL架构,实现和性能的技术概述,还会讨论Pulsar SQL开发的背景及其应用场景。
背景
Apache Pulsar最初是作为下一代分布式消息系统开发的,用于解决现有消息系统中存在的缺点。现在Pulsar已经发展到比传统的消息系统更多的应用场景。 Pulsar创新的服务/计算和存储分离的分层架构,使用户可以轻松地相互独立地扩展服务/计算和存储资源。轻松自由地添加额外的存储资源的特性,吸引了用户在将Pulsar作为发布/订阅系统之外,还将Pulsar用作存储所有数据流(包括新数据和老数据)的存储平台。
Pulsar的层级存储功能使得“流存储”或“事件存储”的有用性变得更加重要。通过层级存储,用户可以通过云存储(例如Amazon S3,Google云端存储等)扩充现有Pulsar集群中的存储,并以极低的单位成本在云中存储几乎无限量的流数据。
Pulsar存储和存档数据流的能力,结合处理流数据的能力,使得在单个系统中访问实时和历史数据成为可能。这弥补了现有的架构中对多套系统和工具的需要。Pulsar内置的Schema Registry和对SQL查询的支持,让用户更方便地使用Apache Pulsar在一个系统中访问实时的数据和历史的数据。
Figure 1: 利用Pulsar系统生产消费和存储结构化的数据
Pulsar SQL是一个构建在Apache Pulsar之上的查询层,它使用户能够动态查询存储在Pulsar内部的所有新旧数据流。用户现在可以通过在单个系统中查询最新的和历史的数据流来满足更多的应用需求。
Pulsar SQL的一个重要应用场景是它可以极大地简化许多数据管道。在传统的ETL管道(例如用于提供Data Lakes管道)中,数据从一组外部系统中提取,并通过一系列转换来清理数据并将其格式化为所需格式,然后再将其加载到目标系统中。通常,这些步骤串联起来完成整个的处理流程,任何一个步骤中的失败都会停止整个处理过程。这种方法有两个明显的缺点:
-- 每个ETL步骤不可避免地最终被特别设计和映射到它运行的框架上,例如,用于提取数据的Sqoop或Flume作业,用于转换数据的Hive和Pig脚本,以及用于将数据加载到可查询表中的Hive或Impala进程。
-- 该过程本质上是面向批处理的,因此加载到Data Lakes中的数据不与输入数据流保持感知。批次之间的间隔越长,数据的实时性就越低,进而基于数据做出的决策也就越不准确。
Apache Pulsar解决了这两个问题。通过Pulsar SQL,用户可以在同一系统上注入数据的同时进行数据流的清理,转换和查询。由于Pulsar具有可扩展的存储层(Pulsar使用Apache BookKeeper作为其消息存储层),Pulsar消除了对实时处理和批处理两个独立系统的需求,并在系统中将所有数据 - 实时数据和历史数据 - 同等对待。
Pulsar SQL利用Presto和Pulsar的独特架构以高度可扩展的方式执行查询,而不用关注构成数据流的Topic的分区数量。我们将在下一节中进一步讨论其架构。
架构
Pulsar SQL是基于已经成熟的Presto来实现的。Pulsar和Presto之间通过Presto Pulsar连接器来交互。 Presto的连接器在Presto集群中的worker上运行。 通过连接器,Presto worker可以从Pulsar集群读取数据并对该数据执行查询。
下面我们会介绍Presto Pulsar连接器如何有效地从Pulsar中读取数据。 在Pulsar中,生产者将消息写入Pulsar,这些消息被组织成为主题(topic)。 Pulsar中的主题被分片存储为Apache Bookkeeper中的分段,每个主题分段会被复制到存储层的Bookies节点中(可配置备份数目)。
Figure 2. Pulsar SQL架构.
从图2的架构图中,我们可以发现,Presto的SQL workers从Pulsar Broker中获取topic的metadata,然后直接从存储节点Bookie中读取数据。
Pulsar SQL旨在最大限度地提高数据扫描速度,因此Presto Pulsar连接器利用Pulsar基于分片的架构,直接从Bookies(而不是通过Pulsar的Consumer API)读取数据。
虽然Consumer API适合于在pub / sub用例中使用消息,但它不太适合对批量读取进行优化。为了维持顺序,Pulsar中的每个Topic仅由一个Broker提供服务,从而将读取吞吐量限制为一个Broker的吞吐量。当然为了提高读取吞吐量,用户可以利用多个Partitions组成的Topic,但Pulsar希望用户能够以高效的方式查询主题,而无需修改现有主题。
对于查询的应用场景,我们并不太关心顺序性,我们只需要读取所有数据。而Pulsar的对每个Topic的分片存储架构,为这种需求提供了底层支持。由于Topic的分片及其副本分布在BookKeeper的多个Bookie存储节点上,Presto worker可以并发地从多个Bookie节点中同时读取Topic分段以实现高吞吐量。如果用户想要得到更高的读取吞吐量,只需要简单地在Topic创建时为Topic配置更多的副本。
Figure 3. Worker 并发读取所有可用副本来提高吞吐
Pulsar SQL不仅可以查询存储在Bookie中的数据,还可以查询已放置在云存储中的数据。 通过Pulsar的分级存储,用户不仅可以存储比物理集群实际容量更多的数据,还可以查询这些数据以获取数据的价值。
使用场景
下面我们会介绍Pulsar SQL的一些使用场景。在下面列出了的一些应用场景中,Pulsar SQL都可以帮助用户简化其架构。在传统架构中,完成类似任务通常需要使用多个系统,但通过Pulsar SQL,用户可以只使用Pulsar就可以完成数据的注入和查询。这些应用场景包括:
- 实时分析:Pulsar拥有收到数据后就立即查询数据的能力,这可以满足用户的一些实时应用场景,比如实时仪表板和监控等。
- Web分析/移动应用分析:Web和移动应用程序中用户的使用和交互数据流。通过实时查询这些数据,可以检测使用模式,改进应用程序,定制实时体验等。
- 事件记录和分析:来自用户应用程序的事件日志或来自操作系统的系统日志可由Pulsar处理和存储。Pulsar SQL可以用来查询这些存储的log数据,从而完成应用程序的debug和故障的搜索。
- 事件重放:使用Pulsar SQL可以按照事件发生的顺序查询和提取出一系列事件。例如,在短时间内识别欺诈交易前后发生的一系列事件,通过捕获这些事件流并重播它们以模拟欺诈活动,来为数据科学团队改进其欺诈检测算法。
指南和实践
Pulsar SQL在Apache Pulsar 2.2.0版本中作为预览功能发布。 在Pulsar 2.2.0中包含一些工具可以让用户轻松设置环境并开始使用Pulsar SQL功能。 有关详细的入门指南,请参阅[Pulsar SQL官方文档](http://pulsar.apache.org/docs/en/sql-overview/)
线下活动
Pulsar社区将于12月15在举办上海第一次线下的交流,我们不仅会介绍Pulsar的架构,Pulsar的整个生态,还有丰富的线上实践经验分享,
在12月20日举办的Flink Forward China大会上,我们将为大家讲述更多Pulsar在批流一体方向做的工作。