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:合并两个流,两个流的类型可以不同;
CoMap、CoFlatMap:对于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. DataStream API之partition
- 随机分区
1 dataStream.shuffle();
- 重分区,消除数据倾斜
1 dataStream.rebalance();
- 自定义分区
1 dataStream.partitionCustom(partiitoner,"somekey");
- 广播分区:把元素广播所有分区,会被重复消费
1 DataStream.broadcast();
5. Flink Distributed Cache(分布式缓存)
- 原理
类似Hadoop,可以在并行函数比如map中读取本地文件或则HDFS文件,Flink自动将文件复制到所有taskmanager节点的本地文件系统。
- 用法
用法一:注册一个文件
1 env.registerCachedFile(“hdfs:///path/to/yout/file","hdfsfile");
用法二:访问数据
1 File myFile = getRuntimeContext().getDistributedCache().getFile("hdfsFile");
6. State
为了实现at least once和exactly once,flink引入了state和checkpoint;state一般将数据保存在
堆内存中,而checkpoint是每隔一段时把state数据
持久化存储了,当失败时可以恢复。
7. 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程序被取消后,会保留检查点数据
8. Flink重启策略
Flink中常用重启策略:
固定时间(Fixed delay);
失败率(Failure rate)【checkpoint机制默认策略】;
无重启(No start)【
默认】
9. 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等
10. Time
针对Stream数据流中的时间,可以分为以下三种:
- Event Time:日志产生的时间;
- Ingestion Time:事件从kafka等取出来,进入Flink的时间;
- Processing Time:事件被处理的时间,例如达到窗口处理的时间等。【默认】
11. Flink并行度
Flink中每个TaskManager为集群提供slot,slot数量与每个节点的可用CPU核数成比例,slot上启动进程,进程内有多个线程。
可以通过setParallelism设置线程的并行度。
12. 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 ...