1. Flink、Storm、Sparkstreaming对比
storm------ ---------At-least-once----Record Acks-------无状态管理-------- 低延迟-----------高吞吐sparkstreaming-----Exectly-once-------RDD Checkpoint-----基于DStream-----中等延迟-----高吞吐Flink-----------------Exectly-once------ Checkpoint-----------基于操作----------低延迟-------高吞吐
2. Flink DataStream API基本算子
3. Flink On Yarn
- 提高集群机器的利用率;
- 一套集群,可以同时执行MR任务,Spark任务,Flink任务。
- 一开始在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(分布式缓存)
- 原理
- 用法
用法一:注册一个文件
1 env.registerCachedFile(“hdfs:///path/to/yout/file","hdfsfile");
用法二:访问数据
1 File myFile = getRuntimeContext().getDistributedCache().getFile("hdfsFile");
7. State
8. Checkpoint
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重启策略
10. 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
- 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并行度;
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数量
14. Flink传递参数给函数
-
使用构造函数方式
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 }
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);
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
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
声明式-用户只关心做什么,不用关心怎么做;高性能-支持查询优化,可以获取更好的执行性能;流批统一-相同的统计逻辑,既可以流模式也可以批模式;标准稳定-语义遵循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函数扩展起来也很方便