当前位置: 首页 > 科技观察

以Flink为例,消除流处理常见的六大谬见

时间:2023-03-13 11:45:35 科技观察

以Flink为例,破除流处理的六大误区流处理在他们的组织中被应用来解决数据问题。我们首先要做的是纠正人们对流处理的误解(作为一个瞬息万变的领域,这里有很多值得思考的误解)。在本文中,我们选择了其中的六个作为示例。因为我们熟悉ApacheFlink,所以我们将基于Flink来解释这些例子。误区一:没有批处理就没有流(Lambda架构)误区二:延迟和吞吐量:只能选择一个误区三:微批处理意味着更好的吞吐量误区四:Exactlyonce?ExactlyImpossible误区5:Streaming只能用于“实时”场景误区6:无论怎样,Streaming仍然很复杂误区1:没有批处理就没有streaming(Lambda架构)“Lambda架构”在Apache中是Storm和其他流处理项目早期的一种有用的设计模式。该架构由“快速流层”和“批处理层”组成。之所以使用两个独立的层,是因为Lambda架构中的流处理只能计算出近似的结果(即如果中间出现错误,计算结果不可信),只能处理比较少的部分事件。Storm的早期版本就有这样的问题,但是现在很多开源的流处理框架都是容错的,能够在失败的前提下生成准确的计算结果,并且具备高吞吐量的计算能力。因此无需为了分别获得“快速”和“准确”的结果而维护多层架构。今天的流处理器(比如Flink)可以帮助你同时获得这两种结果。幸运的是,人们不再谈论Lambda架构,这表明流处理正在走向成熟。误区二:延迟和吞吐量:只能选择早期的开源流处理框架,要么是“高吞吐量”,要么是“低延迟”,“海量快速”还未能成为开源流处理框架。代名词。但是Flink(可能还有其他框架)提供了高吞吐量和低延迟。这是一个示例基准测试结果。我们从头来剖析这个例子,具体从硬件层,结合一个有网络瓶颈的流处理流水线(很多使用Flink的流水线都有这个瓶颈)。硬件层面不应该有取舍,所以网络是影响吞吐量和延迟的主要因素。一个设计良好的软件系统应该充分利用网络的上限,不引入瓶颈。但是,对于Flink来说,总是有优化的空间,可以让它更接近硬件所能提供的性能。使用10个节点的集群,Flink现在可以每秒处理最大数量的事件,如果它扩展到1000个节点,它的延迟可以减少到几十毫秒。在我们看来,这个水平比许多现有的解决方案要高得多。误区#3:微批处理意味着更好的吞吐量我们可以从另一个角度谈论性能,但首先让我们弄清楚两个容易混淆的概念:.“通过这项技术,一个流程或任务可以将一个流视为一系列小批量或数据块。”Buffering缓冲技术用于优化对网络、磁盘和缓存的访问。维基百科最好的定义是“一块物理内存,用于临时存储移动数据”。那么第三种意见是,使用微批处理的数据处理框架可以比一次处理一个事件的框架实现更高的吞吐量,因为微批处理在网络上的传输效率更高。这种误解忽略了这样一个事实,即流式框架在任何编程模型级别都不依赖批处理,它们只在物理级别使用缓冲。Flink也会缓冲数据,这意味着它通过网络发送一组处理过的记录,而不是一次发送一条记录。从性能的角度来看,不缓冲数据是不可取的,因为通过网络一个接一个地发送记录没有性能优势。所以我们不得不承认,在物理层面上,不存在一次一个记录这样的事情。但是buffering只能作为性能的优化,所以buffering:对用户来说是不可见的,不应该对系统有任何影响。不应有人为的界限,不应限制系统功能。所以对于Flink用户来说,他们开发的程序可以对每条记录单独进行处理,因为Flink为了提高性能隐藏了使用缓冲区的细节。事实上,在任务调度中使用微批处理会产生额外的开销,而如果这样做是为了减少延迟,那么这个开销只会增加!流处理器知道如何利用缓冲并且不会在任务调度中带来开销。误区4:恰好一次?完全不可能这个神话包括几个方面:从根本上说,Exactlyonce从头到尾是不可能的Exactlyonce是不可能的“恰好一次”观点的存在。“Exactlyonce”原意是“一次性交付”,现在这个词随便用在流处理中,使这个词容易混淆,失去了原本的意思。尽管如此,相关概念仍然很重要,我们不会跳过它们。为了尽可能准确,我们将“一次性状态”和“一次性交付”视为两个不同的概念。由于人们以前使用这两个词的方式,他们一直很困惑。ApacheStorm使用“至少一次”来描述交付(Storm不支持状态),而ApacheSamza使用“至少一次”来描述应用程序状态。一次性状态是应用程序遇到故障时就好像它从未发生过故障一样。例如,假设我们正在维护一个计数器应用程序,该应用程序在失败后既不能向上计数也不能向下计数。这里使用术语“恰好一次”是因为应用程序状态认为每条消息只被处理一次。一次性投递是指接收端(应用外的系统)在故障发生后接收处理的事件,就好像故障没有发生一样。流处理盒不保证在任何情况下都一次性发送,但可以达到一次性的状态。Flink可以做到一次性状态而不会对性能产生明显影响。Flink还可以在与Flink检查点关联的数据槽上执行一次传递。Flinkcheckpoints是应用状态的快照,Flink会定时为应用异步生成快照。这就是为什么Flink在发生故障时仍然可以保证一次性状态的原因:Flink周期性地记录(快照)输入流的读取位置和每个操作数的关联状态。如果发生故障,Flink会回滚到之前的状态并重新开始计算。因此,即使记录被重新处理,记录看起来也只被处理过一次。端到端的一次性处理怎么样?可以通过适当的方式让一个带有事务协调机制的检查点,也就是让源操作和目标操作参与检查点。在框架内部,结果是一次性的,从端到端的角度来看,也是一次性的,或者说“接近一次性”。例如,当使用Flink和Kafka作为数据源并发生数据槽(HDFS)滚动时,从Kafka到HDFS是一个端到端的一次性过程。同样,当使用Kafka作为Flink的source,Cassandra作为Flink的sink时,如果对Cassandra的更新是幂等的,那么就可以实现端到端的一次性处理。值得一提的是,利用Flink的savepoints,checkpoints也可以作为一种状态版本机制。使用保存点,可以在保持状态一致性的同时“随时间移动”。这简化了代码更新、维护、迁移、调试和各种模拟测试。误区5:Streams只能用于“实时”场景这个误区包括以下几点:“我没有低延迟应用程序,所以我不需要流处理器”“流处理只能工作withtransitionsbeforepersistenceDatahasrelationships”“我们需要批处理器来做大量的离线计算”现在是时候考虑数据集类型和处理模型之间的关系了。首先,有两种数据集:Unbounded:从非预定义端点不断产生的数据Bounded:有限且完整的数据很多真实的数据集都是无界的,不管数据是存储在文件中,还是在HDFS的目录中,或者在像Kafka这样的系统中。一些示例:移动设备或网站用户的交互信息物理传感器提供的指标金融市场数据机器日志数据在实践中,很难在现实世界中找到有界数据集,尽管公司所有建筑物的位置信息确实存在边界(虽然它也会随着公司业务的增长而改变)。其次,有两种处理模型:Streaming:只要有数据产生就处理Batches:在有限的时间内结束处理,释放资源我们再深入一点,区分两类没有边界的数据集:Continuityflow和intermittentflow.完全可以在任何类型的数据集上使用任何类型的模型,尽管这不是最好的方法。例如,批处理模型长期应用于无界数据集,尤其是间歇性无界数据集。事实上,大多数“批处理”任务都是通过调度执行的,一次只处理无限数据集的一小部分。这意味着流的无限性质可能会给某些人(在流入管道上工作的人)带来问题。批处理是无状态的,输出仅取决于输入。实际情况是,批处理任务在内部保持状态(就像reducer经常做的那样),但该状态仅限于批次边界,并且它们不会在批次之间流动。当人们试图实现类似于带有“事件时间戳”的时间窗口之类的东西时,“批处理有界状态”变得很有用,这是处理无界数据集时的常见技巧。处理无界数据集的批处理器不可避免地会遇到延迟事件(由于上游延迟),批处理中的数据可能因此变得不完整。请注意,这里假设我们根据事件时间戳移动时间窗口,因为事件时间戳是现实中最准确的模型。在进行批处理时,延迟数据可能会成为一个问题,即使是简单的时间窗口修复(如翻转或滑动时间窗口)也无法修复它,尤其是在使用会话时间窗口的情况下。因为完成一次计算所需要的数据不会全部在一个batch中,所以在使用batch处理无界数据集时,很难保证结果的正确性。至少,它需要额外的开销来处理延迟到达并维护批次之间的状态(等到所有数据到达后再开始处理,或重新处理批次)。Flink内置了处理迟到数据的机制。Latedata被认为是现实世界中无界数据的正常现象,所以Flink设计了一个流处理器来处理latedata。有状态流处理器更适合处理无限数据集,无论它们是连续生成还是间歇生成。使用流处理器只是锦上添花。误区6:无论如何,流仍然很复杂。这是最后的领悟。你可能会想:“理论很好,但我还是不会使用流式技术,因为……”:流式框架很难掌握。Streaming很难解决时间窗、事件时间戳、触发器等问题。Streams需要结合batch,我已经知道怎么用batch了,那为什么还要用streams呢?我们从不鼓励您使用流,尽管我们认为流是一件很酷的事情。我们认为流的使用完全取决于数据和代码的特性。在做出决定之前问问自己:“我正在使用哪种类型的数据集?”Unbounded(useractivitydata,logs,sensordata)Bounded那么再问一个问题:“哪一部分变化最频繁?”CodechangemorefrequentlythandataDatachangemorefrequentlythancode对于数据变化比代码更频繁的情况,比如对频繁变化的数据集执行相对固定的查询操作,就会出现流问题。所以,在决定流式传输是“复杂”的事情,你可能在不知不觉中解决了流!你可能使用了基于小时的批任务调度,团队中的其他人可以创建和管理这些批(在这种情况下,你可能会得到不准确的结果,而且你没有意识到这样的结果是由批处理时序问题和前面提到的状态问题引起的)。Flink社区已经努力了很长时间,提供了一组封装这些时间和状态复杂性的API。通过定义事件时间戳在Flink中很容易处理一个时间窗口和一个提取时间戳和水印的函数(每个流只调用一次)处理状态也很简单,类似于定义Java变量,并且thzh向Flink注册这些变量。使用Flink的StreamSQL在连续流上运行SQL查询。***要点:如果代码更改比数据更频繁怎么办?对于这种情况,我们认为你有一个探索性问题。使用笔记本或其他类似工具进行迭代可能适用于探索性问题。代码稳定后,您仍然会遇到流式传输问题。我们建议从一开始就采取长期方法进行流式传输。流处理的未来随着流处理的成熟和这些误解的消退,我们看到流正在超越分析应用程序。正如我们所讨论的,现实世界正在不断地生成数据。传统方法打破了这种连续的数据流,因为它必须聚合到一个集中的位置或分成多个批次以供应用程序使用。像CQRS这样的流处理模式正变得越来越流行。可以直接基于连续的数据流开发应用程序,可以在本地保存状态,更好地隔离应用程序和团队,可以更好地处理基于时间的数据。随着Flink的不断演进和完善,被越来越多的企业所采用,我们相信它不仅可以简化分析流水线,还可以为我们带来更强大的计算模型。本文由KostasTzoumas撰写。原文:揭穿流处理神话。