不一样的Flink入门教程
前言
微信搜【Java3y】关注这个朴实无华的男人,点赞关注是对我最大的支持!
文本已收录至我的GitHub:https://github.com/ZhongFuCheng3y/3y,有300多篇原创文章,最近在连载面试和项目系列!
在前段时间写了一篇《Storm》入门的文章,很多同学给我说:“大人,时代变了”。
最近公司要把Storm
集群给下线啦,所以我们都得把Storm
的任务都改成Flink
。
于是最近入门了一把Flink
,现在来分享一下Flink
入门的相关知识。
(写上面这一段话的时候,到发文章这个时候已经过了一个季度了,不好意思,我这篇文章拖了一个季度)
不得不说,Flink这两年是真的火🔥这篇文章主要讲讲Flink
入门时一些可能看不太懂的点又或是看官方介绍看不太懂的点(API
我就不细说了,多用用应该都能看懂)。
什么是Flink?
在Flink的官网上,可以把官方文档语言设置为中文,于是我们可以看到官方是这样介绍的:
上面的图我们每个字都能看得懂,但连起来就看不懂了。
不管怎么样,我们可以了解到:Flink是一个分布式的计算处理引擎
-
分布式:「它的存储或者计算交由多台服务器上完成,最后汇总起来达到最终的效果」。
-
实时:处理速度是毫秒级或者秒级的
-
计算:可以简单理解为对数据进行处理,比如清洗数据(对数据进行规整,取出有用的数据)
基于官网的一句话介绍,我们就可以联想出很多东西。
这篇文章可以带你简单认识一下Flink的一些基础概念,等你真正用到的时候就可以依据这篇文章来对Flink进行入门,现在Storm都被很多人给抛弃掉了,那么Flink优于Storm的地方有哪些呢?接下来我们一起来看看Flink吧。
什么是有边界和无边界?
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。
官方其实也有介绍,但对初学者来说不太好理解,我来幼儿园化一下。
大家学到Flink了,消息队列肯定有用过吧?那你们是怎么用消息队列的呢?Producer
生产数据,发给Broker
,Consumer
消费,完事。
在消费的时候,我们需要管什么Producer什么时候发消息吗?不需要吧。反正来一条,我就处理一条,没毛病吧。
这种没有做任何处理的消息,默认就是无边界的。
那有边界就很好理解了:无边界的基础上加上条件,那就是有边界的。加什么条件呢?比如我要加个时间:我要消费从8月8号到8月9号的数据,那就是有边界的。
什么时候用无边界,什么时候用有边界?那也很好理解。我做数据清洗:来一条,我处理一条,这种无边界的就好了。我要做数据统计:每个小时的pv
(page view)是多少,那我就设置1小时的边界,攒着一小时的数据来处理一次。
在Flink
上,设置“边界”这种操作叫做开窗口(Windows
),窗口可简单分为两种类型:
-
时间窗口(
TimeWindows
):按照时间窗口进行聚合,比如上面所讲得攥着一个小时的数据处理一次。 -
计数窗口(
CountWindows
):按照指定的条数来进行聚合,比如每来了10条数据处理一次。
看着就非常人性化(妈妈再也不用担心我需要聚合了)...
不仅如此,在Flink
使用窗口聚合的时候,还考虑到了数据的准确性问题。比如说:现在我在11:06分
产生了5
条数据,在11:07分
产生了4条数据
,我现在是按每分钟的维度来进行聚合计算。
理论上来讲:Flink
应该是在06分
聚合了5条
数据,在07分
聚合了4条
数据。但是,可能由于网络的延迟性等原因,导致06分
的3条
数据在07分
时Flink
才接收到。如果不做任何处理,那07分
有可能处理了7条
条数据。
某些需要准确结果的场景来说,这就不太合理了。所以Flink
可以给我们指定”时间语义“,不指定默认是「数据到Flink的时间」Processing Time
来进行聚合处理,可以给我们指定聚合的时间以「事件发生的时间」Event Time
来进行处理。
事件发生的时间指的就是:日志真正记录的时间
2020-11-22 00:00:02.552 INFO [http-nio-7001-exec-28] c.m.t.rye.admin.web.aop.LogAspect
虽然指定了聚合的时间为「事件发生的时间」Event Time
,但还是没解决数据乱序的问题(06分产生了5条数据,实际上06分只收到了3条,而剩下的两条在07分才收到,那此时怎么办呢?在06分时该不该聚合,07分收到的两条06分数据怎么办?)
Flink
又可以给我们设置水位线(waterMarks
),Flink意思就是:存在网络延迟等情况导致数据接收不是有序,这种情况我都能理解。你这样吧,根据自身的情况,你可以设置一个「延迟时间」,等延迟的时间到了,我再聚合统一聚合。
比如说:现在我知道数据有可能会延迟一分钟,那我将水位线waterMarks
设置延迟一分钟。
解读:因为设置了「事件发生的时间」Event Time
,所以Flink
可以检测到每一条记录发生的时间,而设置了水位线waterMarks
设置延迟一分钟,等到Flink
发现07分:59秒
的数据来到了Flink
,那就确信06分
的数据都来了(因为设置了1分钟延迟),此时才聚合06分
的窗口数据。
什么叫做有状态?
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。
什么是有状态,什么是无状态?
无状态我们可以简单认为:每次的执行都不依赖上一次或上N次的执行结果,每次的执行都是独立的。
有状态我们可以简单认为:执行需要依赖上一次或上N次的执行结果,某次的执行需要依赖前面事件的处理结果。
比如,我们现在要统计文章的阅读PV
(page view),现在只要有一个点击了文章,在Kafka
就会有一条消息。现在我要在流式处理平台上进行统计,那此时是有状态的还是无状态的?
假设我们要在Storm
做,那我们可能将每次的处理结果放到一个“外部存储”中,然后基于这个“外部存储”进行计算(这里我们不用Storm Trident
),那此时Storm
是无状态的。
比如说:我存储将每次得到的数据存储到 Redis
中,来一条数据,我就先查一下Redis目前的值是多少,跟Redis
的值和现在的值做一次累加就完事了。
假设要在Flink
做,Flink
本身就提供了这种功能给我们使用,我们可以依赖Flink
的“存储”,将每次的处理结果交由Flink
管理,执行计算的逻辑。
可以简单的认为:Flink本身就给我们提供了”存储“的功能,而我们每次执行是可以依赖Flink的”存储”的,所以它是有状态的。
那Flink
是把这些有状态的数据存储在哪的呢?
主要有三个地方:
-
内存
-
文件系统(HDFS)
-
本地数据库
如果假设Flink
挂了,可能内存的数据没了,磁盘可能存储了部分的数据,那再重启的时候(比如消息队列会重新拉取),就不怕会丢了或多了数据吗?
看到这里,你可能在会在别的地方看过Flink
的另外一个比较出名的特性:精确一次性
(简单来说就是:Flink
遇到意外事件挂了以后,有什么机制来尽可能保证处理数据不重复和不丢失的呢)
什么是精确一次性(exactly once)?
众所周知,流的语义性有三种:
-
精确一次性(exactly once):有且只有一条,不多不少
-
至少一次(at least once):最少会有一条,只多不少
-
最多一次(at most once):最多只有一条,可能会没有
Flink实现了精确一次性,这个精确一次性是什么意思呢?
Flink的精确一次性指的是:状态只持久化一次到最终的存储介质中(本地数据库/HDFS...)
以上面的图为例:Source
数据流有以下数字21,13,8,5,3,2,1,1
,然后在Flink
需要做累加操作(求和)
现在处理完2,1,1
了,所以累加的值是4
,现在Flink
把累积后的状态4
已经存储起来了(认为前面2,1,1
这几个数字已经完全处理过了)。
程序一直往下走,处理了5,3
,现在累加的值是12
,但现在Flink
还没来得及把12
存储到最终的介质,此时系统挂掉了。
Flink重启后会重新把系统恢复到累加的值是4
的状态,所以5,3
得继续计算一遍,程序继续往下走。
看文章有的同学可能会认为:精确一次性指的不是某一段代码只会执行一次,不会执行多次或不执行。这5
和3
这两个数,你不是重复计算了吗?怎么就精确一次了?
显然,代码只执行一次肯定是不可能的嘛。我们无法控制系统在哪一行代码挂掉的,你要是在挂的时候,当前方法还没执行完,你还是得重新执行该方法的。
所以,状态只持久化一次到最终的存储介质中(本地数据库/HDFS),在Flink下就叫做exactly once
(计算的数据可能会重复(无法避免),但状态在存储介质上只会存储一次)。
那么Flink
是在多长时间存储一次的呢?这个是我们自己手动配置的。
所谓的CheckPoint
其实就是Flink
会在指定的时间段上保存状态的信息,假设Flink
挂了可以将上一次状态信息再捞出来,重放还没保存的数据来执行计算,最终实现exactly once
。
那CheckPonit
是怎么办到的呢?想想我们在Kafka
在业务上实现「至少一次」是怎么做的?我们从Kafka
把数据拉下来,处理完业务了以后,手动提交offset
(告诉Kafka
我已经处理完了)
我们是做完了业务规则才将offset
进行commit
的,checkponit
其实也是一样的(等拉下来该条数据所有的流程走完,才进行真正的checkponit
)。
问题又来了,那checkpoint
是怎么知道拉下来的数据已经走完了呢?Flink
在流处理过程中插入了barrier
,每个环节处理到barrier
都会上报,等到sink
都上报了barrier
就说明这次checkpoint
已经走完了。
要注意的是,Flink
实现的精确一次性只是保证内部的状态是精确一次的,如果想要端到端精确一次,需要端的支持
-
数据源需要可回放,发证故障可以重新读取未确认的数据
-
Flink
需要把数据存到磁盘介质(不能用内存),发生故障可以恢复 -
发送源需要支持事务(从读到写需要事务的支持保证中途不失败)
最后
这篇文章对Flink
做了一次简单的介绍,希望对大家在入门的时候有所帮助。后续打算会再写一篇Flink
文章对CheckPoint
机制做更加深入的了解,有兴趣的同学可以点个关注第一时间能接收到。
三歪把【大厂面试知识点】、【简历模板】、【原创文章】全部整理成电子书,共有1263页!点击下方链接直接取就好了
PDF文档的内容均为手打,有任何的不懂都可以直接来问我

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一文把三个经典求和问题吃的透透滴。
点击上方“五分钟学算法”,选择“星标”公众号 重磅干货,第一时间送达 今天为大家带来三道求和问题,通过文字,图画,动图为大家解析,很容易就能读懂,每道题目都是经典题,大家快来打卡吧。 题目来源:leetcode 1.两数之和(简单) 15.三数之和(中等) 18.四数之和(中等) 两数之和 题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1] 题目很容易理解,即让查看数组中有没有两个数的和为目标数,如果有的话则返回两数下标,在这为大家提供两种解法双指针(暴力)法,和哈希表法,大家可以看一下。 哈希表法 解析 哈希表的做法很容易理解,我们只需通过一次循环即可,假如我们的 target 值为 9,当前指针指向的值为 2 ,我们只需从哈希表中查找是否含有 7,因为...
- 下一篇
React 入门儿
共计 10137 字,阅读时长约 25 分钟 谁都没有看见过风,更不用说你和我了。但是当纸币在飘的时候,我们知道那是风在数钱。 React 影响着我们工作的方方面面,我们每天都在使用它,只窥其表却难以窥其里。正所谓看不如写,本篇文章的目的就是从原理层面探究 React 是如何工作的。 工具— 在写文章之前,为了方便理解,我准备了一个懒人调试仓库 simple_react[1] ,这个仓库将 benchmark 用例(只有两个 ^ ^)和 React 源码共同放在 src 文件夹中,通过 snowpack 进行热更新,可以直接在源码中加入 log 和 debuger 进行调试。当然这里的“源码”并不是真的源码,因为 React 源码中充斥着巨量的 dev 代码和不明确的功能函数,所以我对源码进行了整理,用 typescript 对类型进行了规范,删除了大量和核心流程无关的代码(当然也误删了一些有关的 ^ ^)。 如果你只是希望了解 React 的运行流程而不是写一个可以用的框架的话,那么这个仓库完全可以满足你学习的需要。当然,这个仓库基于 React16.8 ,虽然这个版本并不包括当前的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7设置SWAP分区,小内存服务器的救世主
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS关闭SELinux安全模块