Flink学习笔记

《Google FileSystem》->HDFS
《Google BigTable》 -> HBase
《Google MapReduce》-> Hadoop
UDF、窗口、状态三大模块

一般遵循先分流,再开窗,后聚合的思路
1.spark中的Driver除了调度还会负责一些工作,比如job切分,封装task->TaskScheduler等等
   flink中的JobMaster只负责调度
2.使用webUI提交jar包一般是使用分发器执行的,Dispatcher在架构中可能并不是必需的,这取决于应用提交运行的方式。
3.物理执行图并不是真正的数据结构,只是想象出的数据流通的过程
4.并行度(Parallelism)要小于等于任务槽的数量,最大并行度取决于算子中设置的最大并行度
    任务槽的数量一般设置为这台机器上的CPU核数
5.作业管理器(JobManager) -> Driver  任务管理器(TaskManager)(进程) -> Executor
    不同于Spark的是,TaskManager的数量就是实际布置机器的数量,而spark中是可以在同一个机器上运行多个executor的
6.Flink 采用了一种称为任务链的优化技术,可以在特定条件下减少本地通信的开销。
    为了满足任务链的要求,必须将两个或多个算子设为相同的并行度,并通过本地转发(local forward)的方式进行连接
    类似于java中窄依赖的算子处于同一个task
7.
    基本转换算子;map,filter,flatmap
        操作在流上每一个元素
    
8.    键控流转换算子:keyBy
    keyBy会把相同key的元素分发到同一个任务槽中,不同的key对应的数据可能在同一个任务槽,同key的数据一定在同一个任务槽
    (滚动聚合算子由KeyedStream调用,并生成一个聚合以后的DataStream,例如:sum,minimum,maximum。
    一个滚动聚合算子会为每一个观察到的key保存一个聚合的值(维护一个状态变量)。针对每一个输入事件,算子将会更新保存的聚合结果,并发送一个带有更新后的值的事件到下游算子。
    滚动聚合不需要用户自定义函数,但需要接受一个参数,这个参数指定了在哪一个字段上面做聚合操作。)
    DataStream API提供了以下滚动聚合方法:
    sum(在输入流上对指定的字段做滚动相加操作。),min,max,minby,maxby(在输入流上针对指定字段求最大值,并返回包含当前观察到的最大值的事件。)
    
9.  多流转换算子
    union:事件合流的方式为FIFO方式。操作符并不会产生一个特定顺序的事件流。union操作符也不会进行去重。每一个输入事件都被发送到了下一个操作符。
    connect:注意直接connect两条流没有意义,要把相同key的流联合在一起处理,类似于join;stream1.keyBy(_._1).connect(stream2.keyBy(_._1))

10. 分布式转换算子
    shuffle  随机向下游算子的并行任务中分配数据
    rebalance(round-robin)  负载均衡将输入流平均分配到后续的并行任务中(轮询)
    rescale(round-robin) 与rebalance区别,仅仅针对每一个任务和下游算子的一部分并行任务建立通信通道,而rebalance是对所有发送者和所有接收者之间建立通信
    broadcast 将输入流的所有数据复制并发送到下游算子的所有并行任务中去。
    Global 方法将所有的输入流数据都发送到下游算子的第一个并行任务中去。这个操作需要很谨慎,因为将所有数据发送到同一个task,将会对应用程序造成很大的压力。
    custom  当Flink提供的分区策略都不适用时,我们可以使用partitionCustom()方法来自定义分区策略。
                这个方法接收一个Partitioner对象,这个对象需要实现分区逻辑以及定义针对流的哪一个字段或者key来进行分区。
11.一般不设定全局并行度,而是对各个算子设置并行度;并行度是动态概念,任务槽数量是静态概念。并行度<=任务槽数量。一个任务槽最多运行一个并行度。
12.
    时间窗口
        滚动时间窗口  .timeWindow(Time.seconds(15))
        滑动时间窗口  .timeWindow(Time.seconds(15),Time.seconds(5))
        会话窗口 .window(EventTimeSessionWindows.withGap(Time.minutes(10))
        全局窗口(global window)(从流的第一条元素一直到最后)

    计数窗口(count window)
        滚动计数窗口(tumbling count window)    .countWindow(5)
        滑动计数窗口    .countWindow(10,2)

        .trigger() —— 触发器
        定义 window 什么时候关闭,触发计算并输出结果
        .evictor() —— 移除器
        定义移除某些数据的逻辑
        .allowedLateness() —— 允许处理迟到的数据
        .sideOutputLateData() —— 将迟到的数据放入侧输出流
        .getSideOutput() —— 获取侧输出流
    
13.窗口函数可以分为两类
    增量聚合函数(incremental aggregation functions)
        每条数据到来就进行计算,保持一个简单的状态
        ReduceFunction, AggregateFunction
    全窗口函数(full window functions)
        先把窗口所有数据收集起来,等到计算的时候会遍历所有数据
        ProcessWindowFunction
        
14. //设置时间语义为事件时间(即水位线是事件时间进展的唯一度量,判断定时器是否到点是判断的水位线)
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)        
     //设置水位线时间为60s,系统默认是200ms
    env.getConfig.setAutoWatermarkInterval(60000)    
    
15.影响水位线的因素:1.延迟时间(经验值5s) 2.更新水位线时间(默认200ms)        
        只要是事件时间,并且设置了延迟时间,就有可能存在迟到元素,且迟到元素仅存在于事件时间语义中
        迟到元素:来的数据时间戳小于水位线
16. //分配时间戳和水位线一定在keyby之前进行
      //水位线 = 系统观察到的元素携带的最大时间戳 - 最大延迟时间    
      //抽取时间戳的单位一定要是ms
17.watermark的引入
    -对于排好序的数据,不需要延迟触发,可以只指定时间戳
      stream.assignAscendingTimestamps(_.timestamp * 1000)
    -未排序的数据,可能存在延迟,一般调用 assignTimestampAndWatermarks 方法,传入一个 BoundedOutOfOrdernessTimestampExtractor,就可以指定 watermark 
      可以自定义MyAssigner,继承AssignerWithPeriodicWatermarks(有周期规律)/AssignerWithPunctuatedWatermarks(没有周期规律)

18.合并后的stream的水位线为所有流的最小值

19.//初始化一个状态变量,用来保存最近一次的温度值
    //懒加载,惰性赋值 lazy val lastTemp = getRuntimeContext.getState(new ValueStateDescriptor[Double]("last-temp",Types.of[Double]))    

20.迟到数据处理策略
    1.丢弃(默认)
    2.发送到侧输出流
    3.使用迟到元素更新窗口计算结果    

21.基于时间的双流join(inner join)    
     -基于间隔的join(目前只支持事件时间和Inner Join语义) ,无法发出未匹配成功的事件  stream1.interval(stream2)  -> between(Time1,Time2)
     -基于窗口的join  JoinFunction  : apply(new JoinFunction) 
        
22.状态变量
        算子状态(Operator State):算子状态的作用范围限定为算子任务
            列表状态(List state)
                将状态表示为一组数据的列表
            联合列表状态(Union list state)
                也将状态表示为数据的列表。它与常规列表状态的区别在于,在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复
            广播状态(Broadcast state)
                如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应用广播状态。

        键控状态(Keyed State):根据输入数据流中定义的键(key)来维护和访问
            值状态(Value state)
                将状态表示为单个的值
            列表状态(List state)
                将状态表示为一组数据的列表
            映射状态(Map state)
                将状态表示为一组 Key-Value 对
            聚合状态(Reducing state & Aggregating State)
                将状态表示为一个用于聚合操作的列表

23. 设置检查点,检查点是自动保存自动恢复的,且不覆盖
    env.enableCheckpointing(10000L)
    env.setStateBackend(new FsStateBackend())
    
    从检查点中恢复数据一般要求source源可以持久化并且有偏移量,比如kafka
    检查点一致性通过检查点屏障实现
    
    这种检查点的保存和恢复机制可以为应用程序状态提供“精确一次”(exactly-once)的一致性,
    因为所有算子都会保存检查点并恢复其所有状态,这样一来所有的输入流就都会被重置到检查点完成时的位置
    sparkStreaming是在stage结束以后做检查点,而flink可以在算子没计算完时就做检查点
    
    状态后端的主要作用包括在每一个TaskManager节点上存储和管理状态,将状态进行远程备份两个部分。
    FLink 目前提供了三种状态后端,分别是:

    MemoryStateBackend
    对于状态管理,MemoryStateBackend直接将State对象存储到TaskManager的JVM堆上,如MapState会被存储为一个HashMap对象。can suffer from garbage collection pauses because it puts many long-lived objects on the heap.
    对于远程备份,MemoryStateBackend会将State备份到JobManager的堆内存上,这种方式是非常不安全的,且受限于JobManager的内存大小。
    FsStateBackend
    对于状态管理,FsStateBackend与MemoryStateBackend一样,将State存储到TaskManager的JVM堆上。
    对于远程备份,FsStateBackend会将State写入到远程的文件系统,如HDFS中。
    RocksDBStateBackend
    对于状态管理,RocksDBStateBackend将state存储到TaskManager节点上的RocksDB数据库实例上。
    对于远程备份,RocksDBstateBackend会将State备份到远程的存储系统中。
24 保存点(savepoint),手动保存和恢复.
    

25.yarn
    job模式:作业提交给resourcemanager,类似于spark的作业提交模式
    session模式:flink有一个稳定运行的集群,作业提交给dispatcher,分配给jobmanager

26.CEP
    val pattern = Pattern
                    .begin[T]("name")
                    .where()
                    .next("name")
                    .where
                    .within(duration)
    val patternStream: PatternStream[T] = CEP.pattern(stream,pattern)
    val detectStream = patternStream.select(orderTimeOutputTag)(timeoutFunc)(selectFunc)

    注意:CEP前的数据一般需要keyBy
27.建议DataStream => Table(动态表) => CRUD(增删改查) => Table(动态表)===toAppenStream/RestractStream==> DataStream => Sink    
    
    table = tableEnv.fromDataStream(stream,fields)
    DataStream  =  table.window.gorupBy.select.toAppenStream/RestractStream //table Api写法
    tableEnv.createTemporaryView("name",table)
    DataStream = tableEnv.sqlQuery("sql").toAppenStream/RestractStream
    
28.
    flinksql中的函数
    标量函数(Scalar Functions)    --UDF
        标量函数的行为由求值方法决定,求值方法必须公开声明并命名为 eval
    表函数(Table Functions)  -- UDTF
        表函数的行为由其求值方法决定,求值方法必须是 public 的,并命名为 eval
    聚合函数(Aggregate Functions) --UDAF  区别于窗口的AggreagateFunction org.apache.flink.table.functions.AggregateFunction  
        要求必须实现的方法:
            createAccumulator()
            def accumulate() 该方法是需要def的,没有override
            getValue()

    表聚合函数(Table Aggregate Functions) -聚合的结果是一个多行多列的表
        Table AggregationFunction 要求必须实现的方法:
            createAccumulator()
            accumulate()  该方法是需要def的,没有override
            emitValue() 该方法是需要def的,没有override

29.筛选超大量数据,可以使用布隆过滤器(爬虫,区块链,大数据)org.apache.flink.shaded.guava18.com.google.common.hash.BloomFilter
    import java.lang.{Long => Jlong}   , BloomFilter[JLong]
    声明过滤器 BloomFilter.create(Funnels.longFunnel()

30.Flink关于kafka的offset维护在了HDFS中,而spark关于kafka是需要自己处理的

Latency Numbers every Programmer should know

Flink提供了8个Process Function:
-ProcessFunction  处理的是没有keyby的流
-KeyedProcessFunction 处理分组(keyby)后的数据,且一条一条处理;重写processElement方法
-CoProcessFunction   处理联合数据(connect),一般先connect->keyby->process  是全外连接
-ProcessJoinFunction/JoinFunction //处理join后的流
-BroadcastProcessFunction
-KeyedBroadcastProcessFunction
-ProcessWindowFunction  分流(keyby)开窗以后的流,整个窗口处理
-ProcessAllWindowFunction    没有分流但是开窗的流    
-AggregateFunction 窗口的增量聚合,但是逐条处理        
-Trigger:窗口聚合函数的底层实现,可自由控制窗口计算的时机 (应用较少)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值