初识Flink(Flink学习之路二)

Flink DataStream API 编程

很久没更新博客了,这半年多来,公司的事情也比较多,没多少时间学习,又赶上疫情,都是在家办公,慢慢感觉自己要颓废下去了,赶紧抽个周末让自己学点东西。

word count

每个分布式计算模型都是从Word count 开始的,学习Flink肯定也不例外,下面这个程序收集socket 端口的输入,统计5s内出现的单词书,并输出到控制台。

object ApplicationDemo {
  def main(args: Array[String]): Unit = {
    //获取执行环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    //    val data: DataStream[String] = FlinkConnectKafka.getKafkaSource(env, "flink-kafka-topic")
    //指定数据源
    val data = env.socketTextStream("localhost", 9999)

    val result: DataStream[(String, Int)] = data.flatMap {
      _.toLowerCase.split(" ") filter {
        _.nonEmpty
      }
    }
      .map(x => (x, 1))
      .keyBy(0)
      .timeWindow(Time.seconds(5))
      .sum(1)
    result.print()

    env.execute("Flink Test")
  }

}

一段最简单的Flink 代码。
数据的流向通过 Data Source ==> Transformation ==> Data Sink

Data Source

一、内部数据源

  • 文件 数据源
    通过readTextFile(path)、readFile(fileInputFormat, path) 、readFile(fileInputFormat, path, watchType, interval, pathFilter)内置的方法获取数据
  • Socket 数据源
    通过socketTextStream获取数据
  • 集合数据源
    通过
    fromCollection(Seq)、
    fromCollection(Iterator)、
    fromElements(elements: _*)、
    fromParallelCollection(SplittableIterator)、
    generateSequence(from, to) 获取数据

二、外部数据源
实现SourceFunction的自定义数据源,通过addSource()注册使用。

Data Sink

一、内部数据接收

  • writeAsText()
  • writeAsCsv(…)
  • print()/ printToErr()
  • writeUsingOutputFormat()
  • writeToSocket

二、外部数据接收
实现SinkFunction 的自定义数据接收,通过addSink()注册使用。

流连接器(connector)

预定义的source和sink

  • Apache Kafka (source/sink)
  • Apache Cassandra (sink)
  • Amazon Kinesis Streams (source/sink)
  • Elasticsearch (sink)
  • Hadoop FileSystem (sink)
  • RabbitMQ (source/sink)
  • Apache NiFi (source/sink)
  • Twitter Streaming API (source)
  • Google PubSub (source/sink)

Flink 还有些一些额外的连接器通过 Apache Bahir 发布, 包括:

  • Apache ActiveMQ (source/sink)
  • Apache Flume (sink)
  • Redis (sink)
  • Akka(sink)
  • Netty (source)

注:Apache Bahir 提供对分布式分析平台(如 Apache Spark 和 Apache Flink )的扩展,通过多种流连接器和 SQL 数据源扩展其覆盖范围。

通过下面代码创建一个kafka消费者

val properties = new Properties()
properties.setProperty("bootstrap.servers", "localhost:9092")
// 仅 Kafka 0.8 需要
//properties.setProperty("zookeeper.connect", "localhost:2181")
properties.setProperty("group.id", "test")
//kafka1.0.0版本之后使用FlinkKafkaConsumer
stream = env
    .addSource(new FlinkKafkaConsumer[String]("topic", new SimpleStringSchema(), properties))
    .print()

kafka 是我工作中用到的最常见的上下游组件,在这也就只列举一个创建kafka consumer的例子了。

Transformation

Transformation 操作是DataStream生成新的DataStream的过程,在转化过程中,每个操作类型被定义成不同的Operator;DataStream的操作可以分为Single-DataStream、Multi-DataStream、物理分区三类。

  1. Single-DataStream
    对单个DataStream数据集元素进行逻辑处理
    (1)、Map(取一个元素并产生一个元素)
    通过用户定义的MapFunction对DataStream进行处理
    (2)、FlatMap(取一个元素并产生零个,一个或多个元素)
    通过用户自定义的FlatMapFunction对DataStream进行处理
    (3)、Filter(对元素进行过滤)
    通过用户自定义的FilterFunction对DataStream进行处理
    (4)、KeyBy
    从逻辑上将DataStream划分为不相交的分区。具有相同key的所有数据都分配给同一分区
    (5)、Reduce(对相同key值的数据进行逻辑运算)
    通过用户自定义的ReduceFunction对DataStream进行处理
    (6)、Aggregations(对相同key值的数据进行逻辑运算)
    封装了sum、min、minBy、max、maxBy等聚合函数
  2. Multi-DataStream
    (1)、Union
    将两个或多个流数据集合并成一个、需保证数据格式一致
    (2)、Connect、CoMap、CoFlatMap
    将两个或多个不同数据类型的流数据集合并成一个;CoMapFunction、CoFlatMapFunction在Paralism 大于1的情况下会产生乱序。
    (3)、Split
    按照一定的规则对DataStream 进行拆分,形成两个SplitStream
    (4)、Select
    从拆分流中选择一个或多个流。
    (5)、Iterate
    通过每一次迭代计算,将计算结果反馈到下一次的迭代计算中。
  3. 物理分区
    (1)、Random partition(随机分区)
    随机将元素分配到下游分区,相对均衡,容易失去原有的数据分区结构。
dataStream.shuffle()

(2)、Round-robin partitioning
通过循环的方式对数据集中的部分进行重分区,解决数据倾斜

dataStream.rebalance()

(3)、Rescaling partitioning
将元素循环地分区到下游操作的子集;在上游并发度和下游并发度成倍数关系,Rescaling 的效果优于Round-robin

dataStream.rescale()

(4)、Broadcasting
将元素广播到每个分区。

dataStream.broadcast()

(5)、Custom partitioning(自定义分区)
用户定义的分区程序为每个元素选择目标任务。继承Partitioner类,实现partition方法即可

dataStream.partitionCustom(partitioner, 0)

今天介绍了DataStream 的整个编程模型,从source 到transformation 到sink整个完整的链路;今天就到这吧。还是那句话,作为一个菜鸟,如果各位大佬在看博客的过程中发现什么问题,欢迎随时批评指正。

你可能感兴趣的:(Flink)