Flink学习6-常见问题

Flink学习6-常见问题

Flink系列文章

1 编译报错

flink no implicits found for parameter evidence9

  • 解释:缺少隐式转换。
  • 解决:在代码上加入import org.apache.flink.api.scala._即可

Error:(72, 8) value build is not a member of ?0

使用flink 1.10.0时报错,代码如下:

val sink: StreamingFileSink[String] = StreamingFileSink
      .forRowFormat(new Path(parameter.get("hdfs-path", "hdfs://xxx"))
        , new SimpleStringEncoder[String]("UTF-8"))
      .withBucketAssigner(new DateTimeBucketAssigner)
      .withRollingPolicy(OnCheckpointRollingPolicy.build())
      .build

报错详细信息:

Error:(72, 8) value build is not a member of ?0
possible cause: maybe a semicolon is missing before `value build'?
      .build

参见Change to StreamingFileSink in Flink 1.10

这是一个bug,已经在flink 1.10.1中解决。

2 启动报错

2.1 ClassCastException: cannot assign instance

使用bin/flink run -m yarn-cluster ...方式提交flink作业时,报错如下:

Caused by: java.lang.ClassCastException: cannot assign instance of org.apache.commons.collections.map.LinkedMap to field org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumerBase.pendingOffsetsToCommit of type org.apache.commons.collections.map.LinkedMap in instance of org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer010

经查,是因为
。我们提交的Flink作业,相关的class被动态加载。

可参考X cannot be cast to X exceptions

是因为多个不同版本的org.apache.commons.collections.map.LinkedMap被不同的CalssLoader加载,而这些类被尝试转换为对方。

解决方法是编辑conf/flink-conf.yaml,设置classloader.resolve-order: parent-first(flink默认逆置了ClassLoader,使用ChildClassLoader即user code ClassLoader来动态加载类。这个选项就关闭了逆置,即优先使用ParentClassLoader Java Application ClassLoader动态加载)来关闭逆置或设置classloader.parent-first-patterns-additional来单独设置使用parent-first的package。

2.2 ClassNotFoundException,NoSuchMethodError,NoClassDefoundError相关错误

  1. 检查maven scope
  2. 检查$FLINK_HOME/lib
  3. 检查jobmanager启动日志,看jar包加载顺序,是否有其他相关jar被优先加载,导致类冲突。如果是,把该包放到$FLINK_HOME/lib,会优先加载

3 运行报错

3.1 Jobmanager内存超限被Kill

之前我们设置的Jobmanager总内存大小为-yjm 2048m,实际JobManager Heap总大小为1399MB,其他内存还包括元空间、Direct Memory 、 栈、本地栈、程序计数器等部分。

在运行DataStream的StreamingFileSink(On Yarn)过程中,突然遇到整个应用直接挂掉的情况。具体在Yarn的FAILED中可以找到该应用记录,可以看到Diagnostics日志如下:

Application application_1575939577711_199999 failed 1 times (global limit =2; local limit is =1) due to Attempt recovered after RM restartAM Container for appattempt_1575939577711_199999_000001 exited with exitCode: -104

Failing this attempt.Diagnostics: Container [pid=994899,containerID=container_e28_1575939577711_199999_01_000001] is running beyond physical memory limits. Current usage: 2.0 GB of 2 GB physical memory used; 7.5 GB of 16 GB virtual memory used. Killing container.

Dump of the process-tree for container_e28_1575939577711_199999_01_000001 :
|- PID PPID PGRPID SESSID CMD_NAME USER_MODE_TIME(MILLIS) SYSTEM_TIME(MILLIS) VMEM_USAGE(BYTES) RSSMEM_USAGE(PAGES) FULL_CMD_LINE
|- 994935 994899 994899 994899 (java) 21450780 17798162 7969161216 524011 /usr/local/jdk//bin/java -Xms1448m -Xmx1448m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/test.bin -Dlog.file=/yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.log -Dlogback.configurationFile=file:logback.xml -Dlog4j.configuration=file:log4j.properties org.apache.flink.yarn.entrypoint.YarnSessionClusterEntrypoint
|- 994899 994897 994899 994899 (bash) 0 0 115818496 297 /bin/bash -c /usr/local/jdk//bin/java -Xms1448m -Xmx1448m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/test.bin -Dlog.file=/yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.log -Dlogback.configurationFile=file:logback.xml -Dlog4j.configuration=file:log4j.properties org.apache.flink.yarn.entrypoint.YarnSessionClusterEntrypoint 1> /yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.out 2> /yarn/logs/application_1575939577711_199999/container_e28_1575939577711_199999_01_000001/jobmanager.err

Container killed on request. Exit code is 143

Container exited with a non-zero exit code 143

For more detailed output, check the application tracking page: http://192.168.1.1:1111/cluster/app/application_1575939577711_199999 Then click on links to logs of each attempt.
. Failing the application.

随后点击该应用Logs查看:
在这里插入图片描述
最后,我们查了监控一直没找到原因(内存一直平稳并未达到2GB)。网上搜了很久也没找到出错原因。

于是我们从最后一次成功Checkpoint处恢复,调大了JobManager内存,继续观察。如果还发现问题回来补充。

4 API问题

4.1 DataStream

4.1.1 StreamingFileSink

可以参考 Flink学习-DataStream-HDFSConnector(StreamingFileSink)3.5 常见问题章节,有关于少类、找不到方法、中文乱码等问题描述

4.2 Table & Sql API

4.2.1 Flink 1.10 关键字time解析报错问题

按照reserved-keywords的说法,我们已经对关键字字段time加上了反引号``,但还是有问题,描述如下:

  1. ddl里面源表包含该字段 time bigint(13位毫秒时间戳),然后是ts_field AS TO_TIMESTAMP(FROM_UNIXTIME(time1 / 1000)),WATERMARK FOR ts_field AS ts_field - INTERVAL ‘10’ SECOND

  2. 再定义目标表。

  3. insert into 目标表 select TUMBLE_START(ts_field, INTERVAL ‘5’ SECOND) as tumble_start, TUMBLE_END(ts_field, INTERVAL ‘5’ SECOND) as tumble_end from 源表 GROUP BY TUMBLE(ts_field, INTERVAL ‘5’ SECOND);

类似如上,用ide调试代码会发现执行时会生成一个临时表,然后select time from 临时表,这个地方time已经不再带反引号了,会导致calcite解析报错,说遇到了time字段。。。

解决方案是自己改org.apache.flink.table.planner.calcite.CalciteParser#parse方法。

4.2.2 Flink 1.10 SQL API时区问题

我在使用时,发现时区全部加了8。。。导致我的时间戳全部变成了+8小时。

具体原因是Flink会大量使用org.apache.flink.table.dataformat.SqlTimestamp来转换时间。

比如我DDL中有字段如下:

time1 BIGINT,
ts_field AS TO_TIMESTAMP(FROM_UNIXTIME(time1 / 1000)),
WATERMARK FOR ts_field AS ts_field - INTERVAL '10' SECOND

则当消费一条time1为1587047085000的数据,则会调用SqlTimestamp#fromLocalDateTime(LocalDateTime dateTime)方法。

这个时候,时间已经被转为了不带时区的LocalDateTime,值为2020-04-16T22:24:45。看起来貌似还对,但是接下来就出问题了。看看这个fromLocalDateTime方法:

public static SqlTimestamp fromLocalDateTime(LocalDateTime dateTime) {
	// 这个地方转为了18368
	long epochDay = dateTime.toLocalDate().toEpochDay();
	// 这里是80685000000000,这个没问题
	long nanoOfDay = dateTime.toLocalTime().toNanoOfDay();
	
	// 毫秒数已经变成了+8小时的时间戳!
	long millisecond = epochDay * MILLIS_PER_DAY + nanoOfDay / 1_000_000;
	int nanoOfMillisecond = (int) (nanoOfDay % 1_000_000);

	return new SqlTimestamp(millisecond, nanoOfMillisecond);
}

通过上述代码,我们知道,flink内部将LocalDateTime转为了epochDay和nanoOfDay两部分。其中epochDay是日期部分减去1970年1月1日的天数。问题就在于,是当做UTC时间处理的,没有考虑我们现在的时区为东八区!

这样一来,日期部分的时间转换后就是2020-04-16 00:00:00(UTC),也就是2020-04-16 08:00:00(东八区时间)。自然,毫秒时间戳就比时间时间多了八小时(28800000毫秒)。这就是时区问题根源所在!

这个问题很难解决,个人觉得这个时间就应该将考虑时区后转换得到的时间戳作为统一的衡量标准来转换。

4.3 DataSet

参考文档

<think>好的,我现在需要处理用户关于Flink常见面试题及解答的请求。首先,用户明确提到了想了解Flink相关的面试问题,并且之前的引用内容中有三个参考链接,其中引用[1]和[2]直接涉及Flink,而引用[3]是关于消息中间件的,可能与用户需求关联不大,但需要留意是否有相关内容可以借鉴。 首先,我需要确保回答结构清晰,符合用户要求的系统级指令,比如使用正确的中文回答、生成相关问题,以及正确应用LaTeX格式。用户提供的示例中展示了快速排序的问题和代码示例,因此可能需要以类似的格式组织Flink的问题和解答。 接下来,我需要回顾用户提供的引用内容。引用[1]列出了Flink的多个面试题,包括应用架构、压测和监控、为什么用Flink、checkpoint存储、exactly-once保证、状态机制、海量key去重、checkpoint与Spark比较、watermark机制、exactly-once实现、CEP、三种时间语义、数据高峰处理。引用[2]详细解答了exactly-once的实现和状态存储,提到了checkpoint机制和状态后端。引用[3]虽然主要讨论RabbitMQ和Kafka,但可能在对比消息系统时提及Flink的应用场景,但暂时可能不相关。 用户的需求是获取Flink常见面试题及答案,因此需要从引用[1]和[2]中提取关键点,并组织成结构化的回答。需要确保每个问题都有简明扼要的解答,同时符合用户要求的引用标注。例如,在回答exactly-once时,需要引用[2],而其他问题可能引用[1]。 同时,用户要求生成相关问题,这些问题应基于已回答的内容,引导用户进一步探索。例如,关于checkpoint机制、状态后端类型、watermark的作用等。 需要注意避免直接复制引用内容,而是用自己的话进行解释,同时保持专业性和准确性。例如,在解释checkpoint存储时,需要说明Flink支持的存储方式,如MemoryStateBackend、FsStateBackend、RocksDBStateBackend,并引用[1]中的相关信息。 此外,用户可能希望了解Flink与其他技术的对比,如与Spark的比较,这也是引用[1]中提到的面试题八,需要简要说明两者的差异,如处理模型(流处理 vs 微批处理)、状态管理、延迟等。 在组织回答时,需分点列出问题和解答,使用清晰的标题,并确保每个解答后有正确的引用标注。例如: ### Flink 的 Checkpoint 机制如何实现容错? 解答内容...[^1][^2] 同时,检查是否有遗漏的重要面试题,如状态机制、CEP、时间语义等,确保覆盖引用[1]中列出的所有相关题目。对于每个问题,需提供足够的信息,但不过于冗长,保持简洁。 最后,生成的相关问题需要与已回答的内容紧密相关,帮助用户深入理解。例如,关于exactly-once的实现细节、状态后端的选择、Watermark处理乱序数据的方法等。 总结步骤: 1. 从引用[1]中提取所有Flink相关面试题,并排序优先级。 2. 根据引用[1]和[2]的内容,为每个问题撰写简明解答,正确标注引用。 3. 确保使用正确的中文和LaTeX格式(如需要数学表达式,但Flink可能较少涉及,需注意)。 4. 生成相关问题,促进进一步学习。 5. 检查结构是否符合用户示例,分点清晰,代码块正确(如有示例代码,但Flink问题可能更多是理论,可能不需要代码)。 6. 确保引用标注自然,如解答末尾添加[^1][^2]等。 现在需要执行这些步骤,整合信息,形成用户所需的回答。</think>### Flink 常见面试题及解答 #### 1. **Flink 如何实现 exactly-once 语义?** Flink 通过 **Checkpoint 机制**实现 exactly-once 语义。具体流程如下: 1. **屏障(Barrier)插入**:Source 端将数据流划分为多个检查点周期,并在每个周期插入屏障。 2. **状态快照**:算子接收到屏障时,异步保存当前状态到持久化存储(如 HDFS、S3)。 3. **两阶段提交(2PC)**:与外部系统交互时,通过 2PC 协议保证事务的原子性,确保数据精准一次写入[^1][^2]。 > **示例代码(状态保存逻辑)**: > ```java > env.enableCheckpointing(5000); // 每 5 秒触发一次 Checkpoint > env.getCheckpointConfig().setCheckpointStorage("hdfs://path/"); > ``` --- #### 2. **Checkpoint 与 Savepoint 的区别?** | **特性** | **Checkpoint** | **Savepoint** | |----------------|-------------------------------|------------------------------| | **用途** | 容错恢复 | 手动备份/版本升级 | | **存储格式** | 二进制(Flink 内部) | 兼容性格式(支持版本迁移) | | **触发方式** | 自动周期触发 | 手动触发 | | **性能影响** | 低开销 | 较高开销 | --- #### 3. **Flink 的状态后端有哪些类型?** - **MemoryStateBackend**:状态存储在堆内存,适用于测试和小规模场景。 - **FsStateBackend**:状态存储在文件系统(如 HDFS),异步持久化。 - **RocksDBStateBackend**:基于 RocksDB 的本地磁盘存储,支持大状态和增量 Checkpoint[^1][^2]。 --- #### 4. **Watermark 的作用及生成方式?** Watermark 用于处理**事件时间乱序**问题,标记“在此时间之前的数据已到达”。 **生成方法**: ```java DataStream<T> stream = input .assignTimestampsAndWatermarks( WatermarkStrategy .<T>forBoundedOutOfOrderness(Duration.ofSeconds(5)) .withTimestampAssigner((event, ts) -> event.getTimestamp()) ); ``` --- #### 5. **Flink 的窗口类型及适用场景?** - **滚动窗口(Tumbling)**:固定大小、不重叠,如每分钟统计销售额。 - **滑动窗口(Sliding)**:固定大小、可重叠,如每 10 秒统计最近 1 分钟的 UV。 - **会话窗口(Session)**:根据数据间隔动态划分,适用于用户行为分析。 --- #### 6. **如何实现 Flink 海量 Key 去重?** - **状态存储 + TTL**:使用 `ValueState` 或 `MapState` 记录已处理数据,并设置过期时间(TTL)。 - **布隆过滤器(Bloom Filter)**:通过位数组和哈希函数实现低内存占用的近似去重[^1]。 --- #### 7. **Flink 与 Spark Streaming 的核心区别?** | **维度** | **Flink** | **Spark Streaming** | |----------------|-------------------------------|-------------------------------| | **处理模型** | 真正的流处理(逐条处理) | 微批处理(按批次处理) | | **延迟** | 毫秒级 | 秒级 | | **状态管理** | 原生支持 | 依赖外部存储(如 Redis) | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值