Flink特点

  1. 批流统一
  2. 高吞吐
  3. 低延迟
  4. 保证Eactly-Once
  5. 丰富的编程API

时间语义

时间语义 是flink中用于时间推进和时间判断的机制
时间推进和时间判断 以什么为标准 就产出了两种不同的时间语义

  • 以processing time为依据 则叫做处理时间语义
  • 以event time为依据 则叫做事件时间语义

时间语义的设计意义
  1. process(EventLog eventlog){
  2. Long eventTime = eventLog.getTimestamp();
  3. Long processTime = System.currentMillimise()
  4. //用户完全可以自己根据需求中的时间定义来进行相应的计算
  5. }

处理时间(processing time)语义

Processing Time 是指数据被Operator处理时所在机器的系统时间
处理时间遵循客观世界中时间的特性:单调递增 恒定速度 永不停滞 永不回退

事件时间(event time)语义

Event Time 是指在数据本身的业务时间(如用户行为日志中的用户行为时间戳):
Event Time 语义中 时间的推进完全由流入flink系统的数据来驱动:
数据中的业务时间推进到哪 flink就认为自己的时间推进到了哪:
它可能停滞 也可能速度不恒定 但也一定是单调递增不可回退

并行度相关概念和API

  • 用户通过算子api所开发的代码 会被flink任务提交客户端解析成jobGraph
  • 然后 jobGraph提交到集群JobManager 转化成ExecutionGraph(并行化后的执行图)
  • 然后 ExecutionGraph中的各个task会以多并行实例(subTask)部署到taskmanager上执行
  • subTask运行的位置是taskmanager所提供的槽位(task slot) 槽位简单理解就是线程

提示:

  • 一个算子的逻辑 可以封装在一个独立的task中(可以有多个运行时实例:subTask);
  • 也可以把多个算子的逻辑chain在一起后封装在一个独立的task中(可以有多个运行实例)
  • 同一个task的不同运行实例 必须放在不同的task slot上运行
  • 同一个task slot 可以运行多个不同task的各一个并行实例
  • setParallelism 设置算子的并行度
  • slotSharingGroup 设置算子的槽位共享组
  • disableChaining 对算子禁用前后链合并
  • startNewChain 对算子开启新链(即禁用算子前链合并)

分区算子:用于指定上游task的各并行subtask与下游task的subtask之间如何传输数据;

  • 设置数据传输策略时 不需要显式指定partitioner 而是调用封装好的算子即可
    • dataStream.global();全部发往第1个task
    • broadcast广播
    • forward上下游并发度一样时一对一发送
    • shuffle随机均匀分配
    • rebalance Round-Robin(轮流分配)
    • recale Local Round-Robin(本地轮流分配)
    • partitionCustom 自定义单播
    • keyBy 根据key的hashcode来进行hash分发
  • 默认情况下 flink会优先使用REBALANCE分发策略

Flink Transformation

  • Map算子:对DataStream中的数据依次取出来进行处理(做映射)
    • 底层调用的是transformation方法 传入Operator名称(Map 返回数据类型和StreamMap并将自定义的计算逻辑传入到StreamMap)
    • StreamMap类实现OneInputStreamOperator接口 必须重写processElement方法 数据是封装在StreamRecord 使用OutPut将处理完的数据输出
    • StreamMap类还实现了AbstractUdfStreamOperator接口 用来约束该类传入的计算逻辑的类型(接口的类型) 只能传入MapFunction类型
  • Filter算子 对数据过滤 保留计算逻辑返回为true的数据
    • 底层调用的是transform方法 传入Operator名称(Fileter) 返回数据类型和StreamMap实例并将自定义的过滤逻辑传入到StreamFilter
    • StreamMap类实现了OneInputStreamOperator接口 必须重写processElement方法 应用过滤逻辑 返回true就使用OutPut输出
    • StreamMap类还实现了AbstractUdfStreamOperator接口 用来约束该类传入的计算逻辑的类型(接口的类型),只能传入FilterFunction类型
  • FlatMap算子 对数据进行扁平化映射 可以 输出0到多条数据 输出数据用Collector的collect方法
    • 底层调用的是transform方法 传入Operator名称(FlatMap) 返回数据类型和StreamFlatMap实例并将自定义的过滤逻辑传入到StreamFlatMap
    • StreamMap类实现了OneInputStreamOperator接口 必须重写processElement方法 应用计算逻辑 如果一条返回多条 用Collector结合for循环将数据输出
    • StreamMap类还实现了AbstractUdfStreamOperator接口 用来约束该类传入的计算逻辑的类型(接口的类型) 只能传入FlatMapFunction类型
  • KeyBy按照key的hash对数据进行分区
    • 可以保证key相同的一定进入到一个分区内 但是一个分区内可以有多key的数据
    • 是对数据进行实时的分区 不是上游发送给下游 而是将数据写入到对应的channel的缓存中 下游到上游实时拉取
    • KeyBy底层是new KeyedStream 然后将父DataStream包起来 并且传入keyBy的条件(keySelector)
    • 最终会调用KeyGroupStreamPartitioner的selectChannel方法 将KeyBy的条件返回值传入到该方法中
      • 步骤
        • 先计算key的HashCode值(有可能会是负的)
        • 将key的HashCode值进行特殊的hash处理 MathUtils.murmurHash(keyHash) 一定返回正数 避免返回的数字为负
        • 将返回特殊的hash值模除以默认最大并行的 默认是128 得到keyGroupId
        • keyGroupId * parallelism(下游的并行度) / maxParallelism(默认最大并行) 返回分区编号
    • 优点:可以将数据尽量均匀分配到多个分区 并且避免key的hashCode为负数
    • 注意: 1如果将自定义POJO当成key 必须重写hashcode方法 不能将数组当成keyBy的key
  • Reduce将KeyedStream数据进行聚合
    • 传入ReduceFunction 输入跟输出的类型保持一致
    • 如果这个key在该分区中第一次出现 不会调用自定义的reduce方法
    • 底层调用的是StreamGroupReduceOperator的processElement方法
    • 将初始值或累计的中间结果以ValueState方法保存起来 如果状态不为null 然后通过多态的方式调用自定义的reduce方法 将reduce方法的返回值在更新到ValueState
    • 然后使用OutPut将数据输出
  • Sum对KeyedStream的数据进行聚合
    • 底层先调用的是aggregate方法 传入SumAggregator 然后再调用reducefangfa
    • 在reduce方法中 会根据数据的类型 调用具体的相加的方法 例如 IntSum LongSum
    • Sum只能对数字类型的数据进行相加 有六种实现
  • Min Max
    • 只会返回KeyBy的字段和最小值 最大值 如果还有其他字段 返回的是第一次出现的值
    • 底层也是调用reduce方法
  • MinBy MaxBy
    • 不但返回KeyBy的字段 还会返回最小值或最大值 如果有多个字段 还会返回最小值 或最大值所在数据的全部字段
    • 底层也是调用reduce方法
  • Union多个类型一样的DataStream合并到一起 使用同样的方式进行处理
    • 可以union一到多个DataStream
    • 如果自己Union自己 是将数据double
    • Union后的DataStream没用指定分区 分区的数量为默认的并行度
  • Connect可以将两个相同或不同类型的数据流包装到一起 得到一个新的数据流
    • 分别调用两个方法对两个数据流中的数据进行操作
    • 重要:可以让两个数据流共享状态
    • 可以实现高级的功能 比如广播状态 inverval join
  • Iterate用来做迭代计算 类似一个分布式for循环
    • 可以指定一个更新模型 对输入的数据进行运算
    • 还可以指定两个过滤判断条件
      • 继续迭代的条件
      • 退出迭代计算 输出数据的条件
  • Project投影
    • 功能类似于map 选择出你想要的数据
    • 只能针对Tuple类型的DataStream
    • 功能是取出想要的全部或部分字段 而且还可以改变字段的顺序