Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added content for the following first two chapters. #18

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions doc/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ root: index
subtrees:
- numbered: 2
entries:
- 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/stream-processing-basics
- file: ch-big-data-intro/bigdata-programming-languages
- file: ch-big-data-intro/exercise-building-data-stream-using-Kafka
- file: ch-programming-basics/index
entries:
- file: ch-programming-basics/inheritance-and-polymorphism
- file: ch-programming-basics/generics
- file: ch-programming-basics/functional-programming
- file: ch-programming-basics/exercise-Flink-development-environment
- file: ch-system-design/index
entries:
- file: ch-system-design/dataflow
Expand Down
64 changes: 64 additions & 0 deletions doc/ch-big-data-intro/batch-processing-and-stream-processing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
(batch-processing-and-stream-processing)=
# 从批处理到流处理

## 1.2.1 数据与数据流

在大数据的5个“V”中我们已经提到,数据量大且产生速度快。从时间维度来讲,数据源源不断地产生,形成一个无界的数据流(Unbounded Data Stream)。如图1-5所示,单条数据被称为事件(Event),事件按照时序排列会形成一个数据流。例如,我们每时每刻的运动数据都会累积到手机传感器上,金融交易随时随地都在发生,物联网(Internet of Things,IoT)传感器会持续监控并生成数据。

![图1-5 数据和数据流](./img/)

数据流中的某段有界数据流(Bounded Data Stream)可以组成一个数据集。我们通常所说的对某份数据进行分析,指的是对某个数据集进行分析。随着数据的产生速度越来越快,数据源越来越多,人们对时效性的重视程度越来越高,如何处理数据流成了大家更为关注的问题。

在本书以及其他官方资料中,也会将单条事件称为一条数据或一个元素(Element)。在本书后文的描述中,事件、数据、元素这3个概念均可以用来表示数据流中的某个元素。

## 1.2.2 批处理与流处理

### 1. 批处理

批处理(Batch Processing)是指对一批数据进行处理。我们身边的批处理比比皆是,最常见的批处理例子有:微信运动每天晚上有一个批处理任务,把用户好友一天所走的步数统计一遍,生成排序结果后推送给用户;银行信用卡中心每月账单日有一个批处理任务,把一个月的消费总额统计一次,生成用户月度账单;国家统计局每季度对经济数据做一次统计,公布季度国内生产总值(GDP)。可见,批处理任务一般是对一段时间的数据聚合后进行处理的。对于数据量庞大的应用,如微信运动、银行信用卡中心等情景,一段时间内积累的数据总量非常大,计算非常耗时。

### 2. 流处理

如前文所述,数据其实是以流(Stream)的方式持续不断地产生着的,流处理(Stream Processing)就是对数据流进行处理。时间就是金钱,对数据流进行分析和处理,获取实时数据价值越发重要。如“双十一电商大促销”,管理者要以秒级的响应时间查看实时销售业绩、库存信息以及与竞品的对比结果,以争取更多的决策时间;股票交易要以毫秒级的速度来对新信息做出响应;风险控制要对每一份欺诈交易迅速做出处理,以减少不必要的损失;网络运营商要以极快速度发现网络和数据中心的故障;等等。以上这些场景,一旦出现故障,造成服务的延迟,损失都难以估量。因此,响应速度越快,越能减少损失、增加收入。而IoT和5G的兴起将为数据生成提供更完美的底层技术基础,海量的数据在IoT设备上采集,并通过高速的5G通道传输到服务器,庞大的实时数据流将汹涌而至,流处理的需求肯定会爆炸式增长。

## 1.2.3 为什么需要一个优秀的流处理框架

处理实时流的系统通常被称为流计算框架、实时计算框架或流处理框架。下面就来解释为何需要一个可靠的流处理框架。

### 1. 股票交易的业务场景

我们都知道股票交易非常依赖各类信息,一些有可能影响股票市场价格的信息经常首发于财经网站、微博、微信等社交媒体平台上。作为人类的我们不可能24小时一直监控各类媒体,如果有一个自动化的系统来做一些分析和预警,将为决策者争取到更多时间。

假设我们有数只股票的交易数据流,我们可以通过这个数据流来计算以10秒为一个时间窗口的股票价格波动,选出那些超过5%变化幅度的股票,并将这些股票与媒体的实时文本数据做相关分析,以判断媒体上的哪些实时信息会影响股票价格。当相关分析的结果足够有说服力时,可以将这个系统部署到生产环境,实时处理股票与媒体数据,产生分析报表,并发送给交易人员。那么,如何构建一个可靠的程序来解决上述业务场景问题呢?

### 2. 生产者-消费者模型

处理流数据一般使用“生产者-消费者”(Producer-Consumer)模型来解决问题。如图1-6所示,生产者生成数据,将数据发送到一个缓存区域(Buffer),消费者从缓存区域中消费数据。这里我们暂且不关心生产者如何生产数据,以及数据如何缓存,我们只关心如何实现消费者。

![图1-6 生产者-消费者模型](./img/)

在股票交易的场景中,我们可以启动一个进程来实现消费者,该进程以10秒为一个时间窗口,统计时间窗口内的交易情况,找到波动最大的那些股票。同时,该进程也对新流入的媒体文本进行分析。这个逻辑看起来很容易实现,但深挖之后会发现问题繁多。

### 3. 流处理框架要解决的诸多问题

#### (1) 可扩展性

股票交易和媒体文本的数据量都非常大,仅以微博为例,平均每秒有上千条、每天有上亿条微博数据。一般情况下,单个节点无法处理这样规模的数据,这时候需要使用分布式计算。假如我们使用类似MPI的框架,需要手动设计分治算法,这对很多程序员来说有一定的挑战性。

随着数据不断增多,我们能否保证我们的程序能够快速扩展到更多的节点上,以应对更多的计算需求?具体而言,当计算需求增多时,计算资源能否线性增加而不是耗费大量的资源,程序的代码逻辑能否保持简单而不会变得极其复杂?一个具有可扩展性的系统必须能够优雅地解决这些问题。

#### (2) 数据倾斜

在分布式计算中,数据需要按照某种规则分布到各个节点上。假如数据路由规则设计得不够完善,当数据本身分布不均匀时,会发生数据倾斜,这很可能导致部分节点数据量远大于其他节点。这样的后果是:轻则负载重的节点延迟过高,重则引发整个系统的崩溃。假如一条突发新闻在网络媒体平台引发激烈的讨论和分析,数据突增,程序很可能会崩溃。数据倾斜是分布式计算中经常面临的一个问题。

#### (3) 容错性

整个系统崩溃重启后,之前的那些计算如何恢复?或者部分节点发生故障,如何将该节点上的计算迁移到其他的节点上?我们需要一个机制来做故障恢复,以增强系统的容错性。

#### (4) 时序错乱

限于网络条件和其他各种潜在影响因素,流处理引擎处理某个事件的时间并不是事件本来发生的时间。比如,你想统计上午11:00:00到11:00:10的交易情况,然而发生在11:00:05的某项交易因网络延迟没能抵达,这时候要直接放弃这项交易吗?绝大多数情况下我们会让程序等待,比如我们会假设数据最晚不会延迟超过10分钟,因此程序会等待10分钟。等待一次也还能接受,但是如果有多个节点在并行处理呢?每个节点等待一段时间,最后做数据聚合时就要等待更长时间。

批处理框架一般处理一个较长时间段内的数据,数据的时序性对其影响较小。批处理框架用更长的时间来换取更好的准确性。流处理框架对时序错乱更为敏感,框架的复杂程度也因此大大增加。

Flink是解决上述问题的最佳选择之一。如果用Flink去解决前文提到的股票建模问题,只需要设置时间窗口,并在这个时间窗口下做一些数据处理的操作,还可以根据数据量来设置由多少节点并行处理。
31 changes: 31 additions & 0 deletions doc/ch-big-data-intro/bigdata-programming-languages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
(bigdata-programming-languages)=
# 编程语言的选择

大数据编程一般会使用Java、Scala和Python等编程语言,Flink目前也支持上述3种语言,本节从大数据编程的角度来分析几种编程语言的优劣。

## 1.6.1 Java和Scala

Java是“老牌”企业级编程语言。Java相比C/C++更易上手,支持多线程,其生态圈中可用的第三方库众多。Java虚拟机(Java Virtual Machine,JVM)保证了程序的可移植性,可以快速部署到不同计算机上,是很多分布式系统首选的编程语言,比如Hadoop和Flink的绝大多数代码都是用Java编写的,这些框架提供了丰富的文档,网络社区的支持好。因此,进行大数据编程,Java编程是必备的技能。相比一些新型编程语言,Java的缺点是代码有点冗长。

Scala是一门基于JVM的编程语言。相比Java,Scala的特色是函数式编程。函数式编程非常适合大数据处理,我们将在第2章进一步介绍函数式编程思想。在并行计算方面,Scala支持Actor模型,Actor模型是一种更为先进的并行计算编程模型,很多大数据框架都基于Actor模型。Spark、Flink和Kafka都是基于Actor模型的大数据框架。Scala可以直接调用Java的代码,相比Java,Scala代码更为简洁和紧凑。凡事都有两面性,Scala虽然灵活简洁,但是不容易掌握,即使是有一定Java基础的开发者,也需要花一定时间系统了解Scala。

另外,Java和Scala在互相学习和借鉴。Java 8开始引入了Lambda表达式和链式调用,能够支持函数式编程,部分语法与Scala越来越接近,代码也更加简洁。

**注意**

这里的Lambda表达式与1.4.1小节介绍的Lambda架构不同。Lambda表达式基于函数式编程,是一种编写代码的方式。Lambda架构主要指如何同时处理流批数据,是一种大数据架构。

Flink的核心代码由Java和Scala编写,为这两种语言提供丰富强大的API,程序员可根据自己和团队的习惯从Java和Scala中选择。本书基于以下两点考虑,决定主要以Java来演示Flink的编程。

- Flink目前绝大多数代码和功能均由Java实现,考虑到本书会展示一些Flink中基于Java的源码和接口,为了避免读者在Java和Scala两种语言间混淆,将主要使用Java展示一些Flink的核心概念。
- 不同读者的编程语言基础不一样,Scala用户往往有一定的Java编程基础,而Java用户可能对Scala并不熟悉。而且Scala的语法非常灵活,一不小心可能出现莫名其妙的错误,初学者难以自行解决,而Scala相对应的书籍和教程不多。或者说Scala用户一般能够兼容Java,而Java用户学习Scala的成本较高。

此外,由于大多数Spark作业基于Scala,很多大数据工程师要同时负责Spark和Flink两套业务逻辑,加上Flink的Scala API与Spark比较接近,本书也会在一些地方提示Scala用户在使用Flink时的必要注意事项,并在随书附赠的工程中提供Java和Scala两个版本的代码,方便读者学习。

## 1.6.2 Python

Python无疑是近几年来编程语言界的“明星”。Python简单易用,有大量第三方库,支持Web、科学计算和机器学习,被广泛应用到人工智能领域。大数据生态圈的各项技术对Python支持力度也很大,Hadoop、Spark、Kafka、HBase等技术都有Python版本的API。鉴于Python在机器学习和大数据领域的流行程度,Flink社区非常重视对Python API的支持,正在积极完善Flink的Python接口。相比Java和Scala,Python API还处于完善阶段,迭代速度非常快。Flink的Python API名为PyFlink,是在1.9版本之后逐渐完善的,但相比Java和Scala还不够完善。考虑到Python和Java/Scala有较大区别,本书的绝大多数内容均基于Java相关知识,且PyFlink也在不断迭代、完善,本书暂时不探讨PyFlink。

## 1.6.3 SQL

严格来说,SQL并不是一种全能的编程语言,而是一种在数据库上对数据进行操作的语言,相比Java、Scala和Python,SQL的上手门槛更低,它在结构化数据的查询上有绝对的优势。一些非计算机相关专业出身的读者可以在短期内掌握SQL,并进行数据分析。随着数据科学的兴起,越来越多的岗位开始要求候选人有SQL技能,包括数据分析师、数据产品经理和数据运营等岗位。Flink把这种面向结构化查询的需求封装成了表(Table),对外提供Table API 和 SQL的调用接口,提供了非常成熟的SQL支持。SQL的学习和编写成本很低,利用它能够处理相对简单的业务逻辑,其非常适合在企业内被大规模推广。本书第8章将重点介绍Table API 和SQL的使用方法。
Loading
Loading