Flink知识点

本文深入探讨Flink与其他流处理框架如Storm、SparkStreaming的对比,详细解析FlinkDataStreamAPI的基本算子,以及Flink在Yarn上的部署方式。同时,文章还介绍了FlinkKafkaConnector的工作机制,数据流的分区策略,分布式缓存的使用,State和Checkpoint机制,重启策略,窗口操作,时间概念,以及并行度和TaskManager数量的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. Flink、Storm、Sparkstreaming对比

Storm只支持流处理任务,数据是一条一条的源源不断地处理,而MapReduce、spark只支持批处理任务,spark-streaming本质上是一个批处理,采用micro-batch的方式,将数据流切分成细粒度的batch进行处理。Flink同时支持流处理和批处理,一条数据被处理完以后,序列化到缓存后,以固定的缓存块为单位进行网络数据传输,缓存块设为0为流处理,缓存块设为较大值为批处理。
storm------ ---------At-least-once----Record Acks-------无状态管理-------- 低延迟-----------高吞吐
sparkstreaming-----Exectly-once-------RDD Checkpoint-----基于DStream-----中等延迟-----高吞吐
Flink-----------------Exectly-once------ Checkpoint-----------基于操作----------低延迟-------高吞吐

2. Flink DataStream API基本算子

map:做一些清洗转换;
flatMap:输入一个元素,返回一个或者多个元素;
filter:符合条件的数据留下;
keyBy:key相同的数据进入同一个分区;
reduce:当前元素与上一次reduce返回值进行聚合操作;
Union:合并多个流,但是所有的流类型必须一致
Connect:合并两个流,两个流的类型可以不同
CoMapCoFlatMap:对于ConnectedStream使用这俩函数,对两个流进行不同的处理;
split:根据规则吧一个数据流切分为多个流;
Select:配合split,选择切分后的流;

3. Flink On Yarn

Flink on yarn上的好处:
  • 提高集群机器的利用率;
  • 一套集群,可以同时执行MR任务,Spark任务,Flink任务。
Flink on yarn的两种方式:
  • 一开始在Yarn上初始化一个集群;yarn-session.sh【开辟资源】+flink run【提交任务】
  • 每个Flink job都申请一个集群,互不影响,任务执行之后资源会被释放掉。flink run -m yarn-cluster【开辟资源+提交任务】 


4. FlinkKafkaConnector(
FlinkKafkaConsumer+FlinkKafkaProducer)

阅读过FlinkKafkaConnector源码后对Kafka偏移量的存储机制有了一个全新的认识,这里有两个坑,简单记下:

  • FlinkKafkaComsumer08用的Kafka老版本Consumer,偏移量提交Zookeeper,由Zookeeper保管,而FlinkKafkaComsumer09以后,偏移量默认存在Kafka内部的Topic中,不再向Zookeeper提交;
  • 使用FlinkKafkaProducer08写Kafka1.1.0(其他高版本没试过)存在超时

5. DataStream API之partition

  • 随机分区
1 dataStream.shuffle();
  • 重分区,消除数据倾斜
1 dataStream.rebalance();
  • 自定义分区
1 dataStream.partitionCustom(partiitoner,"somekey");
  • 广播分区:把元素广播所有分区,会被重复消费
1 DataStream.broadcast();

6. Flink Distributed Cache(分布式缓存)

  • 原理
类似Hadoop,可以在并行函数比如map中读取本地文件或则HDFS文件,Flink自动将文件复制到所有taskmanager节点的本地文件系统。
  • 用法

用法一:注册一个文件

1 env.registerCachedFile(“hdfs:///path/to/yout/file","hdfsfile");

用法二:访问数据

1 File myFile = getRuntimeContext().getDistributedCache().getFile("hdfsFile");

7. State

为了实现at least once和exactly once,flink引入了state和checkpoint;state一般将数据保存在 堆内存中,而checkpoint是每隔一段时把state数据 持久化存储了,当失败时可以恢复。

8. Checkpoint

依赖checkpoint机制,只能保证Flink系统内的exactly once。
checkpoint默认是disabled的,开启之后默认是exactly once,这种模式对大多数应用合适,而at least once在某些低延迟的场景中比较合适(例如几毫秒)。例如,
1 env.enableCheckpointing(1000);                                            //每隔1000ms设置一个检查点【检查点周期】             
2 env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);//设置模式为exactly once(默认值)                 
3 env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);//检查点之间至少有500ms的间隔【检查点最小间隔】        
4 env.getCheckpointConfig().setCheckpointTimeout(60000); //检查点必须在一分钟之内完成,否则丢弃【检查点的超时时间】
5 env.getCheckpointConfig().setMaxConcurrentCheckpoints(1); //同一时间点只允许一个检查点                        
6 env.getCheckpointConfig().enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
7 //Flink程序被取消后,会保留检查点数据

9. Flink重启策略

Flink中常用重启策略:
固定时间(Fixed delay);
失败率(Failure rate)【checkpoint机制默认策略】;
无重启(No start)【 默认

10. Window(窗口)

Flink中的窗口与可以分为时间驱动【Time Window】和数据驱动【Count Window】,每一个可以细分为:
  • 滚动窗口【没有重叠】tumbling windows
1 .timeWindow(Time.minutes(1));
2 .countWindow(100);
  • 滑动窗口【有重叠】sliding windows
1 .timeWindow(Time.minutes(1),Time.seconds(30))//每隔30秒,统计一分钟的数据
2 .countWindow(100,10)//每隔10条数据,统计100条的数据
  • 会话窗口 session windows
定义了窗口之后,会存在不同的聚合:
  • 增量聚合(窗口中每进入一条数据,就进行一次计算),例如reduce、aggregate、sum、min、max;
  • 全量聚合(等窗口所有数据到齐,才开始计算,可以进行排序等)例如apply、process等

11. Time

针对Stream数据流中的时间,可以分为以下三种:
  • Event Time:日志产生的时间;
  • Ingestion Time:事件从kafka等取出来,进入Flink的时间;
  • Processing Time:事件被处理的时间,例如达到窗口处理的时间等。【默认】 

12. Flink并行度

  • Flink中每个TaskManager为集群提供slot,slot数量与每个节点的可用CPU核数成比例,slot上启动进程,进程内有多个线程。

配置一个TaskManager有多少个并发的slot数有两种配置方式:

taskmanager.numberOfTaskSlots。在conf/flink-conf.yaml中更改,默认值为1,表示默认一个TaskManager只有1个task slot.

提交作业时通过参数配置。--yarnslots 1,表示TaskManager的slot数为1.

⚠️注意:slot不能搞太多,几十个就行,你想啊假如你机器不多,TaskManager不多,搞那么多slot,每个slot分到的内存小的可怜,容易OOM啊

  • 并行度的设置有多个地方:操作算子层面、执行环境层面、客户端层面、系统层面,具体可以参考:FLINK并行度
算子层面具体情况具体分析,例如KafkaSource的并行度最好跟Kafka Topic的分区数成比例,比如:
1 val wordCounts = text
2    .flatMap{ _.split(" ") map { (_, 1) } }
3    .keyBy(0)
4    .timeWindow(Time.seconds(5))
5    .sum(1).setParallelism(5)

执行环境层面比如:

1 env.setParallelism(5)

提交任务的时候,在客户端侧flink可以通过-p参数来设置并行度。例如:

1 ./bin/flink run -p 5 ../examples/*WordCount-java*.jar

13. TaskManager数量

TaskManager的数量是在提交作业时根据并行度动态计算。先根据设定的 operator的最大并行度计算,例如,如果作业中operator的最大并行度为10,则 Parallelism/numberOfTaskSlots为向YARN申请的TaskManager数。

14. Flink传递参数给函数

参数可以使用构造函数或withParameters(Configuration)方法传递,参数将会作为函数对象的一部分被序列化并传递到task实例中。
  • 使用构造函数方式

 1 DataSet toFilter = env.fromElements(1, 2, 3);
 2 toFilter.filter(new MyFilter(2));
 3 private static class MyFilter implements FilterFunction {
 4   private final int limit;
 5   public MyFilter(int limit) {
 6     this.limit = limit;
 7   }
 8   @Override
 9   public boolean filter(Integer value) throws Exception {
10     return value > limit;
11   }
12 }
(2)withParameters(Configuration)方式
这个方法将携带一个Configuration对象作为参数,参数将会传递给Rich Function的open方法(关于Rich Function参见:rich function)。Configuration对象是一个Map,存储Key/Value键值对.
 1 DataSet toFilter = env.fromElements(1, 2, 3);
 2 Configuration config = new Configuration();
 3 config.setInteger("limit", 2);
 4 toFilter.filter(new RichFilterFunction() {
 5     private int limit;
 6     @Override
 7     public void open(Configuration parameters) throws Exception {
 8       limit = parameters.getInteger("limit", 0);
 9     }
10     @Override
11     public boolean filter(Integer value) throws Exception {
12       return value > limit;
13     }
14 }).withParameters(config);
(3)使用全局的the ExecutionConfig方式
参数可以被所有的rich function获得
 1 Configuration conf = new Configuration();
 2 conf.setString("mykey","myvalue");
 3 final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
 4 env.getConfig().setGlobalJobParameters(conf);
 5 public static final class Tokenizer extends RichFlatMapFunction> {
 6     private String mykey;
 7     @Override
 8     public void open(Configuration parameters) throws Exception {
 9       super.open(parameters);
10       ExecutionConfig.GlobalJobParameters globalParams = getRuntimeContext().getExecutionConfig().getGlobalJobParameters();
11       Configuration globConf = (Configuration) globalParams;
12       mykey = globConf.getString("mykey", null);
13     }
14     // ... more here ...

15. Flink中的Metrics

Flink中有丰富的Metrics指标,当然我们也可以使用它的Reporter自定义,具体参见官网,示例如下:
 1 import org.apache.flink.api.common.accumulators.LongCounter;
 2 import org.apache.flink.api.common.functions.RichMapFunction;
 3 import org.apache.flink.api.java.utils.ParameterTool;
 4 import org.apache.flink.configuration.Configuration;
 5 import org.apache.flink.dropwizard.metrics.DropwizardMeterWrapper;
 6 import org.apache.flink.metrics.Counter;
 7 import org.apache.flink.metrics.Meter;
 8 import org.apache.flink.metrics.MetricGroup;
 9 
10 
11 public class Map extends RichMapFunction<String, String> {
12   private transient Meter logTotalMeter;
13   private transient Counter logTotalConter;
14   private LongCounter logAcc = new LongCounter();
15 
16   @Override
17   public void open(Configuration parameters) throws Exception {
18     MetricGroup metricGroup = getRuntimeContext().getMetricGroup();
19     logTotalMeter = metricGroup.meter("logTotalMeter",
20         new DropwizardMeterWrapper(new com.codahale.metrics.Meter()));
21     logTotalConter = metricGroup.counter("logTotalConter");
22     getRuntimeContext().addAccumulator("logAcc", this.logAcc);
23   }
24 
25 
26   @Override
27   public String map(String log) throws Exception {
28     logTotalConter.inc();
29     logTotalMeter.markEvent();
30     logAcc.add(NumberUtil.LONG_ONE);
31     logMeter.mark();
32     return log;
33   }
34 }

16. Flink中的table API

听了阿里军长的讲解后有所了解,简单做下笔记,以免忘记。table API和SQL有很多相同的优良特性,比如:
声明式-用户只关心做什么,不用关心怎么做;
高性能-支持查询优化,可以获取更好的执行性能;
流批统一-相同的统计逻辑,既可以流模式也可以批模式;
标准稳定-语义遵循SQL标准,不易变动
易理解-所见即所得
比如:
1 // table API
2 tab.groupBy("word").select("word,count(1) as cnt")
3 
4 // SQL
5 SELECT COUNT(1) AS cnt
6 FROM tab
7 GROUP BY word

总的来说,SQL有的功能table API都有,如下图所示

 

 环境配置如下

三种注册表的方式

三种发射表的方式

table API对列操作比较方便,比如

再比如有一张100列的表,选择1到10列怎么操作?

另外,table API的map函数扩展起来也很方便

 

转载于:https://www.cnblogs.com/lcmichelle/p/10742912.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值