Skip to content

Commit

Permalink
Added content for the following first two chapters.
Browse files Browse the repository at this point in the history
  • Loading branch information
hainaweiben committed Jul 1, 2024
1 parent 5b7dc27 commit 6b2ccfd
Show file tree
Hide file tree
Showing 15 changed files with 1,331 additions and 5 deletions.
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

0 comments on commit 6b2ccfd

Please sign in to comment.