Table of Contents
什么是StreamSQL
需求
最初的基于kafka的解决方案
无限期地存储每个域事件
从批处理数据引导物化视图
回填从Kafka
更新传入事件
多租户、回滚和重播、错误处理等。
为什么用Pulsar
分层存储到S3
独立的计算和存储扩展
内装式多租户
积极回应的社区
Pulsar-Based解决方案
无限期地存储每个域事件
从批处理数据引导物化视图
更新传入事件
脉冲星的缺点
集成
缺乏公共案例研究
基础设施的责任
下一步
Pulsar Functions
Streaming DAG
StreamSQL还在测试阶段
StreamSQL是一个围绕事件源构建的数据存储系统。有三个组件组成了StreamSQL:事件存储、转换和物化状态。事件存储是发送到我们系统的每个域事件的不可变的分类账。我们为物化状态提供类似于 Cassandra、Redis 和 CockroachDB 的 api。转换是将事件映射到状态的纯函数。根据转换,我们接收到的每个事件都被处理并应用到物化状态。
StreamSQL 在所有数据上回溯地运行新的转换。结束状态是整个事件流的真实物化。此外,您可以通过回滚和重放事件来生成“虚拟”状态。虚拟状态可用于训练和验证机器学习模型,并用于调试目的(如前端开发的 Redux)。
系统需要能够做到以下几点:
最初的基于 kafka 的解决方案由一组拼接在一起的大数据工具组成。系统将过去的事件存储在S3中,并使用 Spark 处理它们。对于流数据,它使用了 Kafka 和 Flink。保持事件和物化视图的一致性需要在每个系统之间进行复杂的协调。
每个域事件将通过 Kafka 进入系统,然后将其保存到 S3 中。这使我们能够存储大量很少使用的数据,并且具有高持久性和低成本。
我们试图使用 Kafka 在流上的无限保留,但是发现它很贵而且不容易维护。在更大的主题上,我们开始看到性能下降和不稳定的延迟。我们没有进一步的研究,因为我们几乎完全移到了 Pulsar 上。
我们通过按顺序处理每个事件来实现视图。我们使用 Spark 处理存储在 S3 中的大部分历史数据。如果我们可以暂停事件,这将简化事情。在这种情况下,我们可以读取所有 S3 数据,然后在主题的开头切换到处理 Kafka。实际上,从 Kafka 持久化到 S3 的事件之间有一个延迟,从大的批处理集群到小的流处理集群之间有另一个延迟。
我们不能错过处理任何事件,所以我们使用 Spark 处理尽可能多的事件在S3中然后返回最后一个事件的ID。自从我们配置卡夫卡保留过去几周的数据,我们可以从 Kafka 那里把剩下的事情补回来。
Spark 能够处理过去的大多数事件,但它并没有把我们带到最新的状态。为了处理最后一组过去的事件,我们将 Kafka 集群配置为保留最后两周的已确认事件。我们运行一个 Flink 作业来继续 Spark 启动的 SQL 转换。
我们将 Flink 指向 Kafka 中的第一个事件,并让它重新消费一遍,直到它到达 Spark 停止的 messageID 为止。从那时起,它将继续更新物化视图,直到它到达流的末端。最后,它通知转换 API,物化的视图是最新的,可以使用了。
一旦启动,StreamSQL 必须保持物化视图是最新的。在这一点上,这个问题是微不足道的。Kafka 将每个传入事件直接传递给 Flink,然后由 Flink 执行必要的更新。此时,转换 API 和 Spark 处于空闲状态。但是,我们仍然将每个传入事件保存到S3中,以防用户更新或创建转换。
我们协调 Flink 和 Kafka 一起工作,以保持物化视图的快照。通过适当的协调,我们可以实现无缝的回滚和回放功能。描述这个过程需要一篇博客文章(我们希望在不久的将来写)。
在这篇博客文章中,我们也不会讨论如何扩展我们的Flink和Kafka集群,如何处理服务故障,或者如何在所有这些不同的服务之间实现安全的多租户(提示:每个解决方案都有不同的答案)。如果你迫切需要知道以上任何一个,请随意联系。我们很乐意分享。
============================================分割线============================================
脉冲星是用来永远存储事件的,而不是在系统之间传输它们。此外,脉冲星是在Yahoo!为在全球范围内构建各种产品的团队服务。它本身支持地理分布和多租户。执行复杂的部署(比如为某些租户保留专用服务器)变得很容易。我们尽可能利用这些特性。这使我们能够把我们的自定义逻辑的一个重要部分交给脉冲星。
StreamSQL 用户可以在任何时候创建新的物化视图。这些视图必须是所有事件的投影,因此每个转换都按顺序处理每个历史事件。在基于 kafka 的解决方案中,我们将所有已确认的事件流到 S3 或 GCS 中。然后,Spark 中的批处理管道处理这些事件。整个系统要求我们协调事件流、批处理存储、批处理计算、流计算和有状态存储。在现实世界中,协调这些系统是容易出错的、昂贵的和难以自动化的。
如果我们可以配置我们的事件存储来永久保存事件,它将允许我们合并我们的批处理和流管道。脉冲星和卡夫卡都允许这样做;然而,Kafka 没有分层存储。这意味着所有事件都必须保存在 Kafka 节点的磁盘上。事件分类账是单调增加的,因此我们必须不断增加存储空间。大多数历史事件不经常读取,因此我们昂贵的磁盘存储的大部分都处于休眠状态。
另一方面,Apache 脉冲星有内置的分层存储。脉冲星将每个事件日志分解成片段,并将不活动的片段卸载到 S3。这意味着只需对 Kafka 进行简单的配置更改,我们就可以获得无限的、廉价的存储空间。我们不需要不断地增加集群的大小,我们可以合并我们的批处理和流管道。
我们可以将 Pulsar 配置为在主题达到特定大小时卸载事件,或者手动运行它。这使我们可以灵活地设置正确的卸载策略来平衡成本和速度。我们正在构建机器学习模型,以使我们的卸载策略适合每个主题的特定需求。
我们的事件量和使用模式在一天和不同的用户之间变化很大。每个用户的不同使用模式导致更大的存储或计算使用。幸运的是,脉冲星将它的代理从它的存储层中分离出来。
脉冲星可以执行三种不同的操作:尾写、尾读和历史读。脉冲星的写作,就像卡夫卡的,总是走到最后。对于脉冲星来说,写入有三个步骤。首先,代理接收请求,然后代理将其写入 Bookkeeper,最后,它将其缓存以供后续的尾部读取。这意味着尾部读取非常快,根本不触及存储层。相比之下,历史读取对存储层的影响非常大。
对于卡夫卡和脉冲星来说,添加存储节点相对容易,但是这是一个非常昂贵的操作。必须对数据进行打乱和复制,以正确地平衡存储节点。在 Kafka 的例子中,代理和存储在相同的节点上,因此任何扩展操作都是昂贵的。相反,在脉冲星中,经纪人是无状态的,而且容易而且便宜。这意味着,读尾不构成一个重大的规模问题。我们可以使集群适应历史读取和尾部读取的当前使用模式。
脉冲星是在多租户的情况下建造的。在雅虎!在美国,许多从事不同产品的地理分布团队共享同一个脉冲星集群。该系统必须处理对不同预算和不同sla的跟踪。它有一个特性集,允许我们在同一个脉冲星集群上运行所有用户,同时保持性能、可靠性和安全性。
每个脉冲星主题都属于一个名称空间,而每个名称空间都属于一个租户。每个 StreamSQL 帐户映射到一个租户。租户之间被安全地隔离开来。一个用户不可能接触到另一个用户的流。
从性能的角度来看,名称空间提供了围绕隔离的其他有趣动态。我们可以将用户的名称空间隔离到一组特定的代理和存储节点。这限制了单个用户对整个系统的影响。同时,我们可以在代理上设置自动卸载,这样单个客户机中的峰值就可以被更大的系统所使用。
脉冲星社区的slack频道非常棒。我几乎立刻就能得到大多数问题的答案,而且我总是通过密切关注来学习新事物。有一些会议和脉冲星峰会,以及面对面的学习和网络。我们知道,在最坏的情况下,我们可以联系相关的人,甚至在我们最小众的问题上获得帮助。社区给了我们推进脉冲星的信心。
脉冲星允许我们将整个不可变的账本存储在脉冲星主题中。我们把它当作是在脉冲星上,但是,在引擎盖下,脉冲星把事件卸载到 S3 中。我们得到了使用事件分类账的简单好处,以及将事件放在 S3 中的成本和维护好处。它比我们的 Kafka 系统表现得更好,而无需我们维护任何复杂性。
脉冲星架构融合了我们的流和批处理能力。这使我们可以消除 Spark 和所有协调代码之间的 Spark 和 Flink。Pulsar-> Flink连接器在批处理和流处理模式之间无缝切换。该体系结构的简单性消除了大量的边界情况、错误处理和维护成本,这些成本在基于kafka的版本中都存在。
我们编写一个作业来处理批处理和流式数据。没有来自我们的任何协调,Flink 保持精确的一次处理和交换之间的批处理和流模式。
脉冲星已经存在了几乎与卡夫卡一样长的时间,并在雅虎的生产中得到了验证。我们认为脉冲星的核心是稳定可靠的。集成是一个不同的问题。有无数的集成要编写。在大多数情况下,脉冲星社区建立并保持其集成。例如,我们希望将S3设置为接收器,并了解到不存在任何开源连接器。我们建立了自己的开源解决方案,以推动社区向前发展,但我们希望在未来找到缺失的集成。
考虑到脉冲星还远没有卡夫卡那么受欢迎,大部分的脉冲星集成都是在脉冲星回购中建立和维护的。例如,我们使用的 Flink 连接器在脉冲星repo中,但是也有一个开放的 Apache Flink 票据来在他们那边构建一个。在脉冲星成为主流之前,仍会有缺失的整合。
几乎所有的脉冲星内容都是由像 Streamlio (acq)这样的脉冲星托管提供商发布的。由Splunk)、Stream Native 和 Kafkaesque。很少有公司会研究脉冲星的案例,他们将脉冲星用于大规模生产,而与脉冲星没有商业联系。有许多大公司在生产中使用它,但他们很少向公众公布他们的经验。公共案例研究使我们能够捡起窍门和陷阱,而不必重新发明轮子。
相比之下,关于卡夫卡的个案研究就比较多。Kafka是最著名的事件流媒体平台,并且还在继续获得流行,所以大多数写数据平台的公司都会深入了解他们是如何使用Kafka的。
我们的脉冲星部署需要一个用于元数据的Zookeeper集群、一个用于存储的 Bookkeeper 集群、一个代理集群和一个代理集群。即使使用 AWS 和谷歌云服务,这也是一大笔维护责任。仅脉冲星就有大量的配置可能性,但是,当你观察较低的层时,它需要多个专业工程师来维护和优化。
目前,我们使用 Flink 来处理流事件并更新我们的物化视图。Flink 不允许向集群添加新节点。相反,我们必须保存一个检查点并使用更大的大小重新启动集群。另外,脉冲星函数是在一个单独的计算集群中运行的,我们可以动态地调整它的大小。
Flink 的处理引擎更有表现力和更强大,但扩展起来要复杂得多。脉冲星很容易测量,但测量范围要小得多。我们将很快能够对转换进行分类,并决定在哪里运行它们,以趋向于脉冲星函数。
StreamSQL 目前不允许转换使用物化视图作为状态。我们正在把这个系统建模成一个DAG(有向无环图),就像气流一样。与气流不同的是,依赖关系不能一步一步地执行,每个事件都必须经过整个DAG。脉冲星将使它更容易维持thsi的保证,因为每个事件通过的DAG。
StreamSQL是一个事件源数据存储。它基于我们的数据基础架构,我们使用它来为超过1亿终端用户的ML模型提供动力。我们已经限制了功能集,并开放了测试版。