2023大数据面试总结

文章目录

Hadoop

1. 请说下HDFS读写流程


https://www.yuque.com/wangzhiwuimportbigdata/da20y0/ekwkul#Bb3na

2. Secondary NameNode了解吗?他的工作机制是怎样的?

3. Secondary NameNode 不能恢复NameNode的全部数据,那如何保证NameNode数据存储安全?

4.

5.

6.

7.

8.

Flink(SQL相关后面专题补充)

1.

2. Flink SQL API State TTL 的过期机制是 onCreateAndUpdate 还是 onReadAndWrite?

  1. 结论:Flink SQL API State TTL 的过期机制目前只支持 onCreateAndUpdate,DataStream API 两个都支持。
  2. 剖析:
    • onCreateAndUpdate:是在创建State和更新State时【更新StateTTL】
    • onReadAndWrite:是在访问State和写入State时【更新StateTTL】
  3. 实际踩坑场景:Flink SQL Deduplicate 写法,row_number partition by user_id
    order by proctimeasc,此SQL最后生成的算子只会在第一条数据来的时候更新
    state,后续访问不会更新stateTTL,因此state会在用户设置的stateTTL时间之后过期。

3. watermark 到底是干啥的?应用场景?

  • 标识flink任务的事件时间进度,从而能够推动事件时间窗口的触发、计算
  • 解决事件时间窗口的乱序问题

4. 一个flink任务中可以既有事件时间窗口,又有处理时间窗口吗?

结论:一个 Flink 任务可以同时有事件时间窗口,又有处理时间窗口。

两个角度说明:

  1. 我们其实没有必要把一个Flink任务和某种特定的时间语义进行绑定。对于事件时间窗口来说,我们只要给它watermark,能让watermark一直往前推进,让事件时间窗口能够持续触发计算就行。对于处理时间来说更简单,只要窗口算子按照本地时间按照固定的时间间隔进行触发就行。无论哪种时间窗口,主要满足时间窗口的触发条件就行。
  2. Flink的实现上来说也是支持的。Flink是使用一个叫做TimerService的组件来管理
    timer的,我们可以同时注册事件时间和处理时间的timer,Flink会自行判断timer是否满足触发条件,如果是,则回调窗口处理函数进行计算。

5.

6. Flink 提交作业的流程?以及与yarn的互动?

7. Operator Chains了解吗?

为了更高效地分布式执行,Flink 会尽可能地将operator的subtask链接(chain)在一起形成task。每个task在一个线程中执行。

将operators链接成task是非常有效的优化:它能减少线程之间的切换,减少消息的序列化/反序列化,减少数据在缓冲区的交换,减少了延迟的同时提高整体的吞吐量。这就是Operator Chains(算子链)。

8. 10个int以数组的形式保存,保存在什么状态好?VlaueState还是 ListState?存在哪个的性能比较好?

ValueState[Array[Int]] update形式。

ListState[Int]:add形式添加。

对于操控来说ListState方便取值与更改。

按键分区状态(Keyed State)选择ValueState ListState。
算子状态(Operator State)选择ListState。

9. 一个窗口,现在只取第一帧和最后一帧,如何实现?

如果使用process全量聚合函数:

package com.herobin.flink.common;

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;
import org.apache.flink.streaming.api.windowing.time.Time;

public class FlinkDemo {
   
   
    public static void main(String[] args) throws Exception {
   
   
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);

        DataStream<Integer> sourceStream = env.addSource(new SimpleSourceFunction());

        sourceStream
                .map(new MapFunction<Integer, Tuple2<String, Integer>>() {
   
   
                    @Override
                    public Tuple2<String, Integer> map(Integer value) throws Exception {
   
   
                        return Tuple2.of("Key", value);
                    }
                }) // 为了使用 keyed window,我们需要提供一个 key,这里简单地给所有元素赋予相同的 key
                .keyBy(value -> value.f0)
                .timeWindow(Time.minutes(1))
                .process(new MyProcessWindowFunction())
                .print();

        env.execute("Flink Demo");
    }

    public static class MyProcessWindowFunction extends ProcessWindowFunction<Tuple2<String, Integer>, String, String, TimeWindow> {
   
   
        @Override
        public void process(String key, Context context, Iterable<Tuple2<String, Integer>> elements, Collector<String> out) {
   
   
            Integer first = null;
            Integer last = null;

            for (Tuple2<String, Integer> element : elements) {
   
   
                if (first == null) {
   
   
                    first = element.f1;
                }
                last = element.f1;
            }

            out.collect("Window: " + context.window() + " First: " + first + " Last: " + last);
        }
    }

    static class SimpleSourceFunction implements SourceFunction<Integer> {
   
   
        private volatile boolean isRunning = true;
        private int counter = 0;

        @Override
        public void run(SourceContext<Integer> ctx) throws Exception {
   
   
            while(isRunning && counter < Integer.MAX_VALUE) {
   
   
                synchronized (ctx.getCheckpointLock()) {
   
   
                    ctx.collect(counter++);
                }
                Thread.sleep(1000L); // 每秒生成一个整数
            }
        }

        @Override
        public void cancel() {
   
   
            isRunning = false;
        }
    }
}

输出:

1> Window: TimeWindow{
   
   start=1694865120000, end=1694865180000} First: 0 Last: 28
1> Window: TimeWindow{
   
   start=1694865180000, end=1694865240000} First: 29 Last: 8

如果使用reduce窗口聚合函数,可以将数据转化为一个Tuple3类型的结果输出,f0 为 key,f1 为最早的数据,f2 为最晚的数据。(可以将上有数据转为tuple2<时间戳, 数据>的格式,结果的 f1 就等于 value1.f0 < value2.f0 ? value1.f1 : value2.f1)。

public class FlinkDemo {
   
   
    public static void main(String[] args) throws Exception {
   
   
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStream<Tuple3<Integer, Long, Long>> sourceStream = env.addSource(new SimpleSourceFunction())
                .map(value -> new Tuple3<>(value, System.currentTimeMillis(), System.currentTimeMillis()));

        sourceStream
                .keyBy(0)
                .timeWindow(Time.minutes(5))
                .reduce(new MyReduceFunction())
                .print();

        env.execute("Flink Demo");
    }

    public static class MyReduceFunction implements ReduceFunction<Tuple3<Integer, Long, Long>> {
   
   
        @Override
        public Tuple3<Integer, Long, Long> reduce(Tuple3<Integer, Long, Long> value1, Tuple3<Integer, Long, Long> value2) {
   
   
            return new Tuple3<>(
                    value1.f0, // 取任意一个数值,因为它们都是相同的
                    Math.min(value1.f1, value2.f1), // 取最早的时间
                    Math.max(value1.f2, value2.f2)  // 取最晚的时间
            );
        }
    }
}

10. 背压的原理?解决办法?

11. 遇到状态放不下的场景怎么办?

有时候需要求uv,内存或者状态中存过多数据,导致压力巨大,这个时候可以结合 Redis或者布隆过滤器来去重。

注意:布隆过滤器存在非常小的误判几率,不能判断某个元素一定百分之百存在,所以只能用在允许有少量误判的场景,不能用在需要100%精确判断存在的场景。

12. 使用flink统计订单表的GMV(商品交易总额),如果mysql中的数据出现错误,之后在mysql中做数据的修改操作,那么flink程序如何保证GMV的正确性,你们是如何解决?

CDC 动态捕捉MySQL数据变化,实时处理后数据入湖-Hudi,MOR 机制 快速对下游可见。

另:一般也会有离线Job来恢复和完善实时数据。

13. 开窗函数有哪些?

  • Flink SQL:
    • 待补充
  • Flink Stream:
    • ReduceFunction、AggregateFunction:窗口不维护原始数据,只维护中间结果。每次基于中间结果和增量数据进行聚合
    • ProcessWindowFunction:维护全部原始数据,窗口触发时进行全量聚合

14. 没有数据流的时候,窗口存在吗

不存在,没有数据,窗口不产生

15. 1小时的滚动窗口,一小时处理一次的压力比较大想让他5分钟处理一次.怎么办?

自定义触发器,4个方法,一个Close三个用于控制计算和输出 ??? 如何实现???

分段窗口:可以将1小时的窗口分解为多个小窗口(如,12个5分钟的窗口),并在每个小窗口上进行计算。然后,你可以使用windowAll和reduce操作将这些小窗口的结果组合起来,形成原本1小时窗口的结果。

import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.assigners.GlobalWindows;
import org.apache.flink.streaming.api.windowing.triggers.CountTrigger;

public class FlinkDemo {
   
   
    public static void main(String[] args) throws Exception {
   
   
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值