Flink

Flink

运行的方式
  • BATCH:批处理

    • 底层基于MR模型

    • 只能用于处理有界的数据

  • STREAM流处理

    • 1、底层基于持续流模型
    • 2、既能处理无界流也可以用于有界流
  • 流批合一

    • 在Flink中同一套DataStream的API既可以用作流处理也可以用作批处理
    // 切分每一行单词
    DataStream<String> wordsDS = lineDS.flatMap((line, collector) -> {
        String[] splits = line.split(",");
        // 遍历每一个单词
        for (String word : splits) {
            // 使用collector将结果数据发送给下游
            collector.collect(word);
        }
        // java中的lambda表达式有时无法自动推断类型,需要手动指定
    }, Types.STRING);
    

sink

DataStream<Tuple2<String, Integer>> clazzCnt = studentDS
                .map(line -> Tuple2.of(line.split(",")[4], 1), Types.TUPLE(Types.STRING, Types.INT))
                .keyBy(kv -> kv.f0)
                .sum(1);

//        clazzCnt.print(); // 本质上也是一种sink,sink到console
FileSource

读取文件的方式

  • 指定一个格式的方式
  • 指定一个路径
  • 通过monitorContinuously来实现对目录的实时监控,将读文件转换无界流进行处理
FileSource<String> fileSource = FileSource.forRecordStreamFormat(
                new TextLineInputFormat()// 指定读取文件的格式
                , new Path("flink/data/word/")
        )
        .monitorContinuously(Duration.ofMillis(5)) // 指定时间间隔监控目录的变化
        .build();

// 使用FileSource
DataStream<String> wordDS2 = env.fromSource(fileSource, WatermarkStrategy.noWatermarks(), "fileSource");
Socket Source

一般用于代码调试及开发

DataStream<String> socketDS = env.socketTextStream("master", 8888);
CollectionSource

基于本地集合的Source

DataStream<String> arrDS = env.fromCollection(arr);
Map

传入一条数据返回一条数据

// 传入处理的逻辑三种方式:

        // 1、使用lambda表示式
        studentDS.map(stu -> stu.split(",")[1], Types.STRING).print();

        // 2、使用匿名内部类
        studentDS.map(new MapFunction<String, String>() {
            @Override
            public String map(String value) throws Exception {
                return value.split(",")[1];
            }
        }).print();

        // 3、使用自定义Function类
        studentDS.map(new MyMapFunction()).print();
        studentDS.map(new NameMapFunction()).print();

        // 通过flatMap提取name
        studentDS.flatMap((stu, out) -> {
            out.collect(stu.split(",")[1]);
        }, Types.STRING).print();

        env.execute();
    }
}

// 自定义类实现Function接口
class MyMapFunction implements MapFunction<String, String> {
    @Override
    public String map(String value) throws Exception {
        return value.split(",")[1];
    }
}
FlatMap

传入一条数据返回N条数据

arrDS.flatMap(new FlatMapFunction<String, String>() {
    /**
     * 传入一条数据flatMap方法就会执行一次
     */
    @Override
    public void flatMap(String value, Collector<String> out) throws Exception {
        for (String word : value.split(",")) {
            out.collect(word);
        }
    }
}).print();
filter

用于过滤,根据方法返回布尔值进行过滤

返回True则保留数据

返回False则返回过滤数据

DataStream<String> clazz = studentDS
                .filter(new FilterFunction<String>() {
                    @Override
                    public boolean filter(String value) throws Exception {
                        // 分别提取班级以及性别
                        String[] splits = value.split(",");
                        String clazz = splits[4];
                        String gender = splits[3];

//                        System.out.println(clazz);
//                        System.out.println(gender);

                        return clazz.startsWith("文科") && "女".equals(gender);
                    }
                });

​ Flink中的算子不是懒执行的,不需要action算子触发

​ 统一由evn.execute()触发Flink任务的执行

keyby

进行流上的分组

让相同key的数据能够进入同一个线程对应的Task中进行处理

同一个Task中也会有不同的key

DataStream<Tuple2<String, Integer>> kvDS = lineDS.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
    @Override
    public void flatMap(String value, Collector<Tuple2<String, Integer>> out) throws Exception {
        for (String word : value.split(",")) {
            out.collect(Tuple2.of(word, 1));
        }
    }
});

按照Key进行分组,默认使用Hash分组的原理

KeyedStream同样也为DataStream的子类

它是在DS的基础之上增加了聚合类一些操作,例如:max、min、sum等

Ruduce

将数据切分,一个单词变成一行数据并转化成KV格式

DataStream<Tuple2<String, Integer>> sumDS = grpDS.reduce(new ReduceFunction<Tuple2<String, Integer>>() {
    /**
     * 如果第一条数据进来,则不会触发reduce方法的执行
     * 如果第两条数据进来,则一条赋给value1,另一条赋给value2,就会执行reduce方法,返回一个计算的结果
     * 如果第三条数据进来,则上一次的计算结果会赋给value1,进来的这条数据赋给value2,触发reduce方法执行并计算新的结果
     * 以此类推
     *
     * 由于会使用上一次的计算结果,故这是一个有状态的操作
     * @param value1
     * @param value2
     * @return
     * @throws Exception
     */
    @Override
    public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception {
        System.out.println(value1);
        System.out.println(value2);
        // 实现累加的聚合操作
        return Tuple2.of(value1.f0, value1.f1 + value2.f1);
    }
});
union

将多个DS合并成一个DS

ArrayList<String> arr = new ArrayList<>();
arr.add("java,scala,python");

DataStream<String> arrDS01 = env.fromCollection(arr);
DataStream<String> arrDS02 = env.fromCollection(arr);
DataStream<String> unionDS = arrDS01.union(arrDS02);
proctime

间隔N秒统计单词的数量,需要使用滚动窗口

kvDS.keyBy(kv -> kv.f0)                .window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
.sum(1)
.print();

每隔ns统计最近10s内的单词数量
需要使用滑动窗口
适用榜单的统计
需要指定两个时间:窗口的大小、滑动的时间
当窗口大小 等于 滑动时间时,可以视为滚动窗口
当窗口大小 大于 滑动时间时,可以视为滑动窗口
当然没有窗口大小 小于 滑动时间 这种情况

kvDS.keyBy(kv -> kv.f0)       .window(SlidingProcessingTimeWindows.of(Time.seconds(10), Time.seconds(5)))
        .sum(1)
        .print();
env.execute();
eventTime

当并行度不为1时,Task的数量会大于1的,所以相当于有多个Task在并行执行
所以Task与Task之间也是需要进行水位线对齐的
将并行度设为1,那就不会存在Task之间水位线对不齐的问题,因为只有一个Task
在真实的场景中,由于数据量是远超过并行度的,所以Task之间对其水位线是相对更容易的

DataStream<Tuple2<String, Long>> assDS = wordTimeDS
                .assignTimestampsAndWatermarks(
                        WatermarkStrategy
                                // 1、使用数据中最大的时间作为水位线
//                                .<Tuple2<String, Long>>forMonotonousTimestamps()
                                // 2、将水位线前移5s,解决数据延时到达的问题
                                // 前移的太多就会导致整体任务延时较大
                                .<Tuple2<String, Long>>forBoundedOutOfOrderness(Duration.ofSeconds(5))
                                // 告诉flink,数据中哪部分作为时间戳,即使用事件时间
                                .withTimestampAssigner(TimestampAssignerSupplier.of((kv, ts) -> kv.f1)
                                ));
Window
Flink的窗口分为三类:
1、基于时间的窗口
        基于事件时间:
                滑动:SlidingEventTimeWindows
                滚动:TumblingEventTimeWindows
        基于处理时间:
                滑动:SlidingProcessingTimeWindows
                滚动:TumblingProcessingTimeWindows
2、基于会话的窗口
        基于事件时间:EventTimeSessionWindows
        基于处理时间:ProcessingTimeSessionWindows
3、基于计数的窗口:可以直接在KeyBy之后直接.出来
    滑动:
    滚动:
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值