什么是流处理?以及2016年发生的事件

这篇文章讲述了什么内容?

流处理最初就是从某个地方开始的,它是关于必要考虑事项的信息的总结,供回顾使用。
此外,我还总结了今年个人认为对这个领域影响很大的事件。

为了作为解释给其他人的基础而总结,对于已经熟悉这个领域的人来说,可能会有很多冗长的内容。如果是这种情况,可以适当地跳过阅读。此外,我还从我的其他文章中提取了一些内容,所以可能会有一些重复。特别是关于谷歌对于流数据处理的想法,可能会有些重叠的目的……

我打算尽量不使用太多特定的词汇来写,如果有哪个地方不明白,请您留下评论,谢谢。

在中文中,只需要一个选项将其重述为:“当只写‘流处理’时,容易与流媒体传输等混淆,但在这里我们指的是处理数据流的技术集群,所以我们将其描述为‘流处理’。”

仅提供一种中文的选择来释义以下内容: 参考资料

由于在文章中适时插入引用资料会导致文章变得杂乱无章,所以我将它们统一放在开头。
关于GoogleCloudDataflow方面,说它是否通用有些微妙,
但从将模型通用化并融入其中的意义来看,可以将其归类为如此。

流处理的通用性
    • The world beyond batch: Streaming 101

 

    • The world beyond batch: Streaming 102

 

    • The Evolution of Massive-Scale Data Processing

 

    • MillWheel: Fault-Tolerant Stream Processing at Internet Scale

 

    • The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing

 

    • Streaming Engines for Big Data

 

    • Introduction to Streaming Analytics

 

    • Stream Processing Myths Debunked:Six Common Streaming Misconceptions

 

    A Practical Guide to Selecting a Stream Processing Technology
阿帕奇·宾 Beam
    • Apache Beam and Google Cloud Dataflow

 

    • The Beam Model

 

    Dynamic work rebalancing in Apache Beam
AWS (亚马逊云服务)
    AWS上でのリアルタイムデータ分析入門
对流
    Apache Flink and Apache Kafka Streams: a comparison and guideline for users
数据洪流
    THROUGHPUT, LATENCY, AND YAHOO! PERFORMANCE BENCHMARKS. IS THERE A WINNER?
数据艺术家
    Stream Processing as a Foundational Paradigm and Apache Flink’s Approach to It

什么是流处理?

实际上,指的是什么东西?

流处理这个词用于各种不同的应用。
因此,我们将其定义为具有以下特性的处理,即应用和实际系统一般具有的共同点。

    • 無限に発生し続けるデータを処理

常に増大し続け、本質的には無限に発生するデータを処理します。

データ源自体もしばしば「ストリームデータ」と呼ばれます。
システムのログ、センサーデータ、人間の行動ログ等多々存在します。
また、ある巨大ファイルを延々読み込む場合も、読込み結果自体はストリームデータと言えます。

処理が永続的に継続

常に増大し続け、本質的には無限に発生するデータであるため、処理も永続的に実行されます。

とはいえ、実際は上記のようなデータであっても一定の時間の区切りをすればバッチ処理でも処理は可能です。
そのため、区別の意味でも永続的に継続するようなものをストリーム処理と呼びます。

常に実行し続けるという性質上、バッチ処理以上に性能の安定性や、スパイク時に死なないことが求められます。

ここから、BackPressureという性質が生まれています。

低遅延、近似値&不定期な結果出力

ストリーム処理はバッチ処理に比べて遅延が小さくなります。
ストリーム処理が生成する結果は以後に説明する性質の関係上、しばしば近似の値だったり、不定期な出力が行われます。

バッチ処理の場合、基本は生成されるのは完全なデータで、出力されるのはバッチ処理が実行完了したタイミングと明確ですので、それとの対比になります。

综合起来,虽然变得很长,但只需要将其看作是处理无穷无尽的数据的模型即可。

这是用来做什么的?

虽然只是一种例子,但似乎在以下情况下被使用。

    • 課金処理

クラウド系サービスの利用料課金
携帯電話の通信料課金

ライブ費用見積

クラウド系サービスの利用状況からの課金見積り
携帯電話の通信量見積もり

不正・異常検出

あるシステムに対する不正ログイン検知
システムの異常検知
気象データの異常検知
株価の異常振れ幅検知
ユーザの行動に対するレコメンド

不正・異常検知ではないですが、特徴的な行動に対する反応ということでここに挙げています。

不正検出結果復旧

不正ログイン検知の結果対応

不正を検知したタイミングで一度停止後、再開などの対応

システムの異常復旧
気象警報後の経過通知
異常を検知した結果、即対応できるものをした後の事後対応

系统采用什么样的结构?

在这里,我将说明一般流处理系统采用的系统配置。因为如果不在这里说明,后面的情况可能无法想象。

在进行流处理的系统中,常见的配置如下所示。
关于每个配置要素,将在“实际的流处理系统是什么样的?”中进行再次解释。

StreamProcessingSystemArch.png

正如您所见,我们会将数据临时缓冲到消息总线的位置,并获取缓冲的数据以进行流处理。

批处理有什么不同?

流式处理和批处理显然有不同的情况,首先让我们列举一些大数据的主要处理模式。

大数据的典型处理模式

ビッグデータ処理一覧.png

批处理

把存储在数据存储中的数据进行批量转换并输出结果的处理模型。
系统通常采用以下构架。

バッチ処理モデル.png

对话式查询

执行查询并获取结果的模型,对存储在数据存储中的数据执行查询。通常采用以下系统配置。

対話型クエリモデル.png

根据上述图来看,这只是批处理的一种变形。在这种情况下,”输出目标”和”执行源相同”。

当我们看实际的流程模型时,批处理和流处理在执行时间上部署进程,而交互式查询通常会常驻进程等方面有所不同,我们不深入详细讨论这些差异的细节。从对已存在的数据进行分布式处理并输出(获取)结果的角度来看,与批处理没有多大区别。

然而,最近流行的“持续查询”的方式允许事先设定查询条件,并在实时中获取符合条件的数据,因此将成为涵盖批处理和流处理两种模型的综合模型。
也就是说,虽然在典型的处理模式中只属于其中一项,但实际上可以包含在批处理或流处理中的任何一种。

因此,我們將在後續的解釋中省略此模型。

流处理

请参考之前的说明。关于系统的结构,请参考“实际的流处理系统是什么样的?”

批处理和数据流处理的区别。

在此之上,我们来提取批处理的假设。
批处理是在以下基础上构建的。

    • バッチ処理実行時に全てデータが揃っており、処理対象の範囲が明確でないといけない。

 

    バッチをまたいだ結果出力は基本的に対応しない。

我认为第一个前提是,批处理是将原始数据完全整理成以下的形式。

Batch_01.JPG

如果要输出多个结果,则需要按照下面的方式执行多次批处理。

Batch_02.JPG

如果按照时间分段结果的话,我们会根据包含所有数据的基础上执行批处理。

Batch_03.JPG

如果要输出关于第二个前提的图表(指的是在一定时间段中连续访问的用户会话),可以参考下面的图表。
如果分别输出星期二和星期三的结果,那么跨越日期的会话将被分割。
如果想要将星期三的结果与星期二连接起来,可以读取星期二的结果并重新输出结果,但实际操作起来并不现实,因为需要读取所有过去的结果并进行连接。

Batch_04.JPG

从这里看,可以注意到批处理的第二张图可以按照以下方式进行变形。

BatchFiles.png

这就是将无限的流数据按照固定时间间隔划分开的东西。

BatchInputAsStream.png

换句话说,批处理是流处理模型中的一种有限处理方式。

然而,流处理不可以应用于以下示例,它适用于批量处理的前提条件。

    • バッチ処理実行時に全てデータが揃っており、処理対象の範囲が明確でないといけない。

> 無限のデータであり、常時データは到着し続けるためデータが揃うということはない。

バッチをまたいだ結果出力は基本的に対応しない。

> そもそも無限のデータを処理つづけるもののため、前提自体が違う。

如果在执行时数据都已经存在(存在按时间分隔的数据),那么与批处理相同的操作是可以执行的。
在这方面,可以体会到批处理只是流处理中的一个有限处理模型。
(※然而,这只是在功能上如此,人类理解易度、管理易度和性能效率等自然需要分别进行比较。)

在批处理中没有的新问题是什么?

在进行流处理处理无限数据的情况下,会出现新的困扰。
这就是所谓的“数据不按照发生顺序到达系统”(Out of order)。

如果执行从智能手机收集数据的流数据处理时,如果信号断开,然后一段时间后信号恢复,那么会有“信号中断时刻的数据”稍后到达。

关于“乱序”项,可以考虑如下内容。

    • 大きなずれが発生する要素

ネットワーク切断
上記のスマートフォンの事例もそうですね。
ネットワーク遅延

小さなずれが発生する要素

分散システムであるがゆえに発生する遅延
これは複数のマシンで構成される以上必ず発生する要素です。
マシン間の時刻のずれ

由于上述情况存在,流处理中存在以下多个时间概念。

    • イベント時刻(EventTime)

実際にデータを生成することとなったイベントが発生した時刻

到着時刻(IngestTime)

システムにデータが到着した時刻

処理時刻(ProcessingTime)

実際にストリームデータを処理した時刻

然而,本质上重要的是存在多个时间点和无序性。因此,我们将在之后的讨论中仅考虑事件时刻(EventTime)和处理时刻(ProcessingTime)。

你为什么会因此而苦恼呢?

即使数据到达的时间延迟,只要数据之间没有关联,就可以理解为“结果是近似值”,在构建系统时特别困扰的问题并不存在。
只要数据到达系统,就可以继续处理。
(※判断何时全部到达的时机是另外一个问题。)

然而,正如刚才在批处理处理模型的图表中所示,流式处理中可能需要一种称为窗口的概念。例如,对于异常检测,仅通过一次访问很难检测到异常情况,因此主要是通过与前后数据的相关性来检测异常,比如”在短时间内发生了大量登录失败”。

    • 固定長ウィンドウ(Tubling Window)

1時間ごと、等の一定の時間ごとに区切った範囲のウィンドウ

スライディングウィンドウ(Sliding Window)

毎分、過去5分間分の結果を集計して出力するといった範囲が移動するウィンドウ

セッションウィンドウ(Session Window)

一定時間以内にアクセスが連続した場合にそのアクセスを紐づけるという長さが固定されないウィンドウ

WindowVariation.png

在这里,”数据不是按照发生顺序到达系统”成为一个重大问题。因为,如果在输出了”17:00~17:59期间发生的数据的固定长度窗口聚合结果”之后,”17:10发生的数据”延迟到达,那么就会出现问题。

如何才能解决新出现的问题?

在数据不是按照产生顺序到达系统的情况下,通过组合三个元素来更容易应对输出窗口的结果。

处理事件的截止时间点(水印)

水印是一个概念,用于表示在事件时间基础上处理的进度到达了多远。
如果事件时间和处理时间是分开存在的,则实际处理时间和事件时间的处理进度会有所偏差,如下图所示。
因此,需要引入水印概念。

Watermark.png

举例来说,当Watermark取得X的值时,它表示“早于X的事件时间的数据已经全部处理完毕”。换句话说,Watermark在处理无限数据的过程中,作为一个“分隔点”来指示处理的进展。
但需要注意的是,Watermark永远不可能是完全准确的。因为数据可能会延迟到达,所以Watermark只是一个“大致延迟到这个程度”的估算。
(※也许会有人质疑为什么需要这样的估算,但由于只有这样才能进行处理,所以必须进行估算。)

定义一个机制(触发器),用于确定在何时输出统计结果。

Trigger机制是根据情况来定义何时输出窗口聚合结果的机制。
通过定义Trigger,可以灵活地确定何时应该输出窗口聚合结果。
此外,Trigger机制还可以实现在数据更新时多次输出窗口聚合结果。
通过这个机制,一旦Watermark到达固定位置或者晚于Watermark的数据到达时,可以及时进行投机式的输出。

举个例子,在Clouddataflow中,如果Watermark达到了固定长度窗口的最后位置,就可以用下面的代码来输出聚合结果。

PCollection<KV<String, Integer>> scores = input
  .apply(Window.into(FixedWindows.of(Duration.standardMinutes(2)))  // 固定長ウィンドウを宣言
               .triggering(AtWatermark()))                          // Watermarkが到着したタイミングで出力
  .apply(Sum.integersPerKey());

除了上述的情况之外,如果延迟的数据到达时需要重新输出结果,可以按照以下方式进行描述。

PCollection<KV<String, Integer>> scores = input
  .apply(Window.into(FixedWindows.of(Duration.standardMinutes(2)))  // 固定長ウィンドウを宣言
               .triggering(
                 AtWatermark())                                     // Watermarkが到着したタイミングで出力
                   .withLateFirings(AtCount(1))))                   // 遅れデータが1件到着するごとに出力
  .apply(Sum.integersPerKey());

此外,当延迟数据到达时,我们将保留窗口的时间限制设定为最多5分钟的延迟。如果数据在此之后到达,则可以按以下描述进行删除。

PCollection<KV<String, Integer>> scores = input
  .apply(Window.into(FixedWindows.of(Duration.standardMinutes(2)))  // 固定長ウィンドウを宣言
               .triggering(
                 AtWatermark())                                     // Watermarkが到着したタイミングで出力
                   .withLateFirings(AtCount(1)))                    // 遅れデータが1件到着するごとに出力
               .withAllowedLateness(Duration.standardMinutes(5)))   // 遅れの許容を5分間まで
  .apply(Sum.integersPerKey());

简而言之,我们可以通过触发器的机制来控制下列情况。

    • 集計結果の出力タイミング

 

    • Out of orderなデータへの対応

出力を行うタイミング
EventTimeとProcessingTimeのずれの許容期間

在输出统计结果时使用的累积计算方法(累积)

Accumulation定义了在同一个窗口中多次输出聚合结果时的关系和操作。
这取决于聚合结果的输出系统,也就是根据使用方式而定。

在输出系统将之前的汇总结果相加的情况下,如果在一次窗口中输出汇总结果,则该值将被丢弃,下一次输出应该是新数据的汇总结果。
相反地,如果输出系统是基于用户ID和时间的Key-Value存储等数据结构,则即使在一次窗口中输出汇总结果之后,仍需要保留该值,下一次输出需要将现有数据和新数据的汇总结果合并输出。

Accumulation 是一种机制,用于切换关于处理类似于上述统计结果输出时的值的方式。

积累模式主要存在以下三种方式。

    • 破棄モード(Discarding)

ウィンドウの集計結果を出力したタイミングで集計結果は破棄されるモード
つまり、ウィンドウの集計結果を一度出力した場合、状態はクリアされ、次の集計出力においては、出力後に到着したデータのみの集計結果を出力する動作となります。
このモードは下流のシステムが自前で何かしらの累積計算の機構を保持している場合に有用です。

例えば、集計値として前回との差分を送信し、外部システムはその値を合計して最終結果とするなど。

累算モード(Accumulating)

ウィンドウの集計結果を保持し続け、前の値に対してその後の値を累算させて値を出力するモード
このモードは新しい結果で古い結果を上書きすればいい場合に有用です。

例えば、BigTableのようなKVSに結果を出力するケースなど。

累算&後退モード(Accumulating & Retracting)

累算のモードに似いますが、新たな集計結果を出力する時には前回の値を基にした相殺するための差分値(後退値)を出力するモード
後退(前の値と今回の値を基にした結果)の方式で基本的な考え方として、「以前は結果をXとしたが、それは間違っていた。Xの代わりにYで更新するよ。」となります。
このモードは下記のような場合に有用だと考えられます。

Session Windowを使用する場合に新しい値は単に前の値を更新するだけでなく、前のWindowの値を統合するなど
下流のシステムが複数存在し、各々異なる方式で集計を行うなど

通过实际比较多种模式的操作,可以清楚地了解每个模式之间的差异。

假设在12:00至12:02之间进行数据汇总,数据接收的顺序如下。

No処理時刻イベント発生時刻イベントの値112:0512:027212:0612:007312:0712:018

经过这样的操作,不论是累加与回退模式看起来显得意义难懂,但从这样看来,最终的值也好,总计的值也好,都能看出保持了一定的数值。

破棄モード累算モード累算&後退モードEvent1777Event271414,-7Event382222,-14最終値82222総計値224322

在处理这个问题上,能够对所有的情况都做出应对是不可能的吧?

在引入水印、触发器和累积机制后,不意味着流处理就可以应对所有情况。

因为会出现以下这些问题,所以才会这样做。

    • Watermarkを実時刻からどれくらい遅らせて設定すればいいのか?

遅れを大きくすれば正確性は増しますが、遅延時間は大きくなります。

Accumulationのためにウィンドウの集計結果をどれだけ保持すればいいのか?

保持する時間が長いほど、ストリーム処理を行うシステムのリソースが必要となります。

数据处理系统(包括批处理和流处理)被认为有以下三个要素的权衡。

    • 完全性(Completeness)

 

    • 低遅延(Low Latency)

 

    低コスト(Low Cost)

无法同时满足这三个要素,所有的数据处理系统都是由这三个要素的平衡构成的。
在这里,成本不仅指数据处理系统的资源,还包括对收集数据的路径等的成本。

例如,对于付费处理,我们将完整性视为重要,即使会稍微延迟或增加一些成本也不会成为问题。

Billing.PNG

然而,在异常检测系统中,低延迟是最优先考虑的,其他要素的优先级相对较低。

AbuseDetection.PNG

由于存在这样的情况,我们需要根据实际开发的系统来确定需要什么,并找到一个合理的平衡点。

实际的流处理系统是什么样的?

由于已经讨论过迄今为止的流处理是什么,接下来将解释进行流处理的流处理系统会是什么样子。

系统配置

系统配置之前也出现过,但大多数情况下使用如下图所示的配置。

StreamProcessingSystemArch.png

我将解释各个构成要素的角色。

消息总线

由于流处理系统是处理持续发生的无限数据的源,因此经常会突然出现数据流量剧增的峰值。

此外,在发生障碍时,还有可能需要保证消息的处理,并且可能需要多次获取相同的消息。

因此,通常采用将数据临时存储在消息总线中的方法。

    • 使用される主要なプロダクト

Apache Kafka
(Distributed Log)
(Pulsar)

使用される主要なマネージドサービス

Amazon Kinesis Stream
Google Cloud PubSub
Azure Service Bus

流处理基础设施

从消息总线中获取数据并进行流处理的基础部分。
由于始终持续运行,因此需要更高的进程稳定性,与批处理相比,通常更加重要。

请确认有关被使用的产品和服务的数量和想法较多的问题,即“有哪些流处理基础设施可用?”

数据使用目的

将在流处理基础设施中处理的数据输出,并用于实际使用的功能。
对于这部分来说,它完全依赖于系统,因此不能一概而论。

还有一种模式是将数据使用的目的地再次变为消息总线,然后通过多个阶段进行流处理。

在流媒体处理基础设施中,有哪些选项?

我将介绍有关在流处理系统中执行数据处理的产品和服务,以实现流处理基础设施。

流处理基础设施之谱

首先,如果我们查看流处理平台的历史,结果如下:

StreamProcessingSeries.png

然而,即使是称之为流处理基础架构,由于其性质微妙地变化,所以我们假设进行了几个分类。
当仔细研究后,严格来说,这些分类并不适用,但为了简单明了的目的,我们按照上图进行了划分。

按照每个类别进行分类

每个类别都具有以下的定位/功能。

    • ストリーム処理エンジン

特に他に特別な機能を持たないストリーム処理エンジン

UIでDataflow定義

UIでDataflowが定義可能になっており、その定義の通り動作する機能を保持

DSL

同一の記述で複数のストリーム処理エンジン上でアプリケーションが実行可能

マネージドサービス

クラウド上で実行基盤が提供。アプリケーションをデプロイするとそれに従って動作する。

产品说明(部分内容)

我将解释一些图中产品和服务的概要。
由于基准是我自己对这些事物有一定了解,所以可能会有一些偏见…

暴风雨

    • 2011年にTwitterによって公開

 

    • 実装言語:Clojure

Clojureが読み書き出来ないと深い問題は追えない。

実質的にユーザに対して初のOSSストリーム処理エンジン

メッセージの処理セマンティクスとして、At Least Onceが可能になったのが大きい。

ただし、初期のプロダクトのため問題も多かった。

初期はメッセージ単位の処理であり、レイテンシは低いがスループットが小さい。
データ取得側の性能が高いとあふれて死ぬ。
デフォルトのスレッド配置が非効率。
At Least OnceのAckの処理効率が非効率。

以後のストリーム処理プロダクトに大きく影響している。

实时数据流计算

    • 2013年にamplabによって公開

 

    • 実装言語:Scala

 

    • バッチ処理フレームワークSpark上で小バッチを連続実行し、ストリーム処理を実現

マイクロバッチと呼ばれる。
発表時点で、主にStormと比してスループットは大きいが、レスポンスは遅い。

現時点ではFlinkやApexが出てきており、それと比べると両方微妙な状況。
全体として、大規模クラスタを前提としているSparkのアーキテクチャに沿っているため効率も悪い。

Sparkエコシステム上で実行可能なのが大きい。

機械学習ライブラリの利用
SQLによるデータ操作
開発手法も同様のものが利用可能

你菲

    • 2014年にNSAによって公開

 

    • 実装言語:Java

 

    • 画面上でデータフローを定義し、複数サーバにデプロイして実行可能

HTTPでデータ取得>変換>HDFSに投入 etc…
コンポーネント間のキュー毎に優先度設定やQoS設定が定義可能

各データの発生元や処理履歴の確認機能があり、個別のデータ単位で実際にどう処理が行われたかを追える。

Flink (弗林克)

    • 2014年に公開

実際は2011年からStratosphereとして公開されてはいた

実装言語:Scala
バッチ処理とストリーム処理両方のAPIを提供するデータ処理エンジン
障害対応のための状態の自動保存として、効率のいい分散スナップショット方式を使用

自動的に各コンポーネントの状態を保存
詳細はApache Flinkの分散スナップショットの方式参照

高レベルAPIと低レベルAPIの両方を提供

簡易なものは簡単に組める。

尖顶

    • 2015年にDataTorrentによって公開

 

    • 実装言語:Java

 

    • 元々金融アプリケーション用プロダクトで可用性、耐障害性重視の設計

運用時の問題切り分けも容易な構成
メッセージバッファリングで障害発生時の影響を低減

状態の保存、実行環境共にバランスよく高レベル

HDFSをKVSのように使って耐障害性とレスポンスを両立
YARN上でオーバーヘッドが少なく動作可能

スケーラビリティにも優れた構成

ストリーム処理中にAutoScalingが可能

Gearpump is a term in English and does not have a direct translation in Chinese. However, it can be paraphrased as “齿轮泵” (chǐ in Chinese, which is the common term used to refer to a gear pump.

    • 2015年にIntelによって公開

 

    • 実装言語:Scala

 

    • Googleの「MillWheel」に影響を受けたプロダクト

ストリーム処理モデルの論文

Actorベースの「薄い」構成で拡張性が高い。

その分、状態管理なども自前で準備する必要有
開発コストは高めだが、性能的にも優れる。

Reactive Streamsに準拠しており、標準化されたBack Pressure機構を保持
Akka Stream方式の記述により直観的にグラフを定義可能

光束 shù)

    • 2016年にGoogleによって公開

 

    • 実装言語:Java

 

    • バッチ処理/ストリーム処理を抽象化し、複数の実行エンジン上にデプロイ可能なDSL

下記のストリーム処理エンジンに対してデプロイ可能(端的に最近のJVM上ストリーム処理エンジンなら大体対応)

ローカル環境(デフォルト)
Google Cloud Dataflow
Apache Spark
Apache Flink
Apache Apex
Apache Gearpump

ポータビリティは高いが、各エンジンの固有拡張機能、固有ライブラリは使用できない。

機械学習などの機能を使用する場合、別途TensorFlowなどにデータを渡して実行する必要がある。

谷歌云数据流

    • 2015年にGoogleによって公開

 

    • Beam(公開当初はDataflow API)で記述した処理をマネージドサービス上で動作可能

 

    • 他のマネージドサービス系プロダクトに比べて、可能な処理の幅が広い

「ストリーム処理アプリケーション」として記述可能であるため

CPUの利用率を極力高めるように自動で調整されるため、リソースの遊びが発生しにくい。

亚马逊 Kinesis 分析

    • 2016年にAmazonによって公開

 

    • SQLでストリーム上に流れているデータに対して継続的クエリを実行可能

出来る機能は絞られるが、非常にお手軽にストリーム処理を定義可能
データを蓄積する前に分析・アクションを実行するというData in Motionの考え方のベース

SQL方式ではあるものの、EventTimeとProcessingTimeの区別が可能など、機能はそこそこ広い。
内部で自動的にスケールするが、その分リソース使用量が事前に読みにくい。

用哪个比较好? ?)

从现在来看,就个人而言,如果在本地环境中运行的话,我认为Flink和Apex在性能、功能和开发效率方面都能取得很好的平衡。Gearpump虽然在说明中被提到了,具有高度可定制性和性能,但由于需要将各个元素实现为Actor,所以在开发大量应用时,开发效率上给人印象稍微欠缺。由于在迁移批处理时成本较低,所以在现阶段如果已经在使用Spark的话,Spark Streaming是比较合适的选择。

如果在云上执行的话,最好使用您目前正在使用的云服务提供商的服务。

在构建流处理系统时需要注意的事项是什么?

在构建流处理系统时要考虑的要点和在开发时要设置的要点,以及要注意的陷阱和常见误解等进行总结。

需要考虑的要点

在构建流处理系统时,有许多需要考虑的要点。我们将总结其中几个代表性的要点。

    • 状態管理方式

「状態」をローカルに管理するか?それともリモートのデータストアに管理するか?

耐障害性とパフォーマンスのトレードオフが発生
障害復旧時にどれくらいかかるか?

その「状態」に対してアクセス可能な構成になっているか?

データの抽象定義

データをどういう形式としてとらえて処理するか、という観点
大体のストリーム処理エンジンはデータストリームとしてデータを扱う
Kafka Streams、Spark Streamingでは一定の間隔ごとの実行結果を「Table」として扱うことも可能

時刻モデル

EventTimeを扱う必要があるか、それともProcessingTimeだけでいいのか?

ProcessingTimeだけでいい場合、大幅に単純化するため、諸々コストが下がる。
ただ、あとから切り替えるのは大変なので、あらかじめ決めておくこと。

ウィンドウ処理

「何故それで困るのか?」で記述していますが、どの種別のウィンドウ処理が必要になるか?

Out of orderなデータへの対応

「バッチ処理にはないどういう新たな困った点があるのか?」「新たな困った点をどうやったら解消できるのか?」参照
どこまでを許容するか、どう扱うかを決める必要がある。

再処理が可能な構成にするか?

A/Bテストを行ったり、機能の追加や不具合対応を行った際に再処理を可能にするか?
再処理を可能とする場合、既存のデータとの互換性維持やどうマージするかということが事前に検討が必要。

処理の拡張・縮小

実行中に処理規模の縮小・拡大を可能とするか?
それともアプリケーションの再起動で問題ないのか?
最小実行単位はどの単位になるか?

基本、ストリーム処理システムは常時実行となるため、最小でもこれは常に必要と明確にすることが必要

メッセージ処理セマンティクス

メッセージの処理セマンティクスとして、どれを適用すればいいのか?

At most once
At least once
Exactly once

全ケースをカバーするExactly onceは存在しないため、それを大前提に置く必要がある。

ストリーム処理エンジンで保証可能なのは、「自身の内部状態がExactly onceで処理した状態になっていること」
外部へ出力を行う場合には活用する側でデータのキーで重複除去を行ったり、Accumulation方式による対処が必要

耐障害性

障害が発生した場合にどれくらい影響や遅延が出る構成になっているか?
障害発生時は自動で復旧するのか?それとも手動か?
障害復旧にかかる時間はどれくらいか?

バックプレッシャー機能の有無

構成要素間でスループットの差分が発生した場合に、下流に合わせて流量を制御する機能
この機能がない場合、事前にどれだけのスループットが出るかを見切っておく必要が出る。

セキュリティ

保存するデータの暗号化が必要か?

必要な場合、どのタイミングで暗号化しておくか?

アプリケーション毎にどのデータにアクセス可能かの制御をどう行うか?

データの処理モデル

レコード毎の処理か?(マイクロ)バッチモデルか?

レコード毎処理するモデル

低レイテンシが特徴だが、スループットを出せるかは実行エンジンに依存。
Out of orderなデータの取り扱いも行いやすい。

(マイクロ)バッチモデル

バッチ自体に起動終了・状態保存処理も伴うため、マイクロバッチは非常に中途半端な状態になりがち。

開発API

どのような抽象度の開発が可能か?

開発メンバのスキルや優先すべきもの(カスタマイズ性?開発スピード?)等によって検討が必要

開発時のAPIは主に下記の3つ。

宣言型定義(開発スピード〇、カスタマイズ性〇)

map()、filter()などのデータストリームに対する処理を宣言

命令型定義(開発スピード△、カスタマイズ性◎)

process(event)という形で各イベントレベルで処理を実装

Streaming SQL(開発スピード◎、カスタマイズ性△)

データストリームに対して適用するクエリ(STREAM SELECT FROM WHERE….)

ストリーム処理とバッチ処理を同一のAPIで開発可能なのか?

どのような拡張ライブラリが必要か?

機械学習
グラフ処理
外部コンポーネントとの接続

UIの充実性

大抵ストリーム処理エンジンにはUIも組み込まれている

UIからどのような情報が見れるか?
UIからどのようなオペレーションが可能か?

実行グラフが表示されるのも有用

Shuffleの回数などがわかれば、非効率な処理を行っているかについても解析しやすい。

開発サイクルとオペレーション

アプリケーションという形でローカルで実行できるか?それともクラスタ上でないと実行できないか?

ローカルで実行できる場合、テストコード>クラスタ環境の差分を埋めることが出来る。

事前に何かしらのインストールが必要なのか?それともリソースマネージャ上にデプロイすればいいのか?
ログやエラーの集約が可能なのか?

分散処理で個々のサーバからログを取得して確認するのは無謀。
ストリーム処理エンジンの機能か、または独自でログやエラーを一か所で見れるようにしておく必要がある。

アプリケーション更新時に再起動していいのか?それともNo downtimeでローリングアップデートが必要なのか?
既に使用している開発ツールとどれだけ親和性があるか?
いざという時に解析が可能なよう、開発チームが理解できる言語で開発されているか?

实际上,在构建系统时会出现哪些地方会成为瓶颈?

当我们真正构建流处理系统的时候,会遇到各种瓶颈问题。
以下是其中的一个代表性瓶颈。

    • ファイルアクセス

初期の理解が浅い時期に主によくはまる。
データを処理するたびにファイルアクセスが発生するような機能の場合、そこがボトルネックになる。
キャッシュを活用するなどして同期的なファイルアクセスを発生しないようにする必要がある。

不要なプロセス間の通信

バッチ処理でも同様だが、Shuffleを実行した時のプロセス間の通信負荷はストリーム処理でも大きい。
事前にプロセス内で集約しておくなども行い、プロセス間の通信頻度と量を抑えること。

メッセージバスの処理性能が追い付かなくなる

KafkaであればStormやSpark Streamingの時代はメッセージバス側がボトルネックになることは少なかった。
FlinkやApexの世代になってくるとKafkaの性能を振り切ることも多くなってきている。

メッセージバス側のクラスタサイズ調整やレプリケーション設定を見直す。

GC

JVM上で動作するストリーム処理エンジンが多いため、どうしてもぶつかる問題。

まずはJVMのチューニングを行う。
それでもどうしようもない場合

アプリケーションでのオブジェクトの生成数を極力抑える。
オブジェクトに個々のフィールドではなくバイト配列でまとめて持たせる。

对于流处理的误解

我将解释关于流处理常见的误解。

    • ストリーム処理では近似値しか出せず、バッチとの組み合わせが必須である。

初期のStormでは実際そうで、Lambda Architectureという形で対処がとられていました。
今ではWatermark、Triggerなどを使ってそれも制御可能です。

レイテンシとスループットはどちらかを選ぶ必要がある。

それも、初期のStorm VS Spark Streamingの比較から来ている話です。
実際プログラム上ではその2軸のトレードオフはありません。

ただし、今は新たなトレードオフがあるため、「その対処で全部に対応するのは無理なんじゃないの?」を参照

マイクロバッチ方式の方がスループットが高い。

レコード毎処理であってもデータはバッファリングされているため、実際にはそうではないようです。
マイクロバッチ方式はバッチとして区切ることによる管理コストが発生するため、今となっては利点が薄いと言われています。

Exactly onceは不可能

実際に全ケースへの対応は不可能ですが、下記の2ケースを分けて考える必要があります。

「正確に1回実行されたという状態」をストリーム処理エンジン側に維持することは可能です。
「正確に1回外部に通知」は他のデータストアなどとの重複除去機構をかませる必要があります。

ストリーム処理はリアルタイム系の処理にしか適用できない

「バッチ処理とストリーム処理の違い」にあるとおり、ストリーム処理はバッチ処理の機能的な上位互換になります。
そのため、効率は別途確認が必要ですが、リアルタイム系の処理ではなくても適用可能。

ストリーム処理は難しい

無限のデータソースがあり、データが頻繁に変わるならモデルで対応するよりむしろ対応しやすいです。
初期のストリーム処理は命令型定義のみで開発コストが高かったですが、最近は宣言型定義やSQLによる定義も可能になっているため、ハードルは下がっているかと。

2016年发生了哪些与流处理相关的事情?

在这一章中,我将总结2016年发生的流处理方面的一些重要事件。
也就是说,我们将回顾“2016年的重大事件”。
(※个人印象较为深刻的事件)。

Apache Beam的推出

这个对我来说是最大的。

在解释了流处理是批处理的功能上位互换之后,他们通过DSL定义了流处理和批处理,开发出可以在多个环境下共享执行的产品,整个过程流畅而令人激动。

而且,由于DSL的定义通常可以使用Java或Scala进行开发,因此可以直接使用IDE进行开发,这也是一个重要的优点。

亚马逊Kinesis Analytics的发布

尽管从去年开始已经有预告,但随着Amazon Kinesis Analytics上的发布,我们现在能够在托管服务上使用SQL处理Kinesis数据。这使得之前需要使用AWS Lambda或自己处理的任务可以在托管服务上运行。

当然,虽然有限制的范围,但能够轻松地实现是非常重要的。

你认为明年会怎么样?

请不要把这一章完全当作我的妄想,绝对不要认真对待。
并且,其中还掺杂了已经宣布要做的内容,所以也请注意。

我对今年Apache Beam的推出感到非常满足,感觉缺了一个重要的组成部分终于完整了。
因此,尽管构成方面没有太大变化,但我们预计明年会有一个稳定的演进。

作为一种确实的进化方向,我个人猜测可能出现的是更容易开发的方向以及对硬件进化的追随方向。

开发变得更容易的方式有API的丰富和UI型产品的扩大。流处理引擎的开发将更容易,按照命令式定义>声明式定义>SQL定义的方式进行,但能提供完整设置的引擎是有限的。因此,我们预计会有多个引擎来丰富其API。

关于UI型产品的扩展,在NiFi和Spring Cloud Dataflow中,可以保存从UI定义的状态,但是从UI进行定义意味着无法通过代码进行管理,使用过程中可能会出问题。因此,我认为应该采用易于上手并且使用过程中容易维护的结构。

追述硬件进化的意思是追随ManyCore、大容量内存的硬件进化,但实际上可能也是为了在其上运行时洗清流处理中会出现的问题。例如,批处理在Boosting Spark性能上可能出现新硬件上的问题。目前还不清楚流处理是否存在相同级别的问题,也没有得到太多有关流处理引擎方面的信息。这可能是我只是无知的可能性较大。

尽管我努力寻找论文,但直接找到所需的还未成功。
虽然MES 2016的论文似乎相近,但由于尚未阅读,我无法确定确切情况。

无论如何,就是这个感觉。

总结

感谢您阅读这篇长文。

首先,我解释了流处理的概念。然后,我总结了在实际系统构建中所遇到的问题和需要考虑的要点。最后,我还写了一些关于个人在2016年的经历以及明年可能会发生的事情。

由于一次性写的东西,可能会有错误或不容易理解的地方,如果有的话,请在评论中写下,不胜感激。

bannerAds