❶ 大数据分析应该掌握哪些基础知识
java基础语法
· 分支结构if/switch
· 循环结构for/while/do while
· 方法声明和调用
· 方法重载
· 数组的使用
· 命令行参数、可变参数
IDEA
· IDEA常用设置、常用快捷键
· 自定义模板
· 关联Tomcat
· Web项目案例实操
面向对象编程
· 封装、继承、多态、构造器、包
· 异常处理机制
· 抽象类、接口、内部类
· 常有基础API、集合List/Set/Map
· 泛型、线程的创建和启动
· 深入集合源码分析、常见数据结构解析
· 线程的安全、同步和通信、IO流体系
· 反射、类的加载机制、网络编程
Java8/9/10/11新特性
· Lambda表达式、方法引用
· 构造器引用、StreamAPI
· jShell(JShell)命令
· 接口的私有方法、Optional加强
· 局部变量的类型推断
· 更简化的编译运行程序等
MySQL
· DML语言、DDL语言、DCL语言
· 分组查询、Join查询、子查询、Union查询、函数
· 流程控制语句、事务的特点、事务的隔离级别等
JDBC
· 使用JDBC完成数据库增删改查操作
· 批处理的操作
· 数据库连接池的原理及应用
· 常见数据库连接池C3P0、DBCP、Druid等
Maven
· Maven环境搭建
· 本地仓库&中央仓库
· 创建Web工程
· 自动部署
· 持续继承
· 持续部署
Linux
· VI/VIM编辑器
· 系统管理操作&远程登录
· 常用命令
· 软件包管理&企业真题
Shell编程
· 自定义变量与特殊变量
· 运算符
· 条件判断
· 流程控制
· 系统函数&自定义函数
· 常用工具命令
· 面试真题
Hadoop
· Hadoop生态介绍
· Hadoop运行模式
· 源码编译
· HDFS文件系统底层详解
· DN&NN工作机制
· HDFS的API操作
· MapRece框架原理
· 数据压缩
· Yarn工作机制
· MapRece案例详解
· Hadoop参数调优
· HDFS存储多目录
· 多磁盘数据均衡
· LZO压缩
· Hadoop基准测试
Zookeeper
· Zookeeper数据结果
· 内部原理
· 选举机制
· Stat结构体
· 监听器
· 分布式安装部署
· API操作
· 实战案例
· 面试真题
· 启动停止脚本
HA+新特性
· HDFS-HA集群配置
Hive
· Hive架构原理
· 安装部署
· 远程连接
· 常见命令及基本数据类型
· DML数据操作
· 查询语句
· Join&排序
· 分桶&函数
· 压缩&存储
· 企业级调优
· 实战案例
· 面试真题
Flume
· Flume架构
· Agent内部原理
· 事务
· 安装部署
· 实战案例
· 自定义Source
· 自定义Sink
· Ganglia监控
Kafka
· 消息队列
· Kafka架构
· 集群部署
· 命令行操作
· 工作流程分析
· 分区分配策略
· 数据写入流程
· 存储策略
· 高阶API
· 低级API
· 拦截器
· 监控
· 高可靠性存储
· 数据可靠性和持久性保证
· ISR机制
· Kafka压测
· 机器数量计算
· 分区数计算
· 启动停止脚本
DataX
· 安装
· 原理
· 数据一致性
· 空值处理
· LZO压缩处理
Scala
· Scala基础入门
· 函数式编程
· 数据结构
· 面向对象编程
· 模式匹配
· 高阶函数
· 特质
· 注解&类型参数
· 隐式转换
· 高级类型
· 案例实操
Spark Core
· 安装部署
· RDD概述
· 编程模型
· 持久化&检查点机制
· DAG
· 算子详解
· RDD编程进阶
· 累加器&广播变量
Spark SQL
· SparkSQL
· DataFrame
· DataSet
· 自定义UDF&UDAF函数
Spark Streaming
· SparkStreaming
· 背压机制原理
· Receiver和Direct模式原理
· Window原理及案例实操
· 7x24 不间断运行&性能考量
Spark内核&优化
· 内核源码详解
· 优化详解
Hbase
· Hbase原理及架构
· 数据读写流程
· API使用
· 与Hive和Sqoop集成
· 企业级调优
Presto
· Presto的安装部署
· 使用Presto执行数仓项目的即席查询模块
Ranger2.0
· 权限管理工具Ranger的安装和使用
Azkaban3.0
· 任务调度工具Azkaban3.0的安装部署
· 使用Azkaban进行项目任务调度,实现电话邮件报警
Kylin3.0
· Kylin的安装部署
· Kylin核心思想
· 使用Kylin对接数据源构建模型
Atlas2.0
· 元数据管理工具Atlas的安装部署
Zabbix
· 集群监控工具Zabbix的安装部署
DolphinScheler
· 任务调度工具DolphinScheler的安装部署
· 实现数仓项目任务的自动化调度、配置邮件报警
Superset
· 使用SuperSet对数仓项目的计算结果进行可视化展示
Echarts
· 使用Echarts对数仓项目的计算结果进行可视化展示
Redis
· Redis安装部署
· 五大数据类型
· 总体配置
· 持久化
· 事务
· 发布订阅
· 主从复制
Canal
· 使用Canal实时监控MySQL数据变化采集至实时项目
Flink
· 运行时架构
· 数据源Source
· Window API
· Water Mark
· 状态编程
· CEP复杂事件处理
Flink SQL
· Flink SQL和Table API详细解读
Flink 内核
· Flink内核源码讲解
· 经典面试题讲解
Git&GitHub
· 安装配置
· 本地库搭建
· 基本操作
· 工作流
· 集中式
ClickHouse
· ClickHouse的安装部署
· 读写机制
· 数据类型
· 执行引擎
DataV
· 使用DataV对实时项目需求计算结果进行可视化展示
sugar
· 结合Springboot对接网络sugar实现数据可视化大屏展示
Maxwell
· 使用Maxwell实时监控MySQL数据变化采集至实时项目
ElasticSearch
· ElasticSearch索引基本操作、案例实操
Kibana
· 通过Kibana配置可视化分析
Springboot
· 利用Springboot开发可视化接口程序
❷ 数据分析需要掌握哪些知识
Java基础语法
· 分支结构if/switch
· 循环结构for/while/do while
· 方法声明和调用
· 方法重载
· 数组的使用
· 命令行参数、可变参数
IDEA
· IDEA常用设置、常用快捷键
· 自定义模板
· 关联Tomcat
· Web项目案例实操
面向对象编程
· 封装、继承、多态、构造器、包
· 异常处理机制
· 抽象类、接口、内部类
· 常有基础API、集合List/Set/Map
· 泛型、线程的创建和启动
· 深入集合源码分析、常见数据结构解析
· 线程的安全、同步和通信、IO流体系
· 反射、类的加载机制、网络编程
Java8/9/10/11
新特性
· Lambda表达式、方法引用
· 构造器引用、StreamAPI
· jShell(JShell)命令
· 接口的私有方法、Optional加强
· 局部变量的类型推断
· 更简化的编译运行程序等
MySQL
· DML语言、DDL语言、DCL语言
· 分组查询、Join查询、子查询、Union查询、函数
· 流程控制语句、事务的特点、事务的隔离级别等
JDBC
· 使用JDBC完成数据库增删改查操作
· 批处理的操作
· 数据库连接池的原理及应用
· 常见数据库连接池C3P0、DBCP、Druid等
Maven
· Maven环境搭建
· 本地仓库&中央仓库
· 创建Web工程
· 自动部署
· 持续继承
· 持续部署
Linux
· VI/VIM编辑器
· 系统管理操作&远程登录
· 常用命令
· 软件包管理&企业真题
Shell编程
· 自定义变量与特殊变量
· 运算符
· 条件判断
· 流程控制
· 系统函数&自定义函数
· 常用工具命令
· 面试真题
Hadoop
· Hadoop生态介绍
· Hadoop运行模式
· 源码编译
· HDFS文件系统底层详解
· DN&NN工作机制
· HDFS的API操作
· MapRece框架原理
· 数据压缩
· Yarn工作机制
· MapRece案例详解
· Hadoop参数调优
· HDFS存储多目录
· 多磁盘数据均衡
· LZO压缩
· Hadoop基准测试
Zookeeper
· Zookeeper数据结果
· 内部原理
· 选举机制
· Stat结构体
· 监听器
· 分布式安装部署
· API操作
· 实战案例
· 面试真题
· 启动停止脚本
HA+新特性
· HDFS-HA集群配置
Hive
· Hive架构原理
· 安装部署
· 远程连接
· 常见命令及基本数据类型
· DML数据操作
· 查询语句
· Join&排序
· 分桶&函数
· 压缩&存储
· 企业级调优
· 实战案例
· 面试真题
Flume
· Flume架构
· Agent内部原理
· 事务
· 安装部署
· 实战案例
· 自定义Source
· 自定义Sink
· Ganglia监控
Kafka
· 消息队列
· Kafka架构
· 集群部署
· 命令行操作
· 工作流程分析
· 分区分配策略
· 数据写入流程
· 存储策略
· 高阶API
· 低级API
· 拦截器
· 监控
· 高可靠性存储
· 数据可靠性和持久性保证
· ISR机制
· Kafka压测
· 机器数量计算
· 分区数计算
· 启动停止脚本
DataX
· 安装
· 原理
· 数据一致性
· 空值处理
· LZO压缩处理
Scala
· Scala基础入门
· 函数式编程
· 数据结构
· 面向对象编程
· 模式匹配
· 高阶函数
· 特质
· 注解&类型参数
· 隐式转换
· 高级类型
· 案例实操
Spark Core
· 安装部署
· RDD概述
· 编程模型
· 持久化&检查点机制
· DAG
· 算子详解
· RDD编程进阶
· 累加器&广播变量
Spark SQL
· SparkSQL
· DataFrame
· DataSet
· 自定义UDF&UDAF函数
Spark Streaming
· SparkStreaming
· 背压机制原理
· Receiver和Direct模式原理
· Window原理及案例实操
· 7x24 不间断运行&性能考量
Spark内核&优化
· 内核源码详解
· 优化详解
Hbase
· Hbase原理及架构
· 数据读写流程
· API使用
· 与Hive和Sqoop集成
· 企业级调优
Presto
· Presto的安装部署
· 使用Presto执行数仓项目的即席查询模块
Ranger2.0
· 权限管理工具Ranger的安装和使用
Azkaban3.0
· 任务调度工具Azkaban3.0的安装部署
· 使用Azkaban进行项目任务调度,实现电话邮件报警
Kylin3.0
· Kylin的安装部署
· Kylin核心思想
· 使用Kylin对接数据源构建模型
Atlas2.0
· 元数据管理工具Atlas的安装部署
Zabbix
· 集群监控工具Zabbix的安装部署
DolphinScheler
· 任务调度工具DolphinScheler的安装部署
· 实现数仓项目任务的自动化调度、配置邮件报警
Superset
· 使用SuperSet对数仓项目的计算结果进行可视化展示
Echarts
· 使用Echarts对数仓项目的计算结果进行可视化展示
Redis
· Redis安装部署
· 五大数据类型
· 总体配置
· 持久化
· 事务
· 发布订阅
· 主从复制
Canal
· 使用Canal实时监控MySQL数据变化采集至实时项目
Flink
· 运行时架构
· 数据源Source
· Window API
· Water Mark
· 状态编程
· CEP复杂事件处理
Flink SQL
· Flink SQL和Table API详细解读
Flink 内核
· Flink内核源码讲解
· 经典面试题讲解
Git&GitHub
· 安装配置
· 本地库搭建
· 基本操作
· 工作流
· 集中式
ClickHouse
· ClickHouse的安装部署
· 读写机制
· 数据类型
· 执行引擎
DataV
· 使用DataV对实时项目需求计算结果进行可视化展示
sugar
· 结合Springboot对接网络sugar实现数据可视化大屏展示
Maxwell
· 使用Maxwell实时监控MySQL数据变化采集至实时项目
ElasticSearch
· ElasticSearch索引基本操作、案例实操
Kibana
· 通过Kibana配置可视化分析
Springboot
· 利用Springboot开发可视化接口程序
❸ 哪位好心人能提供个最新flink视频学习教程,感谢
大数据教程flink从入门到精通
了解Flink,了解集群环境搭建运维,学习Flink中重要概念、原理和API的用法,通过知识点 + 案例教学法帮助小白快速掌握Flink。
课程内容:
1、Flink框架简介
2、Flink集群搭建运维
3、Flink Dataset开发
4、Flink 广播变量,分布式缓存,累加器
5、Flink Datastream开发
6、Flink Window操作
7、Flink watermark与侧道输出
8、Flink状态计算
9、Flink容错checkpoint与一致性语义
10、Flink进阶 异步IO,背压,内存管理
11、Flink Table API与SQL
❹ Apache Flink现在在大数据处理方面能够和Apache Spark分庭抗礼么
我们是否还需要另外一个新的数据处理引擎?当我第一次听到flink的时候这是我是非常怀疑的。在大数据领域,现在已经不缺少数据处理框架了,但是没有一个框架能够完全满足不同的处理需求。自从Apache spark出现后,貌似已经成为当今把大部分的问题解决得最好的框架了,所以我对另外一款解决类似问题的框架持有很强烈的怀疑态度。
不过因为好奇,我花费了数个星期在尝试了解flink。一开始仔细看了flink的几个例子,感觉和spark非常类似,心理就倾向于认为flink又是一个模仿spark的框架。但是随着了解的深入,这些API体现了一些flink的新奇的思路,这些思路还是和spark有着比较明显的区别的。我对这些思路有些着迷了,所以花费了更多的时间在这上面。
flink中的很多思路,例如内存管理,dataset API都已经出现在spark中并且已经证明 这些思路是非常靠谱的。所以,深入了解flink也许可以帮助我们分布式数据处理的未来之路是怎样的
在后面的文章里,我会把自己作为一个spark开发者对flink的第一感受写出来。因为我已经在spark上干了2年多了,但是只在flink上接触了2到3周,所以必然存在一些bias,所以大家也带着怀疑和批判的角度来看这篇文章吧。
Apache Flink是什么
flink是一款新的大数据处理引擎,目标是统一不同来源的数据处理。这个目标看起来和spark和类似。没错,flink也在尝试解决spark在解决的问题。这两套系统都在尝试建立一个统一的平台可以运行批量,流式,交互式,图处理,机器学习等应用。所以,flink和spark的目标差别并不大,他们最主要的区别在于实现的细节。
后面我会重点从不同的角度对比这两者。
Apache Spark vs Apache Flink
1.抽象 Abstraction
spark中,对于批处理我们有RDD,对于流式,我们有DStream,不过内部实际还是RDD.所以所有的数据表示本质上还是RDD抽象。
后面我会重点从不同的角度对比这两者。在flink中,对于批处理有DataSet,对于流式我们有DataStreams。看起来和spark类似,他们的不同点在于:
一)DataSet在运行时是表现为运行计划(runtime plans)的
在spark中,RDD在运行时是表现为java objects的。通过引入Tungsten,这块有了些许的改变。但是在flink中是被表现为logical plan(逻辑计划)的,听起来很熟悉?没错,就是类似于spark中的dataframes。所以在flink中你使用的类Dataframe api是被作为第一优先级来优化的。但是相对来说在spark RDD中就没有了这块的优化了。
flink中的Dataset,对标spark中的Dataframe,在运行前会经过优化。
在spark 1.6,dataset API已经被引入spark了,也许最终会取代RDD 抽象。
二)Dataset和DataStream是独立的API
在spark中,所有不同的API,例如DStream,Dataframe都是基于RDD抽象的。但是在flink中,Dataset和DataStream是同一个公用的引擎之上两个独立的抽象。所以你不能把这两者的行为合并在一起操作,当然,flink社区目前在朝这个方向努力(https://issues.apache.org/jira/browse/FLINK-2320),但是目前还不能轻易断言最后的结果。
2.内存管理
一直到1.5版本,spark都是试用java的内存管理来做数据缓存,明显很容易导致OOM或者gc。所以从1.5开始,spark开始转向精确的控制内存的使用,这就是tungsten项目了
flink从第一天开始就坚持自己控制内存试用。这个也是启发了spark走这条路的原因之一。flink除了把数据存在自己管理的内存以外,还直接操作二进制数据。在spark中,从1.5开始,所有的dataframe操作都是直接作用在tungsten的二进制数据上。
3.语言实现
spark是用scala来实现的,它提供了Java,Python和R的编程接口。
flink是java实现的,当然同样提供了Scala API
所以从语言的角度来看,spark要更丰富一些。因为我已经转移到scala很久了,所以不太清楚这两者的java api实现情况。
4.API
spark和flink都在模仿scala的collection API.所以从表面看起来,两者都很类似。下面是分别用RDD和DataSet API实现的word count
// Spark wordcount
object WordCount {
def main(args: Array[String]) {
val env = new SparkContext("local","wordCount")
val data = List("hi","how are you","hi")
val dataSet = env.parallelize(data)
val words = dataSet.flatMap(value => value.split("\\s+"))
val mappedWords = words.map(value => (value,1))
val sum = mappedWords.receByKey(_+_)
println(sum.collect())
}
}
// Flink wordcount
object WordCount {
def main(args: Array[String]) {
val env = ExecutionEnvironment.getExecutionEnvironment
val data = List("hi","how are you","hi")
val dataSet = env.fromCollection(data)
val words = dataSet.flatMap(value => value.split("\\s+"))
val mappedWords = words.map(value => (value,1))
val grouped = mappedWords.groupBy(0)
val sum = grouped.sum(1)
println(sum.collect())
}
}
不知道是偶然还是故意的,API都长得很像,这样很方便开发者从一个引擎切换到另外一个引擎。我感觉以后这种Collection API会成为写data pipeline的标配。
Steaming
spark把streaming看成是更快的批处理,而flink把批处理看成streaming的special case。这里面的思路决定了各自的方向,其中两者的差异点有如下这些:
实时 vs 近实时的角度
flink提供了基于每个事件的流式处理机制,所以可以被认为是一个真正的流式计算。它非常像storm的model。
而spark,不是基于事件的粒度,而是用小批量来模拟流式,也就是多个事件的集合。所以spark被认为是近实时的处理系统。
Spark streaming 是更快的批处理,而Flink Batch是有限数据的流式计算。
虽然大部分应用对准实时是可以接受的,但是也还是有很多应用需要event level的流式计算。这些应用更愿意选择storm而非spark streaming,现在,flink也许是一个更好的选择。
流式计算和批处理计算的表示
spark对于批处理和流式计算,都是用的相同的抽象:RDD,这样很方便这两种计算合并起来表示。而flink这两者分为了DataSet和DataStream,相比spark,这个设计算是一个糟糕的设计。
对 windowing 的支持
因为spark的小批量机制,spark对于windowing的支持非常有限。只能基于process time,且只能对batches来做window。
而Flink对window的支持非常到位,且Flink对windowing API的支持是相当给力的,允许基于process time,data time,record 来做windowing。
我不太确定spark是否能引入这些API,不过到目前为止,Flink的windowing支持是要比spark好的。
Steaming这部分flink胜
SQL interface
目前spark-sql是spark里面最活跃的组件之一,Spark提供了类似Hive的sql和Dataframe这种DSL来查询结构化数据,API很成熟,在流式计算中使用很广,预计在流式计算中也会发展得很快。
至于flink,到目前为止,Flink Table API只支持类似DataFrame这种DSL,并且还是处于beta状态,社区有计划增加SQL 的interface,但是目前还不确定什么时候才能在框架中用上。
所以这个部分,spark胜出。
Data source Integration
Spark的数据源 API是整个框架中最好的,支持的数据源包括NoSql db,parquet,ORC等,并且支持一些高级的操作,例如predicate push down
Flink目前还依赖map/rece InputFormat来做数据源聚合。
这一场spark胜
Iterative processing
spark对机器学习的支持较好,因为可以在spark中利用内存cache来加速机器学习算法。
但是大部分机器学习算法其实是一个有环的数据流,但是在spark中,实际是用无环图来表示的,一般的分布式处理引擎都是不鼓励试用有环图的。
但是flink这里又有点不一样,flink支持在runtime中的有环数据流,这样表示机器学习算法更有效而且更有效率。
这一点flink胜出。
Stream as platform vs Batch as Platform
Spark诞生在Map/Rece的时代,数据都是以文件的形式保存在磁盘中,这样非常方便做容错处理。
Flink把纯流式数据计算引入大数据时代,无疑给业界带来了一股清新的空气。这个idea非常类似akka-streams这种。
成熟度
目前的确有一部分吃螃蟹的用户已经在生产环境中使用flink了,不过从我的眼光来看,Flink还在发展中,还需要时间来成熟。
结论
目前Spark相比Flink是一个更为成熟的计算框架,但是Flink的很多思路很不错,Spark社区也意识到了这一点,并且逐渐在采用Flink中的好的设计思路,所以学习一下Flink能让你了解一下Streaming这方面的更迷人的思路。
❺ flink 1.10 1.12区别
flink 1.10 1.12区别在于Flink 1.12 支持了 Flink SQL Kafka upsert connector 。
因为在 Flink 1.10 中,当前这类任务开发对于用户来说,还是不够友好,需要很多代码,同时也会造成 Flink SQL 冗长。
Flink 1.12 SQL Connector 支持 Kafka Upsert Connector,这也是我们公司内部业务方对实时平台提出的需求。
收益:便利用户有这种需要从 kafka 取最新记录操作的实时任务开发,比如这种 binlog -> kafka,然后用户聚合操作,这种场景还是非常多的,这能提升实时作业开发效率,同时 1.12 做了优化,性能会比单纯的 last_value 性能要好。
Flink Yarn 作业 On k8s 的生产级别能力是:
Flink Jar 作业已经全部 K8s 化,Flink SQL 作业由于是推广初期,还是在 Yarn 上面进行运行,为了将实时计算 Flink 全部K8s化。
所以我们 Flink SQL 作业也需要迁移到 K8s,目前 Flink 1.12 已经满足生产级别的 Flink k8s 功能,所以 Flink SQL K8s 化,打算直接使用社区的 On k8s 能力。
风险:虽然和社区的人沟通,Flink 1.12 on k8s 没有什么问题,但是具体功能还是需要先 POC 验证一下,同时可能社区 Flink on k8s 的能力。
可能会限制我们这边一些 k8s 功能使用,比如 hostpath volome 以及 Ingress 的使用,这里可能需要改底层源码来进行快速支持(社区有相关 JIRA 要做)。
❻ Apache Flink是什么
Flink为流处理和批处理应用公用一个通用的引擎。
1、数据量&吞吐量&延迟性
Flink 的流处理引擎只需要很少配置就能实现高吞吐率和低延迟。
2、支持 Event Time 和乱序事件
Flink 支持了流处理和 Event Time 语义的窗口机制。
Event time 使得计算乱序到达的事件或可能延迟到达的事件更加简单。
3、状态计算的 exactly-once 语义
流程序可以在计算过程中维护自定义状态。
Flink 的 checkpointing 机制保证了即时在故障发生下也能保障状态的 exactly once 语义。
4、高度灵活的流式窗口
Flink 支持在时间窗口,统计窗口,session 窗口,以及数据驱动的窗口
窗口可以通过灵活的触发条件来定制,以支持复杂的流计算模式。
5、带反压的连续流模型
数据流应用执行的是不间断的(常驻)operators。
Flink streaming 在运行时有着天然的流控:慢的数据 sink 节点会反压(backpressure)快的数据源(sources)。
6、容错性
Flink 的容错机制是基于 Chandy-Lamport distributed snapshots 来实现的。
这种机制是非常轻量级的,允许系统拥有高吞吐率的同时还能提供强一致性的保障。
7、Batch 和 Streaming 一个系统流处理和批处理共用一个引擎
Flink 为流处理和批处理应用公用一个通用的引擎。批处理应用可以以一种特殊的流处理应用高效地运行。
8、内存管理
Flink 在 JVM 中实现了自己的内存管理。
应用可以超出主内存的大小限制,并且承受更少的垃圾收集的开销。
9、迭代和增量迭代
Flink 具有迭代计算的专门支持(比如在机器学习和图计算中)。
增量迭代可以利用依赖计算来更快地收敛。
10、程序调优
批处理程序会自动地优化一些场景,比如避免一些昂贵的操作(如 shuffles 和 sorts),还有缓存一些中间数据。
❼ 聊聊批计算、流计算、Hadoop、Spark、Storm、Flink等等
批:处理离线数据,冷数据。单个处理数据量大,处理速度比流慢。
流:处理在线,实时产生的数据。单次处理的数据量小,但处理速度更快。
Spark是UC Berkeley AMP lab所开源的类Hadoop MapRece的通用并行框架。
Spark,拥有Hadoop MapRece所具有的优点;但不同于MapRece的是Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapRece的算法。
Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些有用的不同之处使 Spark 在某些工作负载方面表现得更加优越,换句话说, Spark 启用了RDD(弹性分布式数据集),除了能够提供交互式查询外,它还可以优化迭代工作负载。RDD可以常驻内存的属性,大大简化了迭代计算所需的开销,Spark任务可以立马利用上一次计算出来的RDD来进行下次迭代。
Apache Hadoop中的MapRece是属于离线计算技术;
Spark中Spark Core属于离线计算技术,只不过它基于内存存储中间结果,速度上比MapRece 快很多倍,又离实时计算技术很近;
Spark中Spark Streaming 子项目属于实时计算技术,类似于Storm;
Spark中SparkSQL属于离线计算技术,只不过它基于内存存储中间结果,速度上比Hive快很多倍。
Spark并不是要成为一个大数据领域的“独裁者”,一个人霸占大数据领域所有的“地盘”,而是与Hadoop进行了高度的集成,两者可以完美的配合使用。Hadoop的HDFS、Hive、HBase负责存储,YARN负责资源调度;Spark负责大数据计算。实际上,Hadoop+Spark的组合,可以解决绝大部分大数据的场景。
Spark逐渐形成了一套完整的生态系统,既能够提供内存计算框架,也可以支持SQL 即席查询、实时流计算、机器学习和图计算等。
Spark所提供的生态,可以支持如下3中场景:
一栈式解决方案(one stack to rule them all)
Spark包含了大数据领域常见的各种计算框架:
Spark streaming批量读取数据源中的数据,然后把每个batch转化成内部的RDD。Spark streaming以batch为单位进行计算(默认1s产生一个batch),而不是以Tuple为单位,大大减少了ack所需的开销,显着提高了吞吐。
但也因为处理数据的粒度变大,导致Spark streaming的数据延时不如Storm,Spark streaming是秒级返回结果(与设置的batch间隔有关),Storm则是毫秒级。
Storm提供了低延迟的计算,但是吞吐较低,并且无法保证exactly once(Storm trident采用batch的方式改善了这两点),Spark streaming通过小批量的方式保证了吞吐的情况下,同时提供了exactly once语义,但是实时性不如Storm,而且由于采用micro-batch的方式,对window和event time的支持比较有限(Spark streaming 2.0中引入了window和event time,还在起步阶段)。
Flink采用分布式快照的方式实现了一个高吞吐、低延迟、支持exactly once的流式系统,流式处理的方式也能更优雅的支持window和event time。
当然也不是说Flink一定就比Storm、Spark streaming好, 没有最好的框架,只有最合适的框架 。根据自身的业务、公司的技术储备选择最合适的框架才是正确的选择。
❽ Flink的类加载器解析
在运行 Flink 应用程序时,JVM 会随着时间的推移加载各种类。 这些类可以根据它们的来源分为三组:
作为一般规则,无论何时您先启动 Flink 进程然后再提交作业,作业的类都会动态加载。 如果 Flink 进程与作业/应用程序一起启动,或者如果应用程序产生 Flink 组件(JobManager、TaskManager 等),那么所有作业的类都在 Java 类路径中。
插件组件中的代码由每个插件的专用类加载器动态加载一次。
以下是有关不同部署模式的更多详细信息:
当作为独立会话启动 Flink 集群时,JobManagers 和 TaskManagers 使用 Java 类路径中的 Flink 框架类启动。 针对会话(通过 REST / CLI)提交的所有作业/应用程序中的类都是动态加载的。
Docker / Kubernetes 设置首先启动一组 JobManagers / TaskManagers,然后通过 REST 或 CLI 提交作业/应用程序,其行为类似于独立会话:Flink 的代码位于 Java 类路径中,插件组件和作业代码在启动时动态加载。
YARN 类加载在单个作业部署和会话之间有所不同:
当直接向 YARN 提交 Flink 作业/应用程序时(通过 bin/flink run -m yarn-cluster ...),将为该作业启动专用的 TaskManager 和 JobManager。 这些 JVM 在 Java 类路径中具有用户代码类。 这意味着在这种情况下,作业不涉及动态类加载。
当启动一个 YARN 会话时,JobManagers 和 TaskManagers 是用 classpath 中的 Flink 框架类启动的。 针对会话提交的所有作业的类都是动态加载的。
在涉及动态类加载的设置中(插件组件、会话设置中的 Flink 作业),通常有两个类加载器的层次结构:(1)Java 的应用程序类加载器,它包含类路径中的所有类,以及(2)动态插件/ 用户代码类加载器。 用于从插件或用户代码 jar 加载类。 动态 ClassLoader 将应用程序类加载器作为其父级。
默认情况下,Flink 反转类加载顺序,这意味着它首先查看动态类加载器,如果类不是动态加载代码的一部分,则仅查看父类(应用程序类加载器)。
反向类加载的好处是插件和作业可以使用与 Flink 核心本身不同的库版本,这在不同版本的库不兼容时非常有用。 该机制有助于避免常见的依赖冲突错误,如 IllegalAccessError 或 NoSuchMethodError。 代码的不同部分只是具有单独的类副本(Flink 的核心或其依赖项之一可以使用与用户代码或插件代码不同的副本)。 在大多数情况下,这运行良好,不需要用户进行额外配置。
但是,在某些情况下,反向类加载会导致问题(请参阅下文,“X cannot be cast to X”)。 对于用户代码类加载,您可以通过在 Flink 配置中通过 classloader.resolve-order 将 ClassLoader 解析顺序配置为 parent-first(从 Flink 的默认 child-first)来恢复到 Java 的默认模式。
请注意,某些类总是以父级优先的方式解析(首先通过父类加载器),因为它们在 Flink 的核心和插件/用户代码或面向插件/用户代码的 API 之间共享。 这些类的包是通过 classloader.parent-first-patterns-default 和 classloader.parent-first-patterns-additional 配置的。 要添加父级优先加载的新包,请设置 classloader.parent-first-patterns-additional 配置选项。
所有组件(JobManger、TaskManager、Client、ApplicationMaster 等)在启动时记录它们的类路径设置。 它们可以作为日志开头的环境信息的一部分找到。
当运行 JobManager 和 TaskManagers 专用于一项特定作业的设置时,可以将用户代码 JAR 文件直接放入 /lib 文件夹中,以确保它们是类路径的一部分而不是动态加载。
通常将作业的 JAR 文件放入 /lib 目录中。 JAR 将成为类路径(AppClassLoader)和动态类加载器(FlinkUserCodeClassLoader)的一部分。 因为 AppClassLoader 是 FlinkUserCodeClassLoader 的父级(并且 Java 加载父级,默认情况下),这应该导致类只加载一次。
对于无法将作业的 JAR 文件放入 /lib 文件夹的设置(例如因为安装程序是由多个作业使用的会话),仍然可以将公共库放入 /lib 文件夹,并避免动态为那些类进行加载。
在某些情况下,转换函数、源或接收器需要手动加载类(通过反射动态加载)。 为此,它需要能够访问作业类的类加载器。
在这种情况下,函数(或源或接收器)可以成为 RichFunction(例如 RichMapFunction 或 RichWindowFunction)并通过 getRuntimeContext().getUserCodeClassLoader() 访问用户代码类加载器。
在使用动态类加载的设置中,您可能会看到 com.foo.X cannot be cast to com.foo.X 样式中的异常。 这意味着 com.foo.X 类的多个版本已被不同的类加载器加载,并且该类的类型试图相互分配。
一个常见的原因是库与 Flink 的反向类加载方法不兼容。 您可以关闭反向类加载来验证这一点(在 Flink 配置中设置 classloader.resolve-order: parent-first)或从反向类加载中排除库(在 Flink 配置中设置 classloader.parent-first-patterns-additional)。
另一个原因可能是缓存对象实例,如 Apache Avro 之类的某些库或通过注册(例如通过 Guava 的 Interners)生成的对象实例。 这里的解决方案是要么在没有任何动态类加载的情况下进行设置,要么确保相应的库完全是动态加载代码的一部分。 后者意味着该库不能被添加到 Flink 的 /lib 文件夹中,而必须是应用程序的 fat-jar/uber-jar 的一部分
所有涉及动态用户代码类加载(会话)的场景都依赖于再次卸载类。 类卸载意味着垃圾收集器发现类中不存在任何对象,因此删除该类(代码、静态变量、元数据等)。
每当 TaskManager 启动(或重新启动)一个任务时,它将加载该特定任务的代码。 除非可以卸载类,否则这将成为内存泄漏,因为加载了新版本的类,并且加载的类总数会随着时间的推移而累积。 这通常通过 OutOfMemoryError: Metaspace 表现出来。
类泄漏的常见原因和建议的修复:
卸载动态加载类的一个有用工具是用户代码类加载器释放钩子。 这些是在卸载类加载器之前执行的钩子。 通常建议关闭和卸载资源作为常规函数生命周期的一部分(通常是 close() 方法)。 但在某些情况下(例如对于静态字段),最好在不再需要类加载器时卸载。
类加载器释放钩子可以通过 RuntimeContext.() 方法注册。
从应用程序开发人员的角度解决依赖冲突的一种方法是通过隐藏它们来避免暴露依赖关系。
Apache Maven 提供了 maven-shade-plugin,它允许在编译后更改类的包(因此您编写的代码不受阴影影响)。 例如,如果您的用户代码 jar 中有来自 aws sdk 的 com.amazonaws 包,则 shade 插件会将它们重新定位到 org.myorg.shaded.com.amazonaws 包中,以便您的代码调用您的 aws sdk 版本。
注意 Flink 的大部分依赖,比如 guava、netty、jackson 等,都被 Flink 的维护者屏蔽掉了,所以用户通常不用担心。