mirror of
https://github.com/oldratlee/translations.git
synced 2026-04-14 02:29:54 +08:00
审校
This commit is contained in:
@@ -23,19 +23,19 @@
|
||||
|
||||
<img src="images/19202244_GPDx.jpg" width="250" hspace="10px" align="right" >
|
||||
|
||||
我把流处理视为更广泛的概念:持续数据流处理的基础架构。
|
||||
我认为计算模型可以像`MapReduce`或者分布式处理架构一样通用,但是有能力生成低时延的结果。
|
||||
我把流处理视为更广泛的概念:持续数据流处理的基础设施。
|
||||
我认为计算模型可以像`MapReduce`或者分布式处理框架一样通用,但是有能力生成低时延的结果。
|
||||
|
||||
处理模型的真正驱动力是数据收集方法。成批收集数据自然是批处理。当数据是持续收集的,自然也应该持续不断地处理。
|
||||
|
||||
美国的统计调查是一个成批收集数据的好例子。
|
||||
统计调查周期性的开展,用的是蛮力调查,通过挨门挨户的走访统计美国的公民信息。
|
||||
美国的统计调查是一个成批收集数据的经典例子。
|
||||
统计调查周期性的开展,用的是蛮力调查,通过挨门挨户的走访统计美国公民的信息。
|
||||
在1790年统计调查刚刚开始,这样做是很合理的。
|
||||
那时的数据收集本质就是面向批处理的,包括了骑马到周边人家,用纸笔记录,然后把成批的记录运输到人们统计数据的中心站点。
|
||||
现在,在描述这个统计过程时,人们立即会想到为什么我们不保留出生和死亡的记录,这样就可以算出人口统计信息,这些信息或是持续即时计算出来或者按需要时间隔计算。
|
||||
|
||||
这是一个极端的例子,但是现在大量的数据传输处理仍然依赖于周期性的转储、批量传输和集成。
|
||||
处理批量转储的唯一方法就是批量的处理。
|
||||
这是一个极端的例子,但是现在大量的数据传输处理仍然依赖于周期性的转录和批量的传输和集成。
|
||||
处理批量转录数据的唯一方法就是批量的处理。
|
||||
但是随着这些批处理被持续的数据输入所取代,人们自然而然的开始向持续处理转变,以平滑地使用所需的处理资源并且减少延迟。
|
||||
|
||||
例如在`LinkedIn`几乎完全没有批量数据收集。我们大部分的数据要么是活动数据或者要么是数据库变更,两者都是不间断地发生的。
|
||||
@@ -49,29 +49,29 @@
|
||||
以至于我们实现了一整套[框架](http://engineering.linkedin.com/datafu/datafus-hourglass-incremental-data-processing-hadoop)来管理增量的`Hadoop`工作流。
|
||||
|
||||
由此看来,对于流处理我很容易得出不同观点:
|
||||
流处理包含底层处理的数据时间概念并且不需要静态的数据快照,
|
||||
所以生产输出以用户可控频率而不是等待数据集的『全部』到达可以。
|
||||
它处理的是包含时间概念的底层数据并且不需要静态的数据快照,
|
||||
所以可以以用户可控频率生产输出而不是等待数据集的『都』到达后再生产输出(译注:数据是会持续的,所以实际上不会有『都』达到的时间点)。
|
||||
从这个角度上讲,流处理是广义上的批处理,随着实时数据的流行,流处理会是很重要处理方式。
|
||||
|
||||
那么,为什么流处理的传统观点大家之前认为更合适呢?
|
||||
那么,为什么流处理的传统观点大家之前会认为更合适呢?
|
||||
我个人认为最大的原因是缺少实时数据收集,使得持续处理之前是学术性的概念。
|
||||
|
||||
我觉得,是否缺少实时数据的收集决定了商用流处理系统的命运。
|
||||
当他们的客户还是用面向文件的每日批量处理完成`ETL`和数据集成时,
|
||||
建设流处理系统的公司专注于连接实时数据流的处理引擎,结果就会是当时几乎没有人真地有实时数据流。
|
||||
建设流处理系统的公司专注于提供处理引擎来连接实时数据流,而结果是当时几乎没有人真地有实时数据流。
|
||||
其实我在`LinkedIn`工作的初期,有一家公司想把一个非常棒的流处理系统卖给我们,
|
||||
但是因为当时我们的全部数据都按小时收集在的文件里,
|
||||
但是因为当时我们的所有数据都按小时收集在的文件里,
|
||||
所以用上这个系统我们能做到的最好效果就是在每小时的最后把这些文件输入到流处理系统中。
|
||||
他们意识到这是个普遍问题。
|
||||
下面这个异常案例实际上是证明上面规律:
|
||||
下面的这个异常案例实际上是证明上面规律:
|
||||
流处理获得一些成功的一个领域 —— 金融领域,这个领域在过去,实时数据流就已经标准化,并且流处理已经成为了瓶颈。
|
||||
|
||||
甚至于在一个健康的批处理的生态中,我认为作为一种基础设施风格,流处理的实际应用能力是相当广阔的。
|
||||
我认为它填补了实时数据请求/响应服务和离线批量处理之间的缺口。现代的互联网公司,我觉得大约25%的代码可以划分到这个情况。
|
||||
|
||||
事实证明,日志解决了流处理中最关键的一些技术问题,后面我会进一步讲述,
|
||||
但解决的最大的问题是日志使得多订阅者可以获得实时的数据输入。
|
||||
对这些技术细节感兴趣的朋友,我们可以用开源的[`Samza`](http://samza.apache.org/),
|
||||
但解决的最大的问题是日志使得多个订阅者可以获得实时的数据输入。
|
||||
对技术细节感兴趣的朋友,我们已经开源了[`Samza`](http://samza.apache.org/),
|
||||
它正是基于这些理念建设的一个流处理系统。
|
||||
很多这方面的应用的更多技术细节我们在[此文档](http://samza.apache.org/learn/documentation/latest/)中有详细的描述。
|
||||
|
||||
@@ -97,13 +97,13 @@
|
||||
|
||||
在集成中日志的目标是双重的:
|
||||
|
||||
首先,让每个数据集可以有多个订阅者和有序的。
|
||||
首先,日志让各个数据集可以有多个订阅者并使之有序。
|
||||
让我们回顾一下『状态复制』原理来记住顺序的重要性。
|
||||
为了更具体地说明,设想一下从数据库中更新数据流 —— 如果在处理过程中把对同一记录的两次更新重新排序,可能会产生错误的输出。
|
||||
这里的有序的持久性要强于`TCP`之类所提供的有序,因为不局限于单一的点对点链接,并且在流程处理失败和重连时仍然要保持。
|
||||
这里的有序的持久性要强于`TCP`之类所提供的有序,因为不局限于单一的点对点链接,并且在流程处理失败和重连时仍然要保持有序。
|
||||
|
||||
其次,日志提供了处理流程的缓冲。
|
||||
这是非常基础重要的。如果处理流程是非同步的,那么生成上行流数据的作业生成数据可能比另一个下行流数据作业所能消费的更快。
|
||||
这是非常基础重要的。如果多个处理之间是非同步的,那么生成上行流数据的作业生成数据可能比另一个下行流数据作业所能消费的更快。
|
||||
这种情况下,要么使处理进程阻塞,要么引入缓冲区,要么丢弃数据。
|
||||
丢弃数据似乎不是个好的选择,而阻塞处理进程,会使得整个的数据流的图被迫中止处理。
|
||||
日志是一个非常非常大的缓冲,允许处理进程的重启或是失败,而不影响流处理图中的其它部分的处理速度。
|
||||
@@ -119,7 +119,7 @@
|
||||
比如,给一个的事件流(如用户点击的流)附加上做点击操作用户的信息,
|
||||
—— 实际上即是关联点击流到用户的账户数据库。
|
||||
这类流程最终总是要处理者维护一些状态信息:
|
||||
比如在计算一个计数时,需要到目前为止需要维护的计数器。
|
||||
比如在计算一个计数时,需要维护到目前为止的计数器。
|
||||
在处理者可能挂掉的情况下,如何维护正确的状态?
|
||||
|
||||
最简单的方案是把状态保存在内存中。但是如果处理流程崩溃,会丢失中间状态。
|
||||
@@ -127,11 +127,11 @@
|
||||
但是,如果计数的时间窗口是1个小时这么长,那么这种方式可能不可行。
|
||||
|
||||
另一个方案是简单地存储所有的状态到远程的存储系统,通过网络与这些存储关联起来。
|
||||
但是这会损失数据的局部性并产生很多的网络间数据往返(`network round-trip`)。
|
||||
但问题是没了数据的局部性并产生很多的网络间数据往返(`network round-trip`)。
|
||||
|
||||
如何才能支持即能和处理流程一样分片又像『表』的存储呢?
|
||||
如何才能即支持像处理流程一样分片又支持像『表』一样的存储呢?
|
||||
|
||||
回顾一下关于表和日志二相性的讨论。它正好提供到流转换成与处理相关的表的工具,同时也提供了表的容错处理的机制。
|
||||
回顾一下关于表和日志二相性的讨论。它正好提供了把流转换成与这里我们处理中所需的表的工具,同时也是一个解决表的容错的处理机制。
|
||||
|
||||
流处理器可以把它的状态保存在本地的『表』或『索引』中 —— [`bdb`](http://www.oracle.com/technetwork/products/berkeleydb)、[`leveldb`](https://code.google.com/p/leveldb)
|
||||
甚至是些更不常见的组件,如[`Lucene`](http://lucene.apache.org/) 或[`fastbit`](https://sdm.lbl.gov/fastbit)索引。
|
||||
@@ -163,11 +163,11 @@
|
||||
除非想要使用无限空间,日志总是要清理。
|
||||
为了让讨论更具体些,我会介绍一些`Kafka`这方面的实现。
|
||||
在`Kafka`中,清理有两种方式,取决于数据包括的是键值存储的更新还是事件数据。
|
||||
对于事件数据,`Kafka`支持仅维护一个窗口的数据。通常,窗口配置成几天,但窗口也可以空间定。
|
||||
对于事件数据,`Kafka`支持仅维护一个窗口的数据。通常,窗口配置成几天,但窗口也可以按空间大小来定。
|
||||
对于键值存储的更新,尽管完整日志的一个优点是可以回放以重建源系统的状态(一般是另一个系统中重建)。
|
||||
|
||||
但是,随着时间的推移,保持完整的日志会使用越来越多的空间,并且回放的耗时也会越来越长。
|
||||
因些在`Kafka`中,我们支持不同类型的保留方式。
|
||||
因此在`Kafka`中,我们支持不同类型的保留方式。
|
||||
我们删除过时的记录(如这些记录的主键最近更新过)而不是简单的丢弃旧日志。
|
||||
这样做我们仍然保证日志包含了源系统的完整备份,但是现在我们不再重现原系统曾经的所有状态,仅是最近的哪些状态。
|
||||
这一功能我们称之为[日志合并](https://cwiki.apache.org/confluence/display/KAFKA/Log+Compaction)。
|
||||
|
||||
Reference in New Issue
Block a user