diff --git a/doc/_toc.yml b/doc/_toc.yml index 2efcf09..7e9e2db 100644 --- a/doc/_toc.yml +++ b/doc/_toc.yml @@ -5,12 +5,12 @@ subtrees: - file: ch-big-data-intro/index entries: - file: ch-big-data-intro/bigdata - - file: ch-big-data-intro/batch-processing-and-stream-processing - - file: ch-big-data-intro/representative-big-data-technologies - - file: ch-big-data-intro/evolution-of-big-data-processing-platforms + - file: ch-big-data-intro/batch-stream + - file: ch-big-data-intro/technologies + - file: ch-big-data-intro/evolution - file: ch-big-data-intro/stream-processing-basics - file: ch-big-data-intro/bigdata-programming-languages - - file: ch-big-data-intro/exercise-building-data-stream-using-Kafka + - file: ch-big-data-intro/exercise-stream-with-kafka - file: ch-programming-basics/index entries: - file: ch-programming-basics/inheritance-and-polymorphism diff --git a/doc/ch-big-data-intro/batch-processing-and-stream-processing.md b/doc/ch-big-data-intro/batch-stream.md similarity index 50% rename from doc/ch-big-data-intro/batch-processing-and-stream-processing.md rename to doc/ch-big-data-intro/batch-stream.md index 588b81a..124c123 100644 --- a/doc/ch-big-data-intro/batch-processing-and-stream-processing.md +++ b/doc/ch-big-data-intro/batch-stream.md @@ -1,15 +1,21 @@ -(batch-processing-and-stream-processing)= +(batch-stream)= # 从批处理到流处理 -## 1.2.1 数据与数据流 +## 数据与数据流 -在大数据的5个“V”中我们已经提到,数据量大且产生速度快。从时间维度来讲,数据源源不断地产生,形成一个无界的数据流(Unbounded Data Stream)。如图1-5所示,单条数据被称为事件(Event),事件按照时序排列会形成一个数据流。例如,我们每时每刻的运动数据都会累积到手机传感器上,金融交易随时随地都在发生,物联网(Internet of Things,IoT)传感器会持续监控并生成数据。 +在大数据的 5 个 “V” 中我们已经提到,数据量大且产生速度快。从时间维度来讲,数据源源不断地产生,形成一个无界的数据流(Unbounded Data Stream)。如 {numref}`data-and-data-stream` 所示,单条数据被称为事件(Event),事件按照时序排列会形成一个数据流。例如,我们每时每刻的运动数据都会累积到手机传感器上,金融交易随时随地都在发生,物联网(Internet of Things,IoT)传感器会持续监控并生成数据。 -![图1-5 数据和数据流](./img/data-and-data-stream.png) +```{figure} ./img/data-and-data-stream.png +--- +width: 60% +name: data-and-data-stream +--- +数据和数据流 +``` 数据流中的某段有界数据流(Bounded Data Stream)可以组成一个数据集。我们通常所说的对某份数据进行分析,指的是对某个数据集进行分析。随着数据的产生速度越来越快,数据源越来越多,人们对时效性的重视程度越来越高,如何处理数据流成了大家更为关注的问题。 -在本书以及其他官方资料中,也会将单条事件称为一条数据或一个元素(Element)。在本书后文的描述中,事件、数据、元素这3个概念均可以用来表示数据流中的某个元素。 +在本书以及其他官方资料中,也会将单条事件称为一条数据或一个元素(Element)。在本书后文的描述中,事件、数据、元素这 3 个概念均可以用来表示数据流中的某个元素。 ## 1.2.2 批处理与流处理 @@ -19,7 +25,7 @@ ### 2. 流处理 -如前文所述,数据其实是以流(Stream)的方式持续不断地产生着的,流处理(Stream Processing)就是对数据流进行处理。时间就是金钱,对数据流进行分析和处理,获取实时数据价值越发重要。如“双十一电商大促销”,管理者要以秒级的响应时间查看实时销售业绩、库存信息以及与竞品的对比结果,以争取更多的决策时间;股票交易要以毫秒级的速度来对新信息做出响应;风险控制要对每一份欺诈交易迅速做出处理,以减少不必要的损失;网络运营商要以极快速度发现网络和数据中心的故障;等等。以上这些场景,一旦出现故障,造成服务的延迟,损失都难以估量。因此,响应速度越快,越能减少损失、增加收入。而IoT和5G的兴起将为数据生成提供更完美的底层技术基础,海量的数据在IoT设备上采集,并通过高速的5G通道传输到服务器,庞大的实时数据流将汹涌而至,流处理的需求肯定会爆炸式增长。 +如前文所述,数据其实是以流(Stream)的方式持续不断地产生着的,流处理(Stream Processing)就是对数据流进行处理。时间就是金钱,对数据流进行分析和处理,获取实时数据价值越发重要。如 “双十一电商大促销”,管理者要以秒级的响应时间查看实时销售业绩、库存信息以及与竞品的对比结果,以争取更多的决策时间;股票交易要以毫秒级的速度来对新信息做出响应;风险控制要对每一份欺诈交易迅速做出处理,以减少不必要的损失;网络运营商要以极快速度发现网络和数据中心的故障;等等。以上这些场景,一旦出现故障,造成服务的延迟,损失都难以估量。因此,响应速度越快,越能减少损失、增加收入。而 IoT 和 5G 的兴起将为数据生成提供更完美的底层技术基础,海量的数据在 IoT 设备上采集,并通过高速的 5G 通道传输到服务器,庞大的实时数据流将汹涌而至,流处理的需求肯定会爆炸式增长。 ## 1.2.3 为什么需要一个优秀的流处理框架 @@ -27,23 +33,23 @@ ### 1. 股票交易的业务场景 -我们都知道股票交易非常依赖各类信息,一些有可能影响股票市场价格的信息经常首发于财经网站、微博、微信等社交媒体平台上。作为人类的我们不可能24小时一直监控各类媒体,如果有一个自动化的系统来做一些分析和预警,将为决策者争取到更多时间。 +我们都知道股票交易非常依赖各类信息,一些有可能影响股票市场价格的信息经常首发于财经网站、微博、微信等社交媒体平台上。作为人类的我们不可能 24 小时一直监控各类媒体,如果有一个自动化的系统来做一些分析和预警,将为决策者争取到更多时间。 -假设我们有数只股票的交易数据流,我们可以通过这个数据流来计算以10秒为一个时间窗口的股票价格波动,选出那些超过5%变化幅度的股票,并将这些股票与媒体的实时文本数据做相关分析,以判断媒体上的哪些实时信息会影响股票价格。当相关分析的结果足够有说服力时,可以将这个系统部署到生产环境,实时处理股票与媒体数据,产生分析报表,并发送给交易人员。那么,如何构建一个可靠的程序来解决上述业务场景问题呢? +假设我们有数只股票的交易数据流,我们可以通过这个数据流来计算以 10 秒为一个时间窗口的股票价格波动,选出那些超过 5% 变化幅度的股票,并将这些股票与媒体的实时文本数据做相关分析,以判断媒体上的哪些实时信息会影响股票价格。当相关分析的结果足够有说服力时,可以将这个系统部署到生产环境,实时处理股票与媒体数据,产生分析报表,并发送给交易人员。那么,如何构建一个可靠的程序来解决上述业务场景问题呢? -### 2. 生产者-消费者模型 +### 2. 生产者 - 消费者模型 -处理流数据一般使用“生产者-消费者”(Producer-Consumer)模型来解决问题。如图1-6所示,生产者生成数据,将数据发送到一个缓存区域(Buffer),消费者从缓存区域中消费数据。这里我们暂且不关心生产者如何生产数据,以及数据如何缓存,我们只关心如何实现消费者。 +处理流数据一般使用 “生产者 - 消费者”(Producer-Consumer)模型来解决问题。如图 1-6 所示,生产者生成数据,将数据发送到一个缓存区域(Buffer),消费者从缓存区域中消费数据。这里我们暂且不关心生产者如何生产数据,以及数据如何缓存,我们只关心如何实现消费者。 -![图1-6 生产者-消费者模型](./img/producer-consumer.png) +![图 1-6 生产者 - 消费者模型](./img/producer-consumer.png) -在股票交易的场景中,我们可以启动一个进程来实现消费者,该进程以10秒为一个时间窗口,统计时间窗口内的交易情况,找到波动最大的那些股票。同时,该进程也对新流入的媒体文本进行分析。这个逻辑看起来很容易实现,但深挖之后会发现问题繁多。 +在股票交易的场景中,我们可以启动一个进程来实现消费者,该进程以 10 秒为一个时间窗口,统计时间窗口内的交易情况,找到波动最大的那些股票。同时,该进程也对新流入的媒体文本进行分析。这个逻辑看起来很容易实现,但深挖之后会发现问题繁多。 ### 3. 流处理框架要解决的诸多问题 #### (1) 可扩展性 -股票交易和媒体文本的数据量都非常大,仅以微博为例,平均每秒有上千条、每天有上亿条微博数据。一般情况下,单个节点无法处理这样规模的数据,这时候需要使用分布式计算。假如我们使用类似MPI的框架,需要手动设计分治算法,这对很多程序员来说有一定的挑战性。 +股票交易和媒体文本的数据量都非常大,仅以微博为例,平均每秒有上千条、每天有上亿条微博数据。一般情况下,单个节点无法处理这样规模的数据,这时候需要使用分布式计算。假如我们使用类似 MPI 的框架,需要手动设计分治算法,这对很多程序员来说有一定的挑战性。 随着数据不断增多,我们能否保证我们的程序能够快速扩展到更多的节点上,以应对更多的计算需求?具体而言,当计算需求增多时,计算资源能否线性增加而不是耗费大量的资源,程序的代码逻辑能否保持简单而不会变得极其复杂?一个具有可扩展性的系统必须能够优雅地解决这些问题。 @@ -57,8 +63,8 @@ #### (4) 时序错乱 -限于网络条件和其他各种潜在影响因素,流处理引擎处理某个事件的时间并不是事件本来发生的时间。比如,你想统计上午11:00:00到11:00:10的交易情况,然而发生在11:00:05的某项交易因网络延迟没能抵达,这时候要直接放弃这项交易吗?绝大多数情况下我们会让程序等待,比如我们会假设数据最晚不会延迟超过10分钟,因此程序会等待10分钟。等待一次也还能接受,但是如果有多个节点在并行处理呢?每个节点等待一段时间,最后做数据聚合时就要等待更长时间。 +限于网络条件和其他各种潜在影响因素,流处理引擎处理某个事件的时间并不是事件本来发生的时间。比如,你想统计上午 11:00:00 到 11:00:10 的交易情况,然而发生在 11:00:05 的某项交易因网络延迟没能抵达,这时候要直接放弃这项交易吗?绝大多数情况下我们会让程序等待,比如我们会假设数据最晚不会延迟超过 10 分钟,因此程序会等待 10 分钟。等待一次也还能接受,但是如果有多个节点在并行处理呢?每个节点等待一段时间,最后做数据聚合时就要等待更长时间。 批处理框架一般处理一个较长时间段内的数据,数据的时序性对其影响较小。批处理框架用更长的时间来换取更好的准确性。流处理框架对时序错乱更为敏感,框架的复杂程度也因此大大增加。 -Flink是解决上述问题的最佳选择之一。如果用Flink去解决前文提到的股票建模问题,只需要设置时间窗口,并在这个时间窗口下做一些数据处理的操作,还可以根据数据量来设置由多少节点并行处理。 +Flink 是解决上述问题的最佳选择之一。如果用 Flink 去解决前文提到的股票建模问题,只需要设置时间窗口,并在这个时间窗口下做一些数据处理的操作,还可以根据数据量来设置由多少节点并行处理。 diff --git a/doc/ch-big-data-intro/bigdata.md b/doc/ch-big-data-intro/bigdata.md index 50b1edd..9e5c5e8 100644 --- a/doc/ch-big-data-intro/bigdata.md +++ b/doc/ch-big-data-intro/bigdata.md @@ -1,64 +1,70 @@ (bigdata)= # 什么是大数据 -## 1.1.1 大数据的5个“V” +## 大数据的 5 个 “V” -大数据,顾名思义,就是拥有庞大体量的数据。关于什么是大数据、如何定义大数据、如何使用大数据等一系列问题,拥有不同领域背景的读者的理解各不相同。通常,业界将大数据的特点归纳为图1-1所示的5个“V”。 +大数据,顾名思义,就是拥有庞大体量的数据。关于什么是大数据、如何定义大数据、如何使用大数据等一系列问题,拥有不同领域背景的读者的理解各不相同。通常,业界将大数据的特点归纳为 {numref}`5v` 所示的 5 个 “V”。 -![图1-1 大数据的5个"V"](./img/5V.png) +```{figure} ./img/5V.png +--- +width: 60% +name: 5v +--- +大数据的 5 个 "V" +``` -- **Volume**:指数据量大。数据量单位从TB(1 024 GB)、PB(1 024 TB)、EB(1 024 PB)、ZB(1 024 EB)甚至到YB(1 024 ZB)。纽约证券交易所每天产生的交易数据大约在TB级,瑞士日内瓦附近的大型强子对撞机每年产生的数据约为PB级,而目前全球数据总量已经在ZB级,相当于1 000 000 PB。基于更大规模的数据,我们可以对某个研究对象的历史、现状和未来有更加全面的了解。 +- **Volume**:指数据量大。数据量单位从 TB(1 024 GB)、PB(1 024 TB)、EB(1 024 PB)、ZB(1 024 EB)甚至到 YB(1 024 ZB)。纽约证券交易所每天产生的交易数据大约在 TB 级,瑞士日内瓦附近的大型强子对撞机每年产生的数据约为 PB 级,而目前全球数据总量已经在 ZB 级,相当于 1 000 000 PB。基于更大规模的数据,我们可以对某个研究对象的历史、现状和未来有更加全面的了解。 - **Velocity**:指数据产生速度快。数据要求的处理速度更快和时效性更强,因为时间就是金钱。金融市场的交易数据必须以秒级的速度进行处理,搜索和推荐引擎需要以分钟级速度将实时新闻推送给用户。更快的数据处理速度可让我们基于最新的数据做出更加实时的决策。 -- **Variety**:指数据类型繁多。数据可以是数字、文字、图片、视频等不同的形式,数据源可能是社交网络、视频网站、可穿戴设备以及各类传感器。数据可能是Excel表格等高度结构化的数据,也可能是图片和视频等非结构化的数据。 +- **Variety**:指数据类型繁多。数据可以是数字、文字、图片、视频等不同的形式,数据源可能是社交网络、视频网站、可穿戴设备以及各类传感器。数据可能是 Excel 表格等高度结构化的数据,也可能是图片和视频等非结构化的数据。 - **Veracity**:指数据真实性。一方面,数据并非天然具有高价值,一些异常值会被掺杂进来,例如,统计偏差、人的情感因素、天气因素、经济因素甚至谎报数据等导致的异常值。另一方面,数据源类型不同,如何将来自多样的数据源的多元异构数据连接、匹配、清洗和转化,最终形成具有真实性的数据是一项非常有挑战性的工作。 - **Value**:指数据价值。大数据已经推动了世界的方方面面的发展,从商业、科技到医疗、教育、经济、人文等社会的各个领域,我们研究和利用大数据的最终目的是挖掘数据背后的深层价值。 在数据分析领域,全部研究对象被称为总体(Population),总体包含大量的数据,数据甚至可能是无限的。很多情况下,我们无法保证能收集和分析总体的所有数据,因此研究者一般基于全部研究对象的一个子集进行数据分析。样本(Sample)是从总体中抽取的个体,是全部研究对象的子集。通过对样本的调查和分析,研究者可以推测总体的情况。比如调查某个群体的金融诚信情况,群体内所有人是总体,我们可以抽取一部分个体作为样本,以此推测群体的金融诚信水平。 -在大数据技术成熟之前,受限于数据收集、存储和分析能力,样本数量相对较小。大数据技术的成熟让数据存储和计算能力不再是瓶颈,研究者可以在更大规模的数据上,以更快的速度进行数据分析。但数据并非天然有价值,如何对数据“点石成金”非常有挑战性。在金融诚信调查中,如果我们直接询问样本对象,“你是否谎报了家庭资产以获取更大的金融借贷额度?”十之八九,我们得不到真实的答案,但我们可以结合多种渠道的数据来分析该问题,比如结合样本对象的工作经历、征信记录等数据。 +在大数据技术成熟之前,受限于数据收集、存储和分析能力,样本数量相对较小。大数据技术的成熟让数据存储和计算能力不再是瓶颈,研究者可以在更大规模的数据上,以更快的速度进行数据分析。但数据并非天然有价值,如何对数据 “点石成金” 非常有挑战性。在金融诚信调查中,如果我们直接询问样本对象,“你是否谎报了家庭资产以获取更大的金融借贷额度?”十之八九,我们得不到真实的答案,但我们可以结合多种渠道的数据来分析该问题,比如结合样本对象的工作经历、征信记录等数据。 大数据具有更大的数据量、更快的速度、更多的数据类型等特点。在一定的数据真实性基础上,大数据技术最终要为数据背后的价值服务。 -随着大数据技术的发展,数据的复杂性越来越高,有人在这5个“V”的基础上,又提出了一些补充内容,比如增加了动态性(Vitality),强调整个数据体系的动态性;增加了可视性(Visualization),强调数据的显性化展现;增加了合法性(Validity),强调数据采集和应用的合法性,特别是对于个人隐私数据的合理使用等;增加了数据在线(Online),强调数据永远在线,能随时被调用和计算。 +随着大数据技术的发展,数据的复杂性越来越高,有人在这 5 个 “V” 的基础上,又提出了一些补充内容,比如增加了动态性(Vitality),强调整个数据体系的动态性;增加了可视性(Visualization),强调数据的显性化展现;增加了合法性(Validity),强调数据采集和应用的合法性,特别是对于个人隐私数据的合理使用等;增加了数据在线(Online),强调数据永远在线,能随时被调用和计算。 -## 1.1.2 大数据分而治之 +## 大数据分而治之 计算机诞生之后,一般是在单台计算机上处理数据。大数据时代到来后,一些传统的数据处理方法无法满足大数据的处理需求。将一组计算机组织到一起形成一个集群,利用集群的力量来处理大数据的工程实践逐渐成为主流。这种使用集群进行计算的方式被称为分布式计算,当前几乎所有的大数据系统都在使用集群进行分布式计算。 -分布式计算的概念听起来很高深,其背后的思想却十分朴素,即分而治之,又称为分治法(Divide and Conquer)。如图1-2所示,分治法是指将一个原始问题分解为多个子问题,多个子问题分别在多台计算机上求解,借助必要的数据交换和合并策略,将子结果汇总即可求出最终结果的方法。具体而言,不同的分布式系统使用的算法和策略根据所要解决的问题各有不同,但基本上都是将计算拆分,把子问题放到多台计算机上,分而治之地计算求解。分布式计算的每台计算机(物理机或虚拟机)又被称为一个节点。 +分布式计算的概念听起来很高深,其背后的思想却十分朴素,即分而治之,又称为分治法(Divide and Conquer)。如图 1-2 所示,分治法是指将一个原始问题分解为多个子问题,多个子问题分别在多台计算机上求解,借助必要的数据交换和合并策略,将子结果汇总即可求出最终结果的方法。具体而言,不同的分布式系统使用的算法和策略根据所要解决的问题各有不同,但基本上都是将计算拆分,把子问题放到多台计算机上,分而治之地计算求解。分布式计算的每台计算机(物理机或虚拟机)又被称为一个节点。 -![图1-2 分治法](./img/divide-conquer.png) +![图 1-2 分治法](./img/divide-conquer.png) 分布式计算已经有很多比较成熟的方案,其中比较有名的有消息传递接口(Message Passing Interface,MPI)和映射归约模型(MapReduce)。 ### 1. MPI -MPI是一个“老牌”分布式计算框架,从MPI这个名字也可以看出,MPI主要解决节点间数据通信的问题。在前MapReduce时代,MPI是分布式计算的业界标准。MPI现在依然广泛运用于全球各大超级计算中心、大学、研究机构中,许多物理、生物、化学、能源等基础学科的大规模分布式计算都依赖MPI。图1-3所示为使用MPI在4台服务器上并行计算的示意图。 +MPI 是一个 “老牌” 分布式计算框架,从 MPI 这个名字也可以看出,MPI 主要解决节点间数据通信的问题。在前 MapReduce 时代,MPI 是分布式计算的业界标准。MPI 现在依然广泛运用于全球各大超级计算中心、大学、研究机构中,许多物理、生物、化学、能源等基础学科的大规模分布式计算都依赖 MPI。图 1-3 所示为使用 MPI 在 4 台服务器上并行计算的示意图。 -![图1-3 在4台服务器上使用MPI进行并行计算](./img/mpi.png) +![图 1-3 在 4 台服务器上使用 MPI 进行并行计算](./img/mpi.png) -使用MPI编程,需要使用分治法将问题分解成子问题,在不同节点上分而治之地求解。MPI提供了一个在多进程、多节点间进行数据通信的方案,因为绝大多数情况下,在中间求解和最终汇总的过程中,需要对多个节点上的数据进行交换和同步。 +使用 MPI 编程,需要使用分治法将问题分解成子问题,在不同节点上分而治之地求解。MPI 提供了一个在多进程、多节点间进行数据通信的方案,因为绝大多数情况下,在中间求解和最终汇总的过程中,需要对多个节点上的数据进行交换和同步。 -MPI中最重要的两个操作为数据发送和数据接收,数据发送表示将本进程中某些数据发送给其他进程,数据接收表示接收其他进程的数据。在实际的代码开发过程中,程序员需要自行设计分治算法,将复杂问题分解为子问题,手动调用MPI库,将数据发送给指定的进程。 +MPI 中最重要的两个操作为数据发送和数据接收,数据发送表示将本进程中某些数据发送给其他进程,数据接收表示接收其他进程的数据。在实际的代码开发过程中,程序员需要自行设计分治算法,将复杂问题分解为子问题,手动调用 MPI 库,将数据发送给指定的进程。 -MPI能够以很细的粒度控制数据的通信,这是它的优势,从某些方面而言这也是它的劣势,因为细粒度的控制意味着从分治算法设计、数据通信到结果汇总都需要程序员手动控制。有经验的程序员可以对程序进行底层优化,取得成倍的速度提升。但如果程序员对计算机分布式系统没有太多经验,编码、调试和运行MPI程序的时间成本极高,加上数据在不同节点上分布不均衡和通信延迟等问题,一个节点进程失败将会导致整个程序失败。因此,MPI对大部分程序员来说简直就是“噩梦”。 +MPI 能够以很细的粒度控制数据的通信,这是它的优势,从某些方面而言这也是它的劣势,因为细粒度的控制意味着从分治算法设计、数据通信到结果汇总都需要程序员手动控制。有经验的程序员可以对程序进行底层优化,取得成倍的速度提升。但如果程序员对计算机分布式系统没有太多经验,编码、调试和运行 MPI 程序的时间成本极高,加上数据在不同节点上分布不均衡和通信延迟等问题,一个节点进程失败将会导致整个程序失败。因此,MPI 对大部分程序员来说简直就是 “噩梦”。 -并非所有的程序员都能熟练掌握MPI编程,衡量一个程序的时间成本,不仅要考虑程序运行的时间,也要考虑程序员学习、开发和调试的时间。就像C语言运算速度极快,但是Python却更受欢迎一样,MPI虽然能提供极快的分布式计算速度,但不太接地气。 +并非所有的程序员都能熟练掌握 MPI 编程,衡量一个程序的时间成本,不仅要考虑程序运行的时间,也要考虑程序员学习、开发和调试的时间。就像 C 语言运算速度极快,但是 Python 却更受欢迎一样,MPI 虽然能提供极快的分布式计算速度,但不太接地气。 ### 2. MapReduce -为了解决分布式计算学习和使用成本高的问题,研究人员开发出了更简单易用的MapReduce编程模型。MapReduce是Google于2004年推出的一种编程模型,与MPI将所有事情交给程序员控制不同,MapReduce编程模型只需要程序员定义两个操作:Map和Reduce。 +为了解决分布式计算学习和使用成本高的问题,研究人员开发出了更简单易用的 MapReduce 编程模型。MapReduce 是 Google 于 2004 年推出的一种编程模型,与 MPI 将所有事情交给程序员控制不同,MapReduce 编程模型只需要程序员定义两个操作:Map 和 Reduce。 -比起MPI,MapReduce编程模型将更多的中间过程做了封装,程序员只需要将原始问题转化为更高层次的应用程序接口(Application Programming Interface,API),至于原始问题如何分解为更小的子问题、中间数据如何传输和交换、如何将计算扩展到多个节点等一系列细节问题可以交给大数据编程模型来解决。因此,MapReduce相对来说学习门槛更低,使用更方便,编程开发速度更快。 +比起 MPI,MapReduce 编程模型将更多的中间过程做了封装,程序员只需要将原始问题转化为更高层次的应用程序接口(Application Programming Interface,API),至于原始问题如何分解为更小的子问题、中间数据如何传输和交换、如何将计算扩展到多个节点等一系列细节问题可以交给大数据编程模型来解决。因此,MapReduce 相对来说学习门槛更低,使用更方便,编程开发速度更快。 -图1-4所示为使用MapReduce思想制作三明治的过程,读者可以通过这幅图更好的理解MapReduce。 +图 1-4 所示为使用 MapReduce 思想制作三明治的过程,读者可以通过这幅图更好的理解 MapReduce。 -假设我们需要大批量地制作三明治,三明治的每种食材可以分别单独处理,Map阶段将原材料在不同的节点上分别进行处理,生成一些中间食材,Shuffle/Group阶段将不同的中间食材进行组合,Reduce阶段最终将一组中间食材组合成三明治成品。可以看到,这种Map + Shuffle/Group + Reduce的方式就是分治法的一种实现。 +假设我们需要大批量地制作三明治,三明治的每种食材可以分别单独处理,Map 阶段将原材料在不同的节点上分别进行处理,生成一些中间食材,Shuffle/Group 阶段将不同的中间食材进行组合,Reduce 阶段最终将一组中间食材组合成三明治成品。可以看到,这种 Map + Shuffle/Group + Reduce 的方式就是分治法的一种实现。 -![图1-4 使用MapReduce制作三明治的过程](./img/mapreduce-sandwichs.jpeg) +![图 1-4 使用 MapReduce 制作三明治的过程](./img/mapreduce-sandwichs.jpeg) -基于MapReduce编程模型,不同的团队分别实现了自己的大数据框架:Hadoop是较早的一种开源实现,如今已经成为大数据领域的业界标杆,之后又出现了Spark和Flink。这些框架提供了编程接口,辅助程序员存储、处理和分析大数据。 +基于 MapReduce 编程模型,不同的团队分别实现了自己的大数据框架:Hadoop 是较早的一种开源实现,如今已经成为大数据领域的业界标杆,之后又出现了 Spark 和 Flink。这些框架提供了编程接口,辅助程序员存储、处理和分析大数据。 -1.1.1 小节介绍了大数据的5个“V”特点,1.1.2 小节介绍了大数据的分治法。面对海量数据和各不相同的业务逻辑,我们很难使用一种技术或一套方案来解决各类大数据问题。比如,电商平台和视频网站的大数据架构会略有不同。实际上,大数据技术是一整套方案,包括存储、计算和提供在线服务等多个重要部分,而且与数据形态、业务逻辑、提供何种价值等多方面的因素有关。 +1.1.1 小节介绍了大数据的 5 个 “V” 特点,1.1.2 小节介绍了大数据的分治法。面对海量数据和各不相同的业务逻辑,我们很难使用一种技术或一套方案来解决各类大数据问题。比如,电商平台和视频网站的大数据架构会略有不同。实际上,大数据技术是一整套方案,包括存储、计算和提供在线服务等多个重要部分,而且与数据形态、业务逻辑、提供何种价值等多方面的因素有关。 与大数据有关联的组件众多、技术各有不同,限于本书主题和编者能力,无法一一阐述,本书主要从计算层面来介绍大数据的分析和处理方法。 diff --git a/doc/ch-big-data-intro/evolution-of-big-data-processing-platforms.md b/doc/ch-big-data-intro/evolution.md similarity index 99% rename from doc/ch-big-data-intro/evolution-of-big-data-processing-platforms.md rename to doc/ch-big-data-intro/evolution.md index 5886aef..fe11f16 100644 --- a/doc/ch-big-data-intro/evolution-of-big-data-processing-platforms.md +++ b/doc/ch-big-data-intro/evolution.md @@ -1,4 +1,4 @@ -(evolution-of-big-data-processing-platforms)= +(evolution)= # 从Lambda到Kappa:大数据处理平台的演进 前文已经提到,流处理框架经历了3代的更新迭代,大数据处理也随之经历了从Lambda架构到Kappa架构的演进。本节以电商平台的数据分析为例,来解释大数据处理平台如何支持企业在线服务。电商平台会将用户在App或网页的搜索、点击和购买行为以日志的形式记录下来,用户的各类行为形成了一个实时数据流,我们称之为用户行为日志。 diff --git a/doc/ch-big-data-intro/exercise-building-data-stream-using-Kafka.md b/doc/ch-big-data-intro/exercise-building-data-stream-using-Kafka.md deleted file mode 100644 index e7c88ad..0000000 --- a/doc/ch-big-data-intro/exercise-building-data-stream-using-Kafka.md +++ /dev/null @@ -1,109 +0,0 @@ -(exercise-building-data-stream-using-Kafka)= -# 案例实战:使用Kafka构建文本数据流 - -尽管本书主题是Flink,但是对数据流的整个生命周期有一个更全面的认识有助于我们理解大数据和流处理。1.3.3小节简单介绍了Kafka这项技术,本节将介绍如何使用Kafka构建实时文本数据流,读者可以通过本节了解数据流管道的大致结构:数据生产者源源不断地生成数据流,数据流通过消息队列投递,数据消费者异步地对数据流进行处理。 - -## 1.7.1 Kafka和消息队列相关背景知识 - -### 1. 消息队列的功能 - -消息队列一般使用图1-6所示的“生产者-消费者”模型来解决问题:生产者生成数据,将数据发送到一个缓存区域,消费者从缓存区域中消费数据。消息队列可以解决以下问题: - -- **系统解耦**:很多企业内部有众多系统,一个App也包含众多模块,如果将所有的系统和模块都放在一起作为一个庞大的系统来开发,未来则会很难维护和扩展。如果将各个模块独立出来,模块之间通过消息队列来通信,未来可以轻松扩展每个独立模块。另外,假设没有消息队列,M个生产者和N个消费者通信,会产生M×N个数据管道,消息队列将这个复杂度降到了M+N。 -- **异步处理**:同步是指如果模块A向模块B发送消息,必须等待返回结果后才能执行接下来的业务逻辑。异步是消息发送方模块A无须等待返回结果即可继续执行,只需要向消息队列中发送消息,至于谁去处理这些消息、消息等待多长时间才能被处理等一系列问题,都由消费者负责。异步处理更像是发布通知,发送方不用关心谁去接收通知、如何对通知做出响应等问题。 -- **流量削峰**:电商促销、抢票等场景会对系统造成巨大的压力,瞬时请求暴涨,消息队列的缓存就像一个蓄水池,以很低的成本将上游的洪峰缓存起来,下游的数据处理模块按照自身处理能力从缓存中拉取数据,避免数据处理模块崩溃。 -- **数据冗余**:很多情况下,下游的数据处理模块可能发生故障,消息队列将数据缓存起来,直到数据被处理,一定程度上避免了数据丢失风险。 - -Kafka作为一个消息队列,主要提供如下3种核心能力: - -- 为数据的生产者提供发布功能,为数据的消费者提供订阅功能,即传统的消息队列的能力。 -- 将数据流缓存在缓存区域,为数据提供容错性,有一定的数据存储能力。 -- 提供了一些轻量级流处理能力。 - -可见Kafka不仅是一个消息队列,也有数据存储和流处理的功能,确切地说,Kafka是一个流处理系统。 - -### 2. Kafka的一些核心概念 - -Kafka涉及不少概念,包括Topic、Producer、Consumer等,这里从Flink流处理的角度出发,只对与流处理关系密切的核心概念做简单介绍。 - -- **Topic**:Kafka按照Topic来区分不同的数据。以淘宝这样的电商平台为例,某个Topic发布买家用户在电商平台的行为日志,比如搜索、点击、聊天、购买等行为;另外一个Topic发布卖家用户在电商平台上的行为日志,比如上新、发货、退货等行为。 -- **Producer**:多个Producer将某份数据发布到某个Topic下。比如电商平台的多台线上服务器将买家行为日志发送到名为user_behavior的Topic下。 -- **Consumer**:多个Consumer被分为一组,名为Consumer Group,一组Consumer Group订阅一个Topic下的数据。通常我们可以使用Flink编写的程序作为Kafka的Consumer来对一个数据流做处理。 - -## 1.7.2 使用Kafka构建一个文本数据流 - -### 1. 下载和安装 - -如前文所述,绝大多数的大数据框架基于Java,因此在进行开发之前要先搭建Java编程环境,主要是下载和配置Java开发工具包(Java Development Kit,JDK)。网络上针对不同操作系统的相关教程已经很多,这里不赘述。 - -从Kafka官网下载二进制文件形式的软件包,软件包扩展名为 .tgz。Windows用户可以使用7Zip或WinRAR软件解压 .tgz文件,Linux和macOS用户需要使用命令行工具,进入该下载目录。 - -```bash -$ tar -xzf kafka_2.12-2.3.0.tgz -$ cd kafka_2.12-2.3.0 -``` - -**注意**: - -`$`符号表示该行命令在类UNIX操作系统(macOS和Linux)命令行中执行,而不是在Python交互命令界面或其他任何交互界面中。Windows的命令行提示符是大于号`>`。 - -解压之后的文件中,`bin`目录默认为Linux和macOS设计。Windows用户要进入`bin\windows\`来启动相应脚本,且脚本文件扩展名要改为`.bat`。 - -### 2. 启动服务 - -Kafka使用ZooKeeper来管理集群,因此需要先启动ZooKeeper。刚刚下载的Kafka包里已经包含了ZooKeeper的启动脚本,可以使用这个脚本快速启动一个ZooKeeper服务。 - -```bash -$ bin/zookeeper-server-start.sh config/zookeeper.properties -``` - -启动成功后,对应日志将被输出到屏幕上。 - -接下来再开启一个命令行会话,启动Kafka: - -```bash -$ bin/kafka-server-start.sh config/server.properties -``` - -以上两个操作均使用`config`文件夹下的默认配置文件,需要注意配置文件的路径是否写错。生产环境中的配置文件比默认配置文件复杂得多。 - -### 3. 创建Topic - -开启一个命令行会话,创建一个名为`Shakespeare`的Topic: - -```bash -$ bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic Shakespeare -``` - -也可以使用命令查看已有的Topic: - -```bash -$ bin/kafka-topics.sh --list --bootstrap-server localhost:9092 -Shakespeare -``` - -### 4. 发送消息 - -接下来我们模拟 Producer,假设这个 Producer 是莎士比亚(Shakespeare)本人,它不断向“Shakespeare”这个Topic发送自己的最新作品: - -```bash -$ bin/kafka-console-producer.sh --broker-list localhost:9092 --topic Shakespeare ->To be, or not to be, that is the question: -``` - -每一行作为一条消息事件,被发送到了Kafka集群上,虽然这个集群只有本机这一台服务器。 - -### 5. 消费数据 - -另外一些人想了解莎士比亚向Kafka发送过哪些新作,所以需要使用一个Consumer来消费刚刚发送的数据。我们开启一个命令行会话来模拟Consumer: - -```bash -$ bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic Shakespeare --from-beginning -To be, or not to be, that is the question: -``` - -Producer端和Consumer端在不同的命令行会话中,我们可以在Producer端的命令行会话里不断输入一些文本。切换到Consumer端后,可以看到相应的文本被发送了过来。 - -至此,我们模拟了一个实时数据流数据管道:不同人可以创建Topic,发布属于自己的内容;其他人可以订阅一个或多个Topic,根据需求设计后续处理逻辑。 - -使用Flink做流处理时,我们很可能以消息队列作为输入数据源,进行一定处理后,再输出到消息队列、数据库或其他组件上。 diff --git a/doc/ch-big-data-intro/exercise-stream-with-kafka.md b/doc/ch-big-data-intro/exercise-stream-with-kafka.md new file mode 100644 index 0000000..9032738 --- /dev/null +++ b/doc/ch-big-data-intro/exercise-stream-with-kafka.md @@ -0,0 +1,109 @@ +(exercise-stream-with-kafka)= +# 案例实战:使用 Kafka 构建文本数据流 + +尽管本书主题是 Flink,但是对数据流的整个生命周期有一个更全面的认识有助于我们理解大数据和流处理。{numref}`technologies` 简单介绍了 Kafka 这项技术,本节将介绍如何使用 Kafka 构建实时文本数据流,读者可以通过本节了解数据流管道的大致结构:数据生产者源源不断地生成数据流,数据流通过消息队列投递,数据消费者异步地对数据流进行处理。 + +## 1.7.1 Kafka 和消息队列相关背景知识 + +### 1. 消息队列的功能 + +消息队列一般使用图 1-6 所示的 “生产者 - 消费者” 模型来解决问题:生产者生成数据,将数据发送到一个缓存区域,消费者从缓存区域中消费数据。消息队列可以解决以下问题: + +- ** 系统解耦 **:很多企业内部有众多系统,一个 App 也包含众多模块,如果将所有的系统和模块都放在一起作为一个庞大的系统来开发,未来则会很难维护和扩展。如果将各个模块独立出来,模块之间通过消息队列来通信,未来可以轻松扩展每个独立模块。另外,假设没有消息队列,M 个生产者和 N 个消费者通信,会产生 M×N 个数据管道,消息队列将这个复杂度降到了 M+N。 +- ** 异步处理 **:同步是指如果模块 A 向模块 B 发送消息,必须等待返回结果后才能执行接下来的业务逻辑。异步是消息发送方模块 A 无须等待返回结果即可继续执行,只需要向消息队列中发送消息,至于谁去处理这些消息、消息等待多长时间才能被处理等一系列问题,都由消费者负责。异步处理更像是发布通知,发送方不用关心谁去接收通知、如何对通知做出响应等问题。 +- ** 流量削峰 **:电商促销、抢票等场景会对系统造成巨大的压力,瞬时请求暴涨,消息队列的缓存就像一个蓄水池,以很低的成本将上游的洪峰缓存起来,下游的数据处理模块按照自身处理能力从缓存中拉取数据,避免数据处理模块崩溃。 +- ** 数据冗余 **:很多情况下,下游的数据处理模块可能发生故障,消息队列将数据缓存起来,直到数据被处理,一定程度上避免了数据丢失风险。 + +Kafka 作为一个消息队列,主要提供如下 3 种核心能力: + +- 为数据的生产者提供发布功能,为数据的消费者提供订阅功能,即传统的消息队列的能力。 +- 将数据流缓存在缓存区域,为数据提供容错性,有一定的数据存储能力。 +- 提供了一些轻量级流处理能力。 + +可见 Kafka 不仅是一个消息队列,也有数据存储和流处理的功能,确切地说,Kafka 是一个流处理系统。 + +### 2. Kafka 的一些核心概念 + +Kafka 涉及不少概念,包括 Topic、Producer、Consumer 等,这里从 Flink 流处理的角度出发,只对与流处理关系密切的核心概念做简单介绍。 + +- **Topic**:Kafka 按照 Topic 来区分不同的数据。以淘宝这样的电商平台为例,某个 Topic 发布买家用户在电商平台的行为日志,比如搜索、点击、聊天、购买等行为;另外一个 Topic 发布卖家用户在电商平台上的行为日志,比如上新、发货、退货等行为。 +- **Producer**:多个 Producer 将某份数据发布到某个 Topic 下。比如电商平台的多台线上服务器将买家行为日志发送到名为 user_behavior 的 Topic 下。 +- **Consumer**:多个 Consumer 被分为一组,名为 Consumer Group,一组 Consumer Group 订阅一个 Topic 下的数据。通常我们可以使用 Flink 编写的程序作为 Kafka 的 Consumer 来对一个数据流做处理。 + +## 1.7.2 使用 Kafka 构建一个文本数据流 + +### 1. 下载和安装 + +如前文所述,绝大多数的大数据框架基于 Java,因此在进行开发之前要先搭建 Java 编程环境,主要是下载和配置 Java 开发工具包(Java Development Kit,JDK)。网络上针对不同操作系统的相关教程已经很多,这里不赘述。 + +从 Kafka 官网下载二进制文件形式的软件包,软件包扩展名为 .tgz。Windows 用户可以使用 7Zip 或 WinRAR 软件解压 .tgz 文件,Linux 和 macOS 用户需要使用命令行工具,进入该下载目录。 + +```bash +$ tar -xzf kafka_2.12-2.3.0.tgz +$ cd kafka_2.12-2.3.0 +``` + +** 注意 **: + +`$` 符号表示该行命令在类 UNIX 操作系统(macOS 和 Linux)命令行中执行,而不是在 Python 交互命令界面或其他任何交互界面中。Windows 的命令行提示符是大于号 `>`。 + +解压之后的文件中,`bin` 目录默认为 Linux 和 macOS 设计。Windows 用户要进入 `bin\windows\` 来启动相应脚本,且脚本文件扩展名要改为 `.bat`。 + +### 2. 启动服务 + +Kafka 使用 ZooKeeper 来管理集群,因此需要先启动 ZooKeeper。刚刚下载的 Kafka 包里已经包含了 ZooKeeper 的启动脚本,可以使用这个脚本快速启动一个 ZooKeeper 服务。 + +```bash +$ bin/zookeeper-server-start.sh config/zookeeper.properties +``` + +启动成功后,对应日志将被输出到屏幕上。 + +接下来再开启一个命令行会话,启动 Kafka: + +```bash +$ bin/kafka-server-start.sh config/server.properties +``` + +以上两个操作均使用 `config` 文件夹下的默认配置文件,需要注意配置文件的路径是否写错。生产环境中的配置文件比默认配置文件复杂得多。 + +### 3. 创建 Topic + +开启一个命令行会话,创建一个名为 `Shakespeare` 的 Topic: + +```bash +$ bin/kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic Shakespeare +``` + +也可以使用命令查看已有的 Topic: + +```bash +$ bin/kafka-topics.sh --list --bootstrap-server localhost:9092 +Shakespeare +``` + +### 4. 发送消息 + +接下来我们模拟 Producer,假设这个 Producer 是莎士比亚(Shakespeare)本人,它不断向 “Shakespeare” 这个 Topic 发送自己的最新作品: + +```bash +$ bin/kafka-console-producer.sh --broker-list localhost:9092 --topic Shakespeare +>To be, or not to be, that is the question: +``` + +每一行作为一条消息事件,被发送到了 Kafka 集群上,虽然这个集群只有本机这一台服务器。 + +### 5. 消费数据 + +另外一些人想了解莎士比亚向 Kafka 发送过哪些新作,所以需要使用一个 Consumer 来消费刚刚发送的数据。我们开启一个命令行会话来模拟 Consumer: + +```bash +$ bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic Shakespeare --from-beginning +To be, or not to be, that is the question: +``` + +Producer 端和 Consumer 端在不同的命令行会话中,我们可以在 Producer 端的命令行会话里不断输入一些文本。切换到 Consumer 端后,可以看到相应的文本被发送了过来。 + +至此,我们模拟了一个实时数据流数据管道:不同人可以创建 Topic,发布属于自己的内容;其他人可以订阅一个或多个 Topic,根据需求设计后续处理逻辑。 + +使用 Flink 做流处理时,我们很可能以消息队列作为输入数据源,进行一定处理后,再输出到消息队列、数据库或其他组件上。 diff --git a/doc/ch-big-data-intro/img/three-type-window.png b/doc/ch-big-data-intro/img/three-type-window.png new file mode 100644 index 0000000..e606084 Binary files /dev/null and b/doc/ch-big-data-intro/img/three-type-window.png differ diff --git a/doc/ch-big-data-intro/index.md b/doc/ch-big-data-intro/index.md index 1eefb9b..0a9bad5 100644 --- a/doc/ch-big-data-intro/index.md +++ b/doc/ch-big-data-intro/index.md @@ -1,12 +1,12 @@ # 大数据技术概述 -牛津大学教授维克托·迈尔-舍恩伯格(Viktor Mayer-Schönberger)指出,大数据带来的信息风暴正在改变我们的生活、工作和思维。理解大数据并对这些数据进行有效的处理和分析是企业和政府的机遇,更是一种挑战。数据流的处理必须满足高吞吐和低延迟的特性,Apache Flink(以下简称Flink)是一种针对数据流的大数据处理框架。开源领域比较知名的大数据处理框架Apache Hadoop(以下简称Hadoop)和Apache Spark(以下简称Spark),主要专注于批处理。 +牛津大学教授维克托·迈尔-舍恩伯格(Viktor Mayer-Schönberger)指出,大数据带来的信息风暴正在改变我们的生活、工作和思维。理解大数据并对这些数据进行有效的处理和分析是企业和政府的机遇,更是一种挑战。数据流的处理必须满足高吞吐和低延迟的特性,Apache Flink(以下简称 Flink)是一种针对数据流的大数据处理框架。开源领域比较知名的大数据处理框架 Apache Hadoop(以下简称 Hadoop)和 Apache Spark(以下简称 Spark),主要专注于批处理。 读完本章之后,读者可以了解以下内容。 - 大数据的特点、大数据分而治之的处理思想。 - 批处理和流处理的区别。 - 流处理的基础概念。 - 流处理框架的技术更迭和架构演进。 -- Flink开发的常用编程语言。 +- Flink 开发的常用编程语言。 ```{tableofcontents} diff --git a/doc/ch-big-data-intro/representative-big-data-technologies.md b/doc/ch-big-data-intro/representative-big-data-technologies.md deleted file mode 100644 index 2dfcbd3..0000000 --- a/doc/ch-big-data-intro/representative-big-data-technologies.md +++ /dev/null @@ -1,77 +0,0 @@ -(representative-big-data-technologies)= -# 代表性大数据技术 - -MapReduce编程模型的提出为大数据分析和处理开创了一条先河,其后涌现出一批知名的开源大数据技术,本节主要对一些流行的技术和框架进行简单介绍。 - -## 1.3.1 Hadoop - -2004年,Hadoop的创始人道格·卡廷(Doug Cutting)和麦克·卡法雷拉(Mike Cafarella)受MapReduce编程模型和Google File System等技术的启发,对其中提及的思想进行了编程实现,Hadoop的名字来源于道格·卡廷儿子的玩具大象。由于道格·卡廷后来加入了雅虎,并在雅虎工作期间做了大量Hadoop的研发工作,因此Hadoop也经常被认为是雅虎开源的一款大数据框架。时至今日,Hadoop不仅是整个大数据领域的先行者和领航者,更形成了一套围绕Hadoop的生态圈,Hadoop和它的生态圈是绝大多数企业首选的大数据解决方案。图1-7展示了Hadoop生态圈一些流行组件。 - -Hadoop生态圈的核心组件主要有如下3个。 - -- **Hadoop MapReduce**:Hadoop版本的MapReduce编程模型,可以处理海量数据,主要面向批处理。 -- **HDFS**:HDFS(Hadoop Distributed File System)是Hadoop提供的分布式文件系统,有很好的扩展性和容错性,为海量数据提供存储支持。 -- **YARN**:YARN(Yet Another Resource Negotiator)是Hadoop生态圈中的资源调度器,可以管理一个Hadoop集群,并为各种类型的大数据任务分配计算资源。 - -这三大组件中,数据存储在HDFS上,由MapReduce负责计算,YARN负责集群的资源管理。除了三大核心组件,Hadoop生态圈还有很多其他著名的组件,部分如下。 - -- **Hive**:借助Hive,用户可以编写结构化查询语言(Structured Query Language,SQL)语句来查询HDFS上的结构化数据,SQL语句会被转化成MapReduce运行。 -- **HBase**:HDFS可以存储海量数据,但访问和查询速度比较慢,HBase可以提供给用户毫秒级的实时查询服务,它是一个基于HDFS的分布式数据库。HBase最初受Google Bigtable技术的启发。 -- **Kafka**:Kafka是一款流处理框架,主要用作消息队列。 -- **ZooKeeper**:Hadoop生态圈中很多组件使用动物来命名,形成了一个大型“动物园”,ZooKeeper是这个动物园的管理者,主要负责分布式环境的协调。 - -![图1-7 Hadoop生态圈](./img/hadoop.png) - -## 1.3.2 Spark - -2009年,Spark诞生于加州大学伯克利分校,2013年被捐献给Apache基金会。实际上,Spark的创始团队本来是为了开发集群管理框架Apache Mesos(以下简称Mesos)的,其功能类似YARN,Mesos开发完成后,需要一个基于Mesos的产品运行在上面以验证Mesos的各种功能,于是他们接着开发了Spark。Spark有火花、鼓舞之意,创始团队希望用Spark来证明在Mesos上从零开始创造一个项目非常简单。 - -Spark是一款大数据处理框架,其开发初衷是改良Hadoop MapReduce的编程模型和提高运行速度,尤其是提升大数据在机器学习方向上的性能。与Hadoop相比,Spark的改进主要有如下两点。 - -- **易用性**:MapReduce模型比MPI更友好,但仍然不够方便。因为并不是所有计算任务都可以被简单拆分成Map和Reduce,有可能为了解决一个问题,要设计多个MapReduce任务,任务之间相互依赖,整个程序非常复杂,导致代码的可读性和可维护性差。Spark提供更加方便易用的接口,提供Java、Scala、Python和R语言等的API,支持SQL、机器学习和图计算,覆盖了绝大多数计算场景。 -- **速度快**:Hadoop的Map和Reduce的中间结果都需要存储到磁盘上,而Spark尽量将大部分计算放在内存中。加上Spark有向无环图的优化,在官方的基准测试中,Spark比Hadoop快一百倍以上。 - -Spark的核心在于计算,主要目的在于优化Hadoop MapReduce计算部分,在计算层面提供更细致的服务。 - -Spark并不能完全取代Hadoop,实际上,从图1-7可以看出,Spark融入了Hadoop生态圈,成为其中的重要一员。一个Spark任务很可能依赖HDFS上的数据,向YARN申请计算资源,将结果输出到HBase上。当然,Spark也可以不用依赖这些组件,独立地完成计算。 - -![图1-8 Spark生态圈](./img/spark.png) - -Spark主要面向批处理需求,因其优异的性能和易用的接口,Spark已经是批处理界绝对的“王者”。Spark的子模块Spark Streaming提供了流处理的功能,它的流处理主要基于mini-batch的思想。如图1-9所示,Spark Streaming将输入数据流切分成多个批次,每个批次使用批处理的方式进行计算。因此,Spark是一款集批处理和流处理于一体的处理框架。 - -![图1-9 Spark Streaming mini-batch处理](./img/spark-streaming-mini-batch.png) - -## 1.3.3 Apache Kafka - -2010年,LinkedIn开始了其内部流处理框架的开发,2011年将该框架捐献给了Apache基金会,取名Apache Kafka(以下简称Kafka)。Kafka的创始人杰·克雷普斯(Jay Kreps)觉得这个框架主要用于优化读写,应该用一个作家的名字来命名,加上他很喜欢作家卡夫卡的文学作品,觉得这个名字对一个开源项目来说很酷,因此取名Kafka。 - -Kafka也是一种面向大数据领域的消息队列框架。在大数据生态圈中,Hadoop的HDFS或Amazon S3提供数据存储服务,Hadoop MapReduce、Spark和Flink负责计算,Kafka常常用来连接不同的应用系统。 - -如图1-10所示,企业中不同的应用系统作为数据生产者会产生大量数据流,这些数据流还需要进入不同的数据消费者,Kafka起到数据集成和系统解耦的作用。系统解耦是让某个应用系统专注于一个目标,以降低整个系统的维护难度。在实践上,一个企业经常拆分出很多不同的应用系统,系统之间需要建立数据流管道(Stream Pipeline)。假如没有Kafka的消息队列,M个生产者和N个消费者之间要建立M×N个点对点的数据流管道,Kafka就像一个中介,让数据管道的个数变为M+N,大大减小了数据流管道的复杂程度。 - -![图1-10 Kafka可以连接多个应用系统](./img/kafka.png) - -从批处理和流处理的角度来讲,数据流经Kafka后会持续不断地写入HDFS,积累一段时间后可提供给后续的批处理任务,同时数据流也可以直接流入Flink,被用于流处理。 - -随着流处理的兴起,Kafka不甘心只做一个数据流管道,开始向轻量级流处理方向努力,但相比Spark和Flink这样的计算框架,Kafka的主要功能侧重在消息队列上。 - -## 1.3.4 Flink - -Flink是由德国3所大学发起的的学术项目,后来不断发展壮大,并于2014年年末成为Apache顶级项目之一。在德语中,“flink”表示快速、敏捷,以此来表征这款计算框架的特点。 - -Flink主要面向流处理,如果说Spark是批处理界的“王者”,那么Flink就是流处理领域冉冉升起的“新星”。流处理并不是一项全新的技术,在Flink之前,不乏流处理引擎,比较著名的有Storm、Spark Streaming,图1-11展示了流处理框架经历的三代演进。 - -2011年成熟的Apache Strom(以下简称Storm)是第一代被广泛采用的流处理引擎。它是以数据流中的事件为最小单位来进行计算的。以事件为单位的框架的优势是延迟非常低,可以提供毫秒级的延迟。流处理结果依赖事件到达的时序准确性,Storm并不能保障处理结果的一致性和准确性。Storm只支持至少一次(At-Least-Once)和至多一次(At-Most-Once),即数据流里的事件投递只能保证至少一次或至多一次,不能保证只有一次(Exactly-Once)。在多项基准测试中,Storm的数据吞吐量和延迟都远逊于Flink。对于很多对数据准确性要求较高的应用,Storm有一定劣势。此外,Storm不支持SQL,不支持中间状态(State)。 - -图1-11 流处理框架演进 - -2013年成熟的Spark Streaming是第二代被广泛采用的流处理框架。1.3.2小节中提到,Spark是“一统江湖”的大数据处理框架,Spark Streaming采用微批次(mini-batch)的思想,将数据流切分成一个个小批次,一个小批次里包含多个事件,以接近实时处理的效果。这种做法保证了“Exactly-Once”的事件投递效果,因为假如某次计算出现故障,重新进行该次计算即可。Spark Streaming的API相比第一代流处理框架更加方便易用,与Spark批处理集成度较高,因此Spark可以给用户提供一个流处理与批处理一体的体验。但因为Spark Streaming以批次为单位,每次计算一小批数据,比起以事件为单位的框架来说,延迟从毫秒级变为秒级。 - -与前两代引擎不同,在2015年前后逐渐成熟的Flink是一个支持在有界和无界数据流上做有状态计算的大数据处理框架。它以事件为单位,支持SQL、状态、水位线(Watermark)等特性,支持“Exactly-Once”。比起Storm,它的吞吐量更高,延迟更低,准确性能得到保障;比起Spark Streaming,它以事件为单位,达到真正意义上的实时计算,且所需计算资源相对更少。具体而言,Flink的优点如下。 - -- 支持事件时间(Event Time)和处理时间(Processing Time)多种时间语义。即使事件乱序到达,Event Time也能提供准确和一致的计算结果。Procerssing Time适用于对延迟敏感的应用。 -- Exactly-Once投递保障。 -- 毫秒级延迟。 -- 可以扩展到上千台节点、在阿里巴巴等大公司的生产环境中进行过验证。 -- 易用且多样的API,包括核心的DataStream API和DataSet API以及Table API和SQL。 -- 可以连接大数据生态圈各类组件,包括Kafka、Elasticsearch、JDBC、HDFS和Amazon S3。可以运行在Kubernetes、YARN、Mesos和独立(Standalone)集群上。 \ No newline at end of file diff --git a/doc/ch-big-data-intro/stream-processing-basics.md b/doc/ch-big-data-intro/stream-processing-basics.md index f3a6090..c8e4c63 100644 --- a/doc/ch-big-data-intro/stream-processing-basics.md +++ b/doc/ch-big-data-intro/stream-processing-basics.md @@ -1,21 +1,21 @@ (stream-processing-basics)= # 流处理基础概念 -前文已经多次提到,在某些场景下,流处理打破了批处理的一些局限。Flink作为一款以流处理见长的大数据引擎,相比其他流处理引擎具有众多优势。本节将对流处理的一些基本概念进行细化,这些概念是入门流处理的必备基础,至此你将正式进入数据流的世界。 +前文已经多次提到,在某些场景下,流处理打破了批处理的一些局限。Flink 作为一款以流处理见长的大数据引擎,相比其他流处理引擎具有众多优势。本节将对流处理的一些基本概念进行细化,这些概念是入门流处理的必备基础,至此你将正式进入数据流的世界。 ## 1.5.1 延迟和吞吐 -在批处理场景中,我们主要通过一次计算的总耗时来评价性能。在流处理场景,数据源源不断地流入系统,大数据框架对每个数据的处理越快越好,大数据框架能处理的数据量越大越好。例如1.2.3小节中提到的股票交易案例,如果系统只能处理一两只股票或处理时间长达一天,那说明这个系统非常不靠谱。衡量流处理的“快”和“量”两方面的性能,一般用延迟(Latency)和吞吐(Throughput)这两个指标。 +在批处理场景中,我们主要通过一次计算的总耗时来评价性能。在流处理场景,数据源源不断地流入系统,大数据框架对每个数据的处理越快越好,大数据框架能处理的数据量越大越好。例如 1.2.3 小节中提到的股票交易案例,如果系统只能处理一两只股票或处理时间长达一天,那说明这个系统非常不靠谱。衡量流处理的 “快” 和“量”两方面的性能,一般用延迟(Latency)和吞吐(Throughput)这两个指标。 ### 1. 延迟 -延迟表示一个事件被系统处理的总时间,一般以毫秒为单位。根据业务不同,我们一般关心平均延迟(Average Latency)和分位延迟(Percentile Latency)。假设一个食堂的自助取餐流水线是一个流处理系统,每个就餐者前来就餐是它需要处理的事件,从就餐者到达食堂到他拿到所需菜品并付费离开的总耗时,就是这个就餐者的延迟。如果正赶上午餐高峰期,就餐者极有可能排队,这个排队时间也要算在延迟中。例如,99 分位延迟表示对所有就餐者的延迟进行统计和排名,取排名第99%位的就餐者延迟。一般商业系统更关注分位延迟,因为分位延迟比平均延迟更能反映这个系统的一些潜在问题。还是以食堂的自助餐流水线为例,该流水线的平均延迟可能不高,但是在就餐高峰期,延迟一般会比较高。如果延迟过高,部分就餐者会因为等待时间过长而放弃排队,用户体验较差。通过检查各模块分位延迟,能够快速定位到哪个模块正在“拖累”整个系统的性能。 +延迟表示一个事件被系统处理的总时间,一般以毫秒为单位。根据业务不同,我们一般关心平均延迟(Average Latency)和分位延迟(Percentile Latency)。假设一个食堂的自助取餐流水线是一个流处理系统,每个就餐者前来就餐是它需要处理的事件,从就餐者到达食堂到他拿到所需菜品并付费离开的总耗时,就是这个就餐者的延迟。如果正赶上午餐高峰期,就餐者极有可能排队,这个排队时间也要算在延迟中。例如,99 分位延迟表示对所有就餐者的延迟进行统计和排名,取排名第 99% 位的就餐者延迟。一般商业系统更关注分位延迟,因为分位延迟比平均延迟更能反映这个系统的一些潜在问题。还是以食堂的自助餐流水线为例,该流水线的平均延迟可能不高,但是在就餐高峰期,延迟一般会比较高。如果延迟过高,部分就餐者会因为等待时间过长而放弃排队,用户体验较差。通过检查各模块分位延迟,能够快速定位到哪个模块正在 “拖累” 整个系统的性能。 -延迟对于很多流处理系统非常重要,比如欺诈检测系统、告警监控系统等。Flink可以将延迟降到毫秒级别。如果用mini-batch的思想处理同样的数据流,很可能有分钟级到小时级的延迟,因为批处理引擎必须等待一批数据达到才开始进行计算。 +延迟对于很多流处理系统非常重要,比如欺诈检测系统、告警监控系统等。Flink 可以将延迟降到毫秒级别。如果用 mini-batch 的思想处理同样的数据流,很可能有分钟级到小时级的延迟,因为批处理引擎必须等待一批数据达到才开始进行计算。 ### 2. 吞吐 -吞吐表示一个系统最多能处理多少事件,一般以单位时间处理的事件数量为标准。需要注意的是,吞吐除了与引擎自身设计有关,也与数据源发送过来的事件数据量有关,有可能流处理引擎的最大吞吐量远小于数据源的数据量。比如,自助取餐流水线可能在午餐时间的需求最高,很可能出现大量排队的情况,但另外的时间几乎不需要排队等待。假设一天能为1 000个人提供就餐服务,共计10小时,那它的平均吞吐量为100人/小时;仅午间2小时的高峰期就提供了600人,它的峰值吞吐量是300人/小时。比起平均吞吐量,峰值吞吐量更影响用户体验,如果峰值吞吐量低,会导致就餐者等待时间过长而放弃排队。排队的过程被称作缓存(Buffering)。如果排队期间仍然有大量数据进入缓存,很可能超出系统的极限,就会出现反压(Backpressure)问题,这时候就需要一些优雅的策略来处理类似问题,否则会造成系统崩溃,用户体验较差。 +吞吐表示一个系统最多能处理多少事件,一般以单位时间处理的事件数量为标准。需要注意的是,吞吐除了与引擎自身设计有关,也与数据源发送过来的事件数据量有关,有可能流处理引擎的最大吞吐量远小于数据源的数据量。比如,自助取餐流水线可能在午餐时间的需求最高,很可能出现大量排队的情况,但另外的时间几乎不需要排队等待。假设一天能为 1 000 个人提供就餐服务,共计 10 小时,那它的平均吞吐量为 100 人 / 小时;仅午间 2 小时的高峰期就提供了 600 人,它的峰值吞吐量是 300 人 / 小时。比起平均吞吐量,峰值吞吐量更影响用户体验,如果峰值吞吐量低,会导致就餐者等待时间过长而放弃排队。排队的过程被称作缓存(Buffering)。如果排队期间仍然有大量数据进入缓存,很可能超出系统的极限,就会出现反压(Backpressure)问题,这时候就需要一些优雅的策略来处理类似问题,否则会造成系统崩溃,用户体验较差。 ### 3. 延迟与吞吐 @@ -27,61 +27,61 @@ ### 1. 不同窗口模式 -比起批处理,流处理对窗口(Window)和时间概念更为敏感。在批处理场景下,数据已经按照某个时间维度被分批次地存储了。一些公司经常将用户行为日志按天存储,一些开放数据集都会说明数据采集的时间始末。因此,对于批处理任务,处理一个数据集,其实就是对该数据集对应的时间窗口内的数据进行处理。在流处理场景下,数据以源源不断的流的形式存在,数据一直在产生,没有始末。我们要对数据进行处理时,往往需要明确一个时间窗口,比如,数据在“每秒”“每小时”“每天”的维度下的一些特性。窗口将数据流切分成多个数据块,很多数据分析都是在窗口上进行操作,比如连接、聚合以及其他时间相关的操作。 +比起批处理,流处理对窗口(Window)和时间概念更为敏感。在批处理场景下,数据已经按照某个时间维度被分批次地存储了。一些公司经常将用户行为日志按天存储,一些开放数据集都会说明数据采集的时间始末。因此,对于批处理任务,处理一个数据集,其实就是对该数据集对应的时间窗口内的数据进行处理。在流处理场景下,数据以源源不断的流的形式存在,数据一直在产生,没有始末。我们要对数据进行处理时,往往需要明确一个时间窗口,比如,数据在 “每秒”“每小时”“每天” 的维度下的一些特性。窗口将数据流切分成多个数据块,很多数据分析都是在窗口上进行操作,比如连接、聚合以及其他时间相关的操作。 -图1-14展示了3种常见的窗口形式:滚动窗口、滑动窗口、会话窗口。 +图 1-14 展示了 3 种常见的窗口形式:滚动窗口、滑动窗口、会话窗口。 -![图1-14 3种常见的窗口形式](./img/) +![图 1-14 3 种常见的窗口形式](./img/three-type-window.png) -- **滚动窗口(Tumbling Window)**:模式一般定义一个固定的窗口长度,长度是一个时间间隔,比如小时级的窗口或分钟级的窗口。窗口像车轮一样,滚动向前,任意两个窗口之间不会包含同样的数据。 -- **滑动窗口(Sliding Window)**:模式也设有一个固定的窗口长度。假如我们想每分钟开启一个窗口,统计10分钟内的股票价格波动,就使用滑动窗口模式。当窗口的长度大于滑动的间隔,可能会导致两个窗口之间包含同样的事件。其实,滚动窗口模式是滑动窗口模式的一个特例,滚动窗口模式中滑动的间隔正好等于窗口的大小。 -- **会话窗口(Session Window)**:模式的窗口长度不固定,而是通过一个间隔来确定窗口,这个间隔被称为会话间隔(Session Gap)。当两个事件之间的间隔大于会话间隔,则两个事件被划分到不同的窗口中;当事件之间的间隔小于会话间隔,则两个事件被划分到同一窗口。 +- ** 滚动窗口(Tumbling Window)**:模式一般定义一个固定的窗口长度,长度是一个时间间隔,比如小时级的窗口或分钟级的窗口。窗口像车轮一样,滚动向前,任意两个窗口之间不会包含同样的数据。 +- ** 滑动窗口(Sliding Window)**:模式也设有一个固定的窗口长度。假如我们想每分钟开启一个窗口,统计 10 分钟内的股票价格波动,就使用滑动窗口模式。当窗口的长度大于滑动的间隔,可能会导致两个窗口之间包含同样的事件。其实,滚动窗口模式是滑动窗口模式的一个特例,滚动窗口模式中滑动的间隔正好等于窗口的大小。 +- ** 会话窗口(Session Window)**:模式的窗口长度不固定,而是通过一个间隔来确定窗口,这个间隔被称为会话间隔(Session Gap)。当两个事件之间的间隔大于会话间隔,则两个事件被划分到不同的窗口中;当事件之间的间隔小于会话间隔,则两个事件被划分到同一窗口。 ### 2. 时间语义 -#### (1) Event Time和Processing Time +#### (1) Event Time 和 Processing Time -“时间”是平时生活中最常用的概念之一,在流处理中需要额外注意它,因为时间的语义不仅与窗口有关,也与事件乱序、触发计算等各类流处理问题有关。常见的时间语义如下。 +“时间” 是平时生活中最常用的概念之一,在流处理中需要额外注意它,因为时间的语义不仅与窗口有关,也与事件乱序、触发计算等各类流处理问题有关。常见的时间语义如下。 - **Event Time**:事件实际发生的时间。 - **Processing Time**:事件被流处理引擎处理的时间。 -对于一个事件,自其发生起,Event Time就已经确定不会改变。因各类延迟、流处理引擎各个模块先后处理顺序等因素,不同节点、系统内不同模块、同一数据不同次处理都会产生不同的Processing Time。 +对于一个事件,自其发生起,Event Time 就已经确定不会改变。因各类延迟、流处理引擎各个模块先后处理顺序等因素,不同节点、系统内不同模块、同一数据不同次处理都会产生不同的 Processing Time。 -#### (2) “一分钟”真的是一分钟吗? +#### (2) “一分钟” 真的是一分钟吗? -在很多应用场景中,时间有着不同的语义,“一分钟”真的是一分钟吗?很多手机游戏中多玩家在线实时竞技,假设我们在玩某款手机游戏,该游戏将数据实时发送给游戏服务器,服务器计算一分钟内玩家的一些操作,这些计算影响用户该局游戏的最终得分。当游戏正酣,我们进入了电梯,手机信号丢失,一分钟后才恢复信号;幸好手机在电梯期间缓存了掉线时的数据,并在信号恢复后将缓存数据传回了服务器,图1-15展示了这个场景的流处理过程。在丢失信号的这段时间,你的数据没有被计算进去,显然这样的计算不公平。当信号恢复时,数据重传到服务器,再根据Event Time重新计算一次,那就非常公平了。我们可以根据Event Time复现一个事件序列的实际顺序。因此,使用Event Time是最准确的。 +在很多应用场景中,时间有着不同的语义,“一分钟” 真的是一分钟吗?很多手机游戏中多玩家在线实时竞技,假设我们在玩某款手机游戏,该游戏将数据实时发送给游戏服务器,服务器计算一分钟内玩家的一些操作,这些计算影响用户该局游戏的最终得分。当游戏正酣,我们进入了电梯,手机信号丢失,一分钟后才恢复信号;幸好手机在电梯期间缓存了掉线时的数据,并在信号恢复后将缓存数据传回了服务器,图 1-15 展示了这个场景的流处理过程。在丢失信号的这段时间,你的数据没有被计算进去,显然这样的计算不公平。当信号恢复时,数据重传到服务器,再根据 Event Time 重新计算一次,那就非常公平了。我们可以根据 Event Time 复现一个事件序列的实际顺序。因此,使用 Event Time 是最准确的。 -![图1-15 数据传输过程恰好遇到信号丢失](./img/signal.png) +![图 1-15 数据传输过程恰好遇到信号丢失](./img/signal.png) ### 3. Watermark -虽然使用Event Time更准确,但问题在于,因为各种不可控因素,事件上报会有延迟,那么最多要等待多长时间呢?从服务器的角度来看,在事件到达之前,我们也无法确定是否有事件发生了延迟,如何设置等待时间是一个很难的问题。比如刚才的例子,我们要统计一分钟内的实时数据,考虑到事件的延迟,如何设置合理的等待时间,以等待一分钟内所有事件都到达服务器?也正因为这个问题,流处理与批处理在准确性上有差距,因为批处理一般以更长的一段时间为一个批次,一个批次内延迟上报的数据比一个流处理时间窗口内延迟上报的数据相对更少。比如电商平台上,对于计算一件商品每分钟点击次数,使用一天的总数除以分钟数,比使用一分钟时间窗口实时的点击次数更准确。可以看到,数据的实时性和准确性二者不可得兼,必须取一个平衡。 +虽然使用 Event Time 更准确,但问题在于,因为各种不可控因素,事件上报会有延迟,那么最多要等待多长时间呢?从服务器的角度来看,在事件到达之前,我们也无法确定是否有事件发生了延迟,如何设置等待时间是一个很难的问题。比如刚才的例子,我们要统计一分钟内的实时数据,考虑到事件的延迟,如何设置合理的等待时间,以等待一分钟内所有事件都到达服务器?也正因为这个问题,流处理与批处理在准确性上有差距,因为批处理一般以更长的一段时间为一个批次,一个批次内延迟上报的数据比一个流处理时间窗口内延迟上报的数据相对更少。比如电商平台上,对于计算一件商品每分钟点击次数,使用一天的总数除以分钟数,比使用一分钟时间窗口实时的点击次数更准确。可以看到,数据的实时性和准确性二者不可得兼,必须取一个平衡。 -Watermark是一种折中解决方案,它假设某个时间点上,不会有比这个时间点更晚的上报数据。当流处理引擎接收到一个Watermark后,它会假定之后不会再接收到这个时间窗口的内容,然后会触发对当前时间窗口的计算。比如,一种Watermark 策略等待延迟上报的时间非常短,这样能保证低延迟,但是会导致错误率上升。在实际应用中,Watermark设计为多长非常有挑战性。还是以手机游戏为例,系统不知道玩家这次掉线的原因是什么,可能是在穿越隧道,可能是有事退出了该游戏,还有可能是坐飞机进入飞行模式。 +Watermark 是一种折中解决方案,它假设某个时间点上,不会有比这个时间点更晚的上报数据。当流处理引擎接收到一个 Watermark 后,它会假定之后不会再接收到这个时间窗口的内容,然后会触发对当前时间窗口的计算。比如,一种 Watermark 策略等待延迟上报的时间非常短,这样能保证低延迟,但是会导致错误率上升。在实际应用中,Watermark 设计为多长非常有挑战性。还是以手机游戏为例,系统不知道玩家这次掉线的原因是什么,可能是在穿越隧道,可能是有事退出了该游戏,还有可能是坐飞机进入飞行模式。 -那既然Event Time似乎可以解决一切问题,为什么还要使用Processing Time?前文也提到了,为了处理延迟上报或事件乱序,需要使用一些机制来等待,这样会导致延迟提高。某些场景可能对准确性要求不高,但是对实时性要求更高,在这些场景下使用Processing Time就更合适一些。 +那既然 Event Time 似乎可以解决一切问题,为什么还要使用 Processing Time?前文也提到了,为了处理延迟上报或事件乱序,需要使用一些机制来等待,这样会导致延迟提高。某些场景可能对准确性要求不高,但是对实时性要求更高,在这些场景下使用 Processing Time 就更合适一些。 ## 1.5.3 状态与检查点 -状态是流处理区别于批处理的特有概念。如果我们对一个文本数据流进行处理,把英文大写字母都改成英文小写字母,这种处理是无状态的,即系统不需要记录额外的信息。如果我们想统计这个数据流一分钟内的单词出现次数,一方面要处理每一瞬间新流入的数据,另一方面要保存之前一分钟内已经进入系统的数据,额外保存的数据就是状态。图1-16展示了无状态和有状态两种不同类型的计算。 +状态是流处理区别于批处理的特有概念。如果我们对一个文本数据流进行处理,把英文大写字母都改成英文小写字母,这种处理是无状态的,即系统不需要记录额外的信息。如果我们想统计这个数据流一分钟内的单词出现次数,一方面要处理每一瞬间新流入的数据,另一方面要保存之前一分钟内已经进入系统的数据,额外保存的数据就是状态。图 1-16 展示了无状态和有状态两种不同类型的计算。 -![图1-16 无状态计算和有状态计算](./img/state-stateless.png) +![图 1-16 无状态计算和有状态计算](./img/state-stateless.png) -状态在流处理中经常被用到。再举一个温度报警的例子,当系统在监听到“高温”事件后10分钟内又监听到“冒烟”的事件,系统必须及时报警。在这个场景下,流处理引擎把“高温”的事件作为状态记录下来,并判断这个状态接下来十分钟内是否有“冒烟”事件。 +状态在流处理中经常被用到。再举一个温度报警的例子,当系统在监听到 “高温” 事件后 10 分钟内又监听到 “冒烟” 的事件,系统必须及时报警。在这个场景下,流处理引擎把 “高温” 的事件作为状态记录下来,并判断这个状态接下来十分钟内是否有 “冒烟” 事件。 流处理引擎在数据流上做有状态计算主要有以下挑战。 -- 设计能够管理状态的并行算法极具挑战。前文已经多次提到,大数据需要在多节点上分布式计算,一般将数据按照某个Key进行切分,将相同的Key切分到相同的节点上,系统按照Key维护对应的状态。 +- 设计能够管理状态的并行算法极具挑战。前文已经多次提到,大数据需要在多节点上分布式计算,一般将数据按照某个 Key 进行切分,将相同的 Key 切分到相同的节点上,系统按照 Key 维护对应的状态。 - 如果状态数据不断增长,最后就会造成数据爆炸。因此可使用一些机制来限制状态的数据总量,或者将状态数据从内存输出到磁盘或文件系统上,持久化保存起来。 - 系统可能因各种错误而出现故障,重启后,必须能够保证之前保存的状态数据也能恢复,否则重启后很多计算结果有可能是错误的。 -检查点(Checkpoint)机制其实并不是一个新鲜事物,它广泛存在于各类计算任务上,主要作用是将中间数据保存下来。当计算任务出现问题,重启后可以根据Checkpoint中保存的数据重新恢复任务。在流处理中,Checkpoint主要保存状态数据。 +检查点(Checkpoint)机制其实并不是一个新鲜事物,它广泛存在于各类计算任务上,主要作用是将中间数据保存下来。当计算任务出现问题,重启后可以根据 Checkpoint 中保存的数据重新恢复任务。在流处理中,Checkpoint 主要保存状态数据。 ## 1.5.4 数据一致性保障 -流处理任务可能因为各种原因出现故障,比如数据量暴涨导致内存溢出、输入数据发生变化而无法解析、网络故障、集群维护等。事件进入流处理引擎,如果遇到故障并重启,该事件是否被成功处理了呢?一般有如下3种结果。 +流处理任务可能因为各种原因出现故障,比如数据量暴涨导致内存溢出、输入数据发生变化而无法解析、网络故障、集群维护等。事件进入流处理引擎,如果遇到故障并重启,该事件是否被成功处理了呢?一般有如下 3 种结果。 - **At-Most-Once**:每个事件最多被处理一次,也就是说,有可能某些事件直接被丢弃,不进行任何处理。这种投递保障最不安全,因为一个流处理系统完全可以把接收到的所有事件都丢弃。 - **At-Least-Once**:无论遇到何种状况,流处理引擎能够保证接收到的事件至少被处理一次,有些事件可能被处理多次。例如,我们统计文本数据流中的单词出现次数,事件被处理多次会导致统计结果并不准确。 -- **Exactly-Once**:无论是否有故障重启,每个事件只被处理一次。Exactly-Once意味着事件不能有任何丢失,也不能被多次处理。比起前两种保障,Exactly-Once的实现难度非常高。如遇故障重启,Exactly-Once就必须确认哪些事件已经被处理、哪些还未被处理。Flink在某些情况下能提供Exactly-Once的保障。 +- **Exactly-Once**:无论是否有故障重启,每个事件只被处理一次。Exactly-Once 意味着事件不能有任何丢失,也不能被多次处理。比起前两种保障,Exactly-Once 的实现难度非常高。如遇故障重启,Exactly-Once 就必须确认哪些事件已经被处理、哪些还未被处理。Flink 在某些情况下能提供 Exactly-Once 的保障。 diff --git a/doc/ch-big-data-intro/technologies.md b/doc/ch-big-data-intro/technologies.md new file mode 100644 index 0000000..d4ea283 --- /dev/null +++ b/doc/ch-big-data-intro/technologies.md @@ -0,0 +1,77 @@ +(technologies)= +# 代表性大数据技术 + +MapReduce 编程模型的提出为大数据分析和处理开创了一条先河,其后涌现出一批知名的开源大数据技术,本节主要对一些流行的技术和框架进行简单介绍。 + +## 1.3.1 Hadoop + +2004 年,Hadoop 的创始人道格·卡廷(Doug Cutting)和麦克·卡法雷拉(Mike Cafarella)受 MapReduce 编程模型和 Google File System 等技术的启发,对其中提及的思想进行了编程实现,Hadoop 的名字来源于道格 · 卡廷儿子的玩具大象。由于道格 · 卡廷后来加入了雅虎,并在雅虎工作期间做了大量 Hadoop 的研发工作,因此 Hadoop 也经常被认为是雅虎开源的一款大数据框架。时至今日,Hadoop 不仅是整个大数据领域的先行者和领航者,更形成了一套围绕 Hadoop 的生态圈,Hadoop 和它的生态圈是绝大多数企业首选的大数据解决方案。图 1-7 展示了 Hadoop 生态圈一些流行组件。 + +Hadoop 生态圈的核心组件主要有如下 3 个。 + +- **Hadoop MapReduce**:Hadoop 版本的 MapReduce 编程模型,可以处理海量数据,主要面向批处理。 +- **HDFS**:HDFS(Hadoop Distributed File System)是 Hadoop 提供的分布式文件系统,有很好的扩展性和容错性,为海量数据提供存储支持。 +- **YARN**:YARN(Yet Another Resource Negotiator)是 Hadoop 生态圈中的资源调度器,可以管理一个 Hadoop 集群,并为各种类型的大数据任务分配计算资源。 + +这三大组件中,数据存储在 HDFS 上,由 MapReduce 负责计算,YARN 负责集群的资源管理。除了三大核心组件,Hadoop 生态圈还有很多其他著名的组件,部分如下。 + +- **Hive**:借助 Hive,用户可以编写结构化查询语言(Structured Query Language,SQL)语句来查询 HDFS 上的结构化数据,SQL 语句会被转化成 MapReduce 运行。 +- **HBase**:HDFS 可以存储海量数据,但访问和查询速度比较慢,HBase 可以提供给用户毫秒级的实时查询服务,它是一个基于 HDFS 的分布式数据库。HBase 最初受 Google Bigtable 技术的启发。 +- **Kafka**:Kafka 是一款流处理框架,主要用作消息队列。 +- **ZooKeeper**:Hadoop 生态圈中很多组件使用动物来命名,形成了一个大型 “动物园”,ZooKeeper 是这个动物园的管理者,主要负责分布式环境的协调。 + +![图 1-7 Hadoop 生态圈](./img/hadoop.png) + +## 1.3.2 Spark + +2009 年,Spark 诞生于加州大学伯克利分校,2013 年被捐献给 Apache 基金会。实际上,Spark 的创始团队本来是为了开发集群管理框架 Apache Mesos(以下简称 Mesos)的,其功能类似 YARN,Mesos 开发完成后,需要一个基于 Mesos 的产品运行在上面以验证 Mesos 的各种功能,于是他们接着开发了 Spark。Spark 有火花、鼓舞之意,创始团队希望用 Spark 来证明在 Mesos 上从零开始创造一个项目非常简单。 + +Spark 是一款大数据处理框架,其开发初衷是改良 Hadoop MapReduce 的编程模型和提高运行速度,尤其是提升大数据在机器学习方向上的性能。与 Hadoop 相比,Spark 的改进主要有如下两点。 + +- ** 易用性 **:MapReduce 模型比 MPI 更友好,但仍然不够方便。因为并不是所有计算任务都可以被简单拆分成 Map 和 Reduce,有可能为了解决一个问题,要设计多个 MapReduce 任务,任务之间相互依赖,整个程序非常复杂,导致代码的可读性和可维护性差。Spark 提供更加方便易用的接口,提供 Java、Scala、Python 和 R 语言等的 API,支持 SQL、机器学习和图计算,覆盖了绝大多数计算场景。 +- ** 速度快 **:Hadoop 的 Map 和 Reduce 的中间结果都需要存储到磁盘上,而 Spark 尽量将大部分计算放在内存中。加上 Spark 有向无环图的优化,在官方的基准测试中,Spark 比 Hadoop 快一百倍以上。 + +Spark 的核心在于计算,主要目的在于优化 Hadoop MapReduce 计算部分,在计算层面提供更细致的服务。 + +Spark 并不能完全取代 Hadoop,实际上,从图 1-7 可以看出,Spark 融入了 Hadoop 生态圈,成为其中的重要一员。一个 Spark 任务很可能依赖 HDFS 上的数据,向 YARN 申请计算资源,将结果输出到 HBase 上。当然,Spark 也可以不用依赖这些组件,独立地完成计算。 + +![图 1-8 Spark 生态圈](./img/spark.png) + +Spark 主要面向批处理需求,因其优异的性能和易用的接口,Spark 已经是批处理界绝对的 “王者”。Spark 的子模块 Spark Streaming 提供了流处理的功能,它的流处理主要基于 mini-batch 的思想。如图 1-9 所示,Spark Streaming 将输入数据流切分成多个批次,每个批次使用批处理的方式进行计算。因此,Spark 是一款集批处理和流处理于一体的处理框架。 + +![图 1-9 Spark Streaming mini-batch 处理](./img/spark-streaming-mini-batch.png) + +## 1.3.3 Apache Kafka + +2010 年,LinkedIn 开始了其内部流处理框架的开发,2011 年将该框架捐献给了 Apache 基金会,取名 Apache Kafka(以下简称 Kafka)。Kafka 的创始人杰 · 克雷普斯(Jay Kreps)觉得这个框架主要用于优化读写,应该用一个作家的名字来命名,加上他很喜欢作家卡夫卡的文学作品,觉得这个名字对一个开源项目来说很酷,因此取名 Kafka。 + +Kafka 也是一种面向大数据领域的消息队列框架。在大数据生态圈中,Hadoop 的 HDFS 或 Amazon S3 提供数据存储服务,Hadoop MapReduce、Spark 和 Flink 负责计算,Kafka 常常用来连接不同的应用系统。 + +如图 1-10 所示,企业中不同的应用系统作为数据生产者会产生大量数据流,这些数据流还需要进入不同的数据消费者,Kafka 起到数据集成和系统解耦的作用。系统解耦是让某个应用系统专注于一个目标,以降低整个系统的维护难度。在实践上,一个企业经常拆分出很多不同的应用系统,系统之间需要建立数据流管道(Stream Pipeline)。假如没有 Kafka 的消息队列,M 个生产者和 N 个消费者之间要建立 M×N 个点对点的数据流管道,Kafka 就像一个中介,让数据管道的个数变为 M+N,大大减小了数据流管道的复杂程度。 + +![图 1-10 Kafka 可以连接多个应用系统](./img/kafka.png) + +从批处理和流处理的角度来讲,数据流经 Kafka 后会持续不断地写入 HDFS,积累一段时间后可提供给后续的批处理任务,同时数据流也可以直接流入 Flink,被用于流处理。 + +随着流处理的兴起,Kafka 不甘心只做一个数据流管道,开始向轻量级流处理方向努力,但相比 Spark 和 Flink 这样的计算框架,Kafka 的主要功能侧重在消息队列上。 + +## 1.3.4 Flink + +Flink 是由德国 3 所大学发起的的学术项目,后来不断发展壮大,并于 2014 年年末成为 Apache 顶级项目之一。在德语中,“flink” 表示快速、敏捷,以此来表征这款计算框架的特点。 + +Flink 主要面向流处理,如果说 Spark 是批处理界的 “王者”,那么 Flink 就是流处理领域冉冉升起的 “新星”。流处理并不是一项全新的技术,在 Flink 之前,不乏流处理引擎,比较著名的有 Storm、Spark Streaming,图 1-11 展示了流处理框架经历的三代演进。 + +2011 年成熟的 Apache Strom(以下简称 Storm)是第一代被广泛采用的流处理引擎。它是以数据流中的事件为最小单位来进行计算的。以事件为单位的框架的优势是延迟非常低,可以提供毫秒级的延迟。流处理结果依赖事件到达的时序准确性,Storm 并不能保障处理结果的一致性和准确性。Storm 只支持至少一次(At-Least-Once)和至多一次(At-Most-Once),即数据流里的事件投递只能保证至少一次或至多一次,不能保证只有一次(Exactly-Once)。在多项基准测试中,Storm 的数据吞吐量和延迟都远逊于 Flink。对于很多对数据准确性要求较高的应用,Storm 有一定劣势。此外,Storm 不支持 SQL,不支持中间状态(State)。 + +图 1-11 流处理框架演进 + +2013 年成熟的 Spark Streaming 是第二代被广泛采用的流处理框架。1.3.2 小节中提到,Spark 是 “一统江湖” 的大数据处理框架,Spark Streaming 采用微批次(mini-batch)的思想,将数据流切分成一个个小批次,一个小批次里包含多个事件,以接近实时处理的效果。这种做法保证了 “Exactly-Once” 的事件投递效果,因为假如某次计算出现故障,重新进行该次计算即可。Spark Streaming 的 API 相比第一代流处理框架更加方便易用,与 Spark 批处理集成度较高,因此 Spark 可以给用户提供一个流处理与批处理一体的体验。但因为 Spark Streaming 以批次为单位,每次计算一小批数据,比起以事件为单位的框架来说,延迟从毫秒级变为秒级。 + +与前两代引擎不同,在 2015 年前后逐渐成熟的 Flink 是一个支持在有界和无界数据流上做有状态计算的大数据处理框架。它以事件为单位,支持 SQL、状态、水位线(Watermark)等特性,支持 “Exactly-Once”。比起 Storm,它的吞吐量更高,延迟更低,准确性能得到保障;比起 Spark Streaming,它以事件为单位,达到真正意义上的实时计算,且所需计算资源相对更少。具体而言,Flink 的优点如下。 + +- 支持事件时间(Event Time)和处理时间(Processing Time)多种时间语义。即使事件乱序到达,Event Time 也能提供准确和一致的计算结果。Procerssing Time 适用于对延迟敏感的应用。 +- Exactly-Once 投递保障。 +- 毫秒级延迟。 +- 可以扩展到上千台节点、在阿里巴巴等大公司的生产环境中进行过验证。 +- 易用且多样的 API,包括核心的 DataStream API 和 DataSet API 以及 Table API 和 SQL。 +- 可以连接大数据生态圈各类组件,包括 Kafka、Elasticsearch、JDBC、HDFS 和 Amazon S3。可以运行在 Kubernetes、YARN、Mesos 和独立(Standalone)集群上。 \ No newline at end of file