第 10 章和第 11 章,介绍“大数据”的处理,分两个大类:
大数据处理,主要要解决三个问题:
批处理系统和流处理系统主要解决 2 和 3 两个问题。
谈大数据批处理,绕不过的就是 MapReduce。MapReduce 是大数据处理的老祖宗了。
2004 年 Google 发表了一篇论文 MapReduce: Simplified Data Processing on Large Clusters。论文介绍了 MapReduce 的历史,API 的设计和实现,以及 Google 内部使用了 MapReduce 的一些生产案例,但是没有开源代码。后来,开源社区参考这篇论文自己撸了一个 MapReduce 框架配合 HDFS 使用。
MapReduce 的基本思想是提供一套非常简洁的数据处理 API —— 用户只需要实现一个 map 函数和一个 reduce 函数。剩下的繁琐的扩展性和容错系统问题由 MapReduce 框架负责处理。
Map 函数的输入是「一条记录」,然后经过处理,输出 0~N 个 key-value。Mapper 的输出是 Reducer 的输入。
Reduce 函数的输入是「key + key 相同的所有 value」,输出是本次 MapReduce 任务的结果。
一次 MapReduce 的执行流程如下:
举个例子进行说明:WordCount - 计算文件(一行一个单词)中每个单词出现的次数。
Map 函数:
map(String key, String value) :
// key: file name
// value: file content
for each word w in value :
EmitIntermediate(w, "1");
Reduce 函数:
reduce(String key, Interator values) :
// key: a word
// value: a list of counts
int result = 0;
for each v in values :
result += ParseInt(v);
Emit(AsString(result));
MapReduce 的优点是理解起来简单,实现起来也不难。但是由于 MapReduce 的编程模型过于简单,导致表达能力限制太大,单个 MapReduce 任务并不能完成大量实际上的业务需求。一些比较复杂的系统可能需要 50 ~ 100 个 MapReduce 任务进行组合,这会产生很多中间数据需要写入到分布式文件系统,严重影响执行性能和效率。同时,太多的 MapReduce 任务组合提高了系统的维护难度。
关于 MapReduce 的更多细节,建议阅读论文。
说到流处理,自然不得不提 Apache Spark 和 Apache Flink(其实我也是在网上道听途说,这两个系统我都不怎么了解……)。
Spark 在 2009 年左右诞生于加州大学伯克利分校的著名 AMPLab。最开始的 Spark 其实是个批处理系统,其能成名的原因是它能够经常在内存执行大量的计算工作,直到作业的最后一步才写入磁盘,性能上比 MapReduce 要好不少。后来,Spark Streaming 的出现,Spark 才开始有了能支持流处理的能力。不过,Spark Streaming 是通过 micro-batch(多个记录/事件) 来模拟 stream 的。从 Spark 最近的版本更新看,Spark Streaming 应该是要被新搞出来的 Structured Streaming 代替了。
和 Spark 不同,Flink 处理流的时候是 per-event 的(一个记录/事件)。打个不太严谨的比方,洗头冲水的时候有两种方式:
最后,推荐一篇论文:Google 在 VLDB2015 发表的:The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing。这篇论文提供了一种统一批处理和流处理的 dataflow 模型。
coredump