
做数据开发这几年前前后后也面过不少人也被面过不少次。这两年Flink基本成了实时计算岗位的标配技能简历上几乎人人都会写“精通Flink”但一聊到状态、容错、背压这些底层机制能讲通透的确实不多。在我看来Flink面试题其实分两类一类是考你有没有用过另一类是考你有没有真正理解它。前者靠项目经验就能带过后者则需要把原理和源码逻辑串起来。这篇文章我就结合自己带团队、面试候选人的经验把Flink面试里那些高频问题、底层原理以及面试官真正想听的东西系统性梳理一遍。不管是准备跳槽还是想补基础希望都能帮你少走点弯路。1. 框架核心设计与架构类问题1.1 为什么实时计算一定绕不开Flink面试从这个问题开始的概率极高几乎每个候选人的简历上都会写“熟悉实时计算”那第一个问题自然就是你用过哪些框架为什么最终选了Flink其实国内早期实时计算领域是Storm和Spark Streaming的天下后来Flink慢慢成了主流这背后是架构代际的差异。Storm是真正的流式计算来一条处理一条延迟极低但它的吞吐量和精确一次语义支持都比较弱而且编程模型偏底层开发效率不高。Spark Streaming本质上是微批处理把流切成一个个小批次去跑虽然吞吐高、生态好但延迟做不到毫秒级而且严格意义上它处理的还是“批”而不是“流”。Flink的设计思路完全不同它从底层就把数据当成无界流来处理把批处理看作是流计算的一个特例。所有算子都是流式的数据一直在管道里流动配合自己的状态管理和容错机制做到了真正的低延迟、高吞吐、精确一次。用生活里的话说Storm像是对讲机说话马上能听到但人多就乱Spark Streaming像快递批量发货一次发一批效率高但不是那么实时Flink就是一条全自动流水线每个工位随到随处理既能稳定高速运转出了问题还能精准回滚到之前的某个节点重新来过。面试官问这个问题其实不指望你把文档背一遍而是想听你怎么理解流和批的关系有没有真正做过技术选型分析。回答的时候可以提到Flink的“批流一体”设计同一套API既能跑批任务又能跑流任务这使得团队不需要维护两套计算引擎代码开发维护成本明显下降这也是很多公司迁移到Flink的重要原因。1.2 JobManager与TaskManager的分工逻辑Flink的运行时架构是面试必问的第二关而且很多人在这里只答了个表层说“一个管调度一个管执行”但面试官追问下去就露馅了。完整的答案要覆盖四个组件。JobManager是集群的“大脑”负责接收作业、生成执行图、向TaskManager分配任务以及协调checkpoint。TaskManager是“工人”真正干活的地方一个TaskManager上有多个slot每个slot可以跑一个任务子任务。ResourceManager管资源在Flink集群上负责slot的分配和回收如果跑在YARN或K8s上它还负责向外部资源池申请容器。Dispatcher则负责提供REST接口接收作业提交拉起JobManager。这里有一个容易忽略的细节TaskManager上的slot数决定了一个TaskManager能并行跑多少任务但slot共享是Flink非常巧妙的优化点。默认情况下不同算子的子任务可以共享同一个slot只要它们是同一个作业里的。这大大减少了网络数据交互的消耗因为你不需要所有数据都序列化后在网络间传输很多上下游算子其实就在同一个TaskManager进程里通过本地内存直接传递就行。举一个实际调优的例子。我之前跑一个实时ETL作业source端并行度设了4后面每个算子并行度都设4总共如果按一个算子一个slot来算需要二十多个slot。但因为有slot共享整个作业可能只需要三四个TaskManager就能跑完资源利用率一下子提上去了。1.3 数据流图的执行机制与算子链从写的代码到真正跑起来的任务中间隔了好几步很多面了三年以上的人也未必能完整讲清楚这几步。用户写的SQL或DataStream API代码第一步会生成StreamGraph这是最原始的、逻辑层面的数据流图。然后经过StreamGraphGenerator优化生成JobGraph这个阶段会把一些可以合并的算子串成算子链相当于把流水线上相邻的几个工位合并成一个全能工位省去中间传送带网络IO和序列化。接下来JobManager拿到JobGraph后会根据并行度展开成ExecutionGraph这是可并行执行的物理执行图每个并行实例叫作ExecutionVertex。最后通过调度器分发给TaskManager真正开始跑。核心在于算子链的合并条件这是实际问题里排查性能问题的关键。只有上下游算子之间的数据分发方式是forward一对一模式时才能合并如果中间有keyBy、rebalance这种需要重新分区数据的操作就必须断开网络传输。很多新手刚优化作业时加了一堆并行度发现吞吐没上去一看监控发现数据在大量算子之间频繁走网络这就是算子链没有合并的典型症状。我做过一个实际优化案例一个从Kafka消费数据做清洗、再写入ClickHouse的作业原本每个算子独立调度吞吐只有不到两万条每秒。我把数据清洗的多个步骤整合成能链式执行的算子同时调大了并行度吞吐直接翻了三倍还多。这就是面试里体现“经验”的细节。1.4 为什么要求“窗口”而不只是“来一条算一条”面试官如果前面基础题觉得你答得还可以接下来大概率会引导到窗口计算。流计算确实是个无界的数据流但业务需求往往要求按时间段聚合比如每5分钟算一次销售额、统计过去1小时的UV这些场景都不能来一条算一条必须划分窗口。Flink的窗口分三大类滚动窗口Tumbling Window固定大小互不重叠比如每5分钟开一个窗口关了就清空重新积累滑动窗口Sliding Window大小固定但有步长窗口之间可以重叠比如窗口大小1小时、滑动步长5分钟数据可能同时属于多个窗口会话窗口Session Window则按时间间隔切分一段时间没有新数据进来就算一次会话结束适合分析用户连续操作行为。窗口还有一个绕不开的基石水位线Watermark。它用来处理乱序数据——没有水位线的话数据晚到一会儿窗口就关了结果就缺了这段数据。水位线的本质是一个“时间进度信号”告诉Flink目前为止这个时间戳之前的数据我已经收集完毕了可以触发窗口计算了。水位线和窗口触发的关系几乎可以算面试里最高频的组合问题答得好基本能让面试官眼前一亮。比如事件时间语义下设置10秒的乱序容忍度水位线的推进就等于当前观察到的最大的事件时间减去10秒。如果一条时间戳为12:00:30的数据在12:00:40到达此时水位线已经推进到12:00:30那12:00:30之前的数据可能已经触发过窗口计算了。这也是Flink输出“迟到的数据”的典型场景。2. 状态管理与容错机制2.1 状态为什么是Flink的精髓很多Flink学习者在入门阶段就把状态给跳过了因为写业务逻辑时好像不显式“用状态”也能跑面试一考就明显卡壳。但实际上状态管理才是Flink区别于其他计算框架的核心价值所在。我习惯用一个比喻来解释状态如果流计算是一条流水线状态就相当于每个工位上工人手边的备忘录。没有备忘录的话工人只能处理手头这一个零件一条数据有了备忘录他可以记住“这位用户之前买过什么”“这个商品的库存还剩多少”这就是有状态计算。像计数、去重、累加、窗口聚合这些操作本质上都需要状态。Flink里状态分两大类。Keyed State按键分区同一个key的所有数据都会落到同一个子任务上处理所以每个key可以有自己的独立状态空间常用的有ValueState存单个值、ListState存列表、MapState存映射、ReducingState和AggregatingState存聚合中间结果。Operator State则是每个子任务粒度一份跟key无关比如Kafka的offset就可以用Operator State来记录当前消费的位置。一个极具代表性的案例实时去重计数。比如统计每个页面的UV理论上需要记住所有访问过的用户ID才能去重数据量一大内存必然爆炸。这时候正确做法是用MapState来存已访问用户ID配合RocksDB状态后端让状态可以落盘到磁盘而不会把内存撑爆。我问候选人是否处理过这种场景时很多人回答“直接用Redis去重”这当然也是一种方案但如果你不理解Flink自身状态的能力边界就很难针对不同业务选到最省事的方案。2.2 Checkpoint与精准一次语义的底层原理这里几乎算是Flink面试的分水岭能把这部分讲透彻的候选人普遍对分布式系统有比较扎实的理解。Checkpoint机制的核心是Barrier对齐。上游Source周期性向数据流中注入一种特殊记录叫检查点屏障Checkpoint Barrier。屏障像一条分界线把数据流切成了“本次检查点前”和“本次检查点后”两个阶段。当某个算子收到所有输入通道的屏障之后说明这个算子对“检查点前所有数据”的处理已经完整了于是把当前状态快照保存到持久化存储里。JVM堆内存实现也就是我们常说的HashMapStateBackend保存快照时把状态序列化写到内存或文件系统RocksDB状态后端则先让RocksDB把memtable刷到本地磁盘再异步上传快照文件这种方式对超大状态更友好。“精准一次”这个目标单靠Flink自身是不够的。Flink内部可以通过屏障对齐、事务性状态写入来保证每个算子只对每条数据生效一次但结果写到外部系统时如果下游不支持事务或者没有配合仍然可能出现重复。Flink的经典解法是TwoPhaseCommitSinkFunction也就是两阶段提交。预提交阶段数据写入外部系统但未正式生效检查点完成信号到达后再触发提交动作让数据真正可见。如果中途失败则回滚。Kafka恰好支持这样的跨系统事务机制所以Flink Kafka Sink能做到端到端的精确一次这也是Kafka和Flink天生一对的原因之一。面试时如果能把“Flink精确一次需要两阶段提交外部存储也要支持事务或幂等”这个边界条件讲出来就已经超过大部分只知道背概念的人了。2.3 状态过期、状态后端选型与日常维护状态既然存在就不能无限增长否则磁盘和内存早晚会爆掉。这也是实际生产中常踩的坑面试官很喜欢把它包装成“线上案例”来问。先说状态过期TTL。Flink的StateTtlConfig可以给状态设置存活时间比如用户登录状态只保留7天写代码时给状态配置TTL后底层会为状态值附带一个时间戳读取时如果超时就视为过期并且后台会定期清理过期数据。这里的关键是仅设置TTL并不能保证过期数据立刻被删除只是读取时不可见真正清理要靠后台清理策略比如RocksDB的Compaction Filter机制可以边压实边清理过期数据或者通过快照时全量清理。业务对状态大小比较敏感时这块需要针对不同状态后端做专门调优。状态后端的选型也是高频考点。HashMapStateBackend适合状态量比较小、纯内存就能放下的场景天然走堆内存访问极快但状态非常大时GC压力剧增容易OOM。EmbeddedRocksDBStateBackend则把状态存在RocksDB中内存放热数据、磁盘放冷数据单TaskManager能承载的状态量可以达到几百GB甚至TB级别代价是每次读写都要走序列化和反序列化延迟会有一定的开销。生产上凡是key维度特别大的作业比如每个用户都维护一份行为记录基本无脑选RocksDB。实际处理过一个场景某个实时对账作业状态增长非常快上线第三天就把RocksDB所在磁盘打满了。后来我把整个作业的key做了二级拆分把大Key状态拆成多个小维度的Keyed State同时设了合理的TTL状态增长速度立刻降了一个数量级。这就是经验的价值面试时能讲出这类案例比背十道题都管用。3. 背压、可靠性与运维实战3.1 背压的产生原理与定位方法背压英文叫BackPressure面试考的是“你的作业处理不过来了会发生什么”实际运维则考的是“你敢不敢在线上环境快速定位背压源头”。这两个视角都必须具备。Flink的背压机制经历了两个阶段的演进。早期版本用的是基于TCP的滑动窗口流控接收端消费变慢传输层的缓冲区就会变满发送端的写入速度自然被拖慢一层层向上游传递最终反馈到source端。现在Flink使用的是基于Credit的流控。简单理解就是下游节点会周期性告诉上游自己还能接收多少数据Credit上游手里有了信用额度才敢发数据没有额度就等待。这种方式可以更精确地控制网络缓冲背压传播速度更快、更平缓。排查背压时最容易犯的错是只看CPU使用率。CPU低不代表没背压因为可能瓶颈在序列化、网络或锁竞争。正确思路是逐层看先看每个算子收数据和发数据的速率差如果某个算子接收速率远大于发送速率说明这个算子处理不过来了再看TaskManager的线程栈如果大量线程卡在反压监控指标里说明背压已经比较严重。如果背压出现在sink端那可能是下游数据库写入性能抖动了比如ClickHouse的merge压力大、MySQL锁等待、ES bulk队列堆积这些都需要对照外部系统监控综合判断。3.2 数据倾斜与反压的关联排查线上作业的一大杀手是数据倾斜。热门大V的信息、双十一的头部商品的订单量都天然比其他key大得多这些热key如果哈希到同一个子任务上那个子任务很容易被打爆成为背压的起点。典型的“倾斜型背压”特征是同一个算子多个并行子任务里个别子任务的繁忙程度接近100%其他子任务却很空闲。不同业务的解决手段不完全一样。最简单的做法是加盐把原来集中的大key拆成多个加随机后缀的子key先在局部聚合再把结果按原始key汇总相当于先分治后合并。这个思路在双11大屏、实时榜单的业务中非常实用。还有一种方法是给Source端增加并行度让数据尽量均匀地分布到下游不过这种方法只是推迟了问题并没有真正解决热点。我印象特别深刻的一个案例是处理某个支付平台的对账作业一个支付渠道的key集中了全量数据的80%怎么调并行度都没用。后来我在keyBy前增加了一轮两层聚合先按渠道加随机后缀局部求和再按渠道汇总作业从频繁反压变成稳定运行且吞吐提升了近3倍。这种经验在面试时讲出来面试官基本能立刻判断出你是有真实生产经验的人而不是纸上谈兵。3.3 JDBC连接器异常与Sink写入失败的排查经验工作里Flink最常见的线上问题反而往往不在Flink内部而在与外部系统的连接器上。热词里有一条“flink的jdbc连接器异常”还有“flink sink hive表数据不入表”这两个我都在生产环境踩过。JDBC连接器有个典型问题连接池耗尽。默认的JDBC Sink在写入数据时会从连接池取连接如果下游数据库连接数配置太小而source端消费速度又快连接池很快就会被占满作业表现就是持续背压、不断报连接获取超时。解决思路不复杂要么调大连接池上限要么在下游加批量写入缓冲要么控制sink并行度。但如果在高并发写库场景里你还要考虑数据库端的max_connections——我曾经遇到一个线上事故就是Sink并行度开到32每个子任务都抱着一堆连接直接把MySQL的连接数打满导致所有业务系统写入都受影响。这教训非常深刻现在我的原则是凡是面向在线业务库的出站Sink一定要控制并行度并且开启批量攒批避免实时小事务把数据库搞垮。Sink写入Hive表数据不入表也很有意思。Hive Sink的实际逻辑是先写入临时目录或临时文件然后通过Hive的atomic rename机制把文件移动到分区目录下。如果作业正在运行但你查Hive分区表看不到数据是正常的因为还没到提交分区那一步。很多人以为数据丢了其实要么是分区提交策略配置不对比如没有设置触发间隔分区迟迟不提交要么是开启流模式后需要设置streaming-source.enable来持续感知新分区。这类问题在面试中如果主动展开讲自己的排查思路非常加分因为能体现你在真实生产环境里遇到问题、定位问题、解决问题的能力这比面试官问一句你答一句的机械感好太多。3.4 部署模式的演进从Standalone到K8sFlink的部署方式也在面试题里高频出现尤其是热词里就有“flink 安装配置到部署”这属于入门第一步。但深入面试时面试官问的往往不是怎么下载压缩包而是不同部署模式的生产适用性。最早接触Flink时很多人用的是Standalone集群把所有进程都手动分配好适合学习、测试或者团队运维能力比较弱的场景。它可以快速上手但资源利用率低、缺少动态伸缩能力生产上除非规模不大否则不太推荐。YARN部署模式是当前很多公司的首选因为国内大数据集群基本都有Hadoop生态。Flink on YARN有三种提交模式Application Mode、Per-Job Mode和Session Mode。Application Mode和Per-Job Mode都会在提交作业时为作业单独创建一个专用集群作业结束集群就释放好处是隔离性好、互不影响。Session Mode则是集群常驻多个作业共用一个Flink集群好处是启动作业快坏处是资源竞争和故障影响范围大。K8s部署则是未来的大趋势。Flink在K8s上原生支持Active/Standby两种模式的HA资源层可以按实际负载自动伸缩配合Helm Chart和Operator来做生命周期管理运维成本比YARN模式更低。我们团队最近的Flink作业已经全面迁到K8s之前做一个作业扩容要等YARN队列审批现在直接改Parallelism配置等Pod自动拉起就行体验差了好几个级别。面试时如果能对比清楚三种模式的适用场景并从运维角度说出各自优劣面试官基本会认为你有规模化的生产实践。4. 高频实战场景与项目级问题4.1 CDC Pipeline部署与Flink CDC的实践热词里出现了“flink cdc pipeline部署”和“flink cdc安装部署”这也是我强烈建议面试准备者要认真准备的一块。CDCChange Data Capture主要是捕捉数据库变更日志让实时计算可以读取数据库的binlog或者WAL日志。在实时数仓里Flink CDC几乎是标配广泛用于实时同步、实时入仓、数据湖增量同步。Flink CDC项目经历了较大演进。早期的做法是每个表一个source通过Debezium嵌入式引擎去接数据库的binlog然后注册为Flink表。现在Flink CDC已经发展出YAML Pipeline模式可以直接在Flink集群上启动一个“同步管道”它不像之前那样需要写一堆Java代码而是用一个YAML声明“从哪张表、哪个库同步到哪张目标表”甚至不需要写DataStream API。部署方式上也支持把CDC任务提交到Flink集群上由其统一管理生命周期。这个模式对实时数据同步来说成本大幅降低也让不会写复杂Flink代码的同学也能快速上手。部署时最容易踩的坑有三个。第一数据库binlog格式必须设置为ROW模式否则无法获取变更前和变更后的完整数据。第二Flink CDC在检查点恢复时会把binlog offset记录在状态里如果你作业恢复时指定的检查点过期了或者binlog已经被MySQL清理就只能重新做全量同步初始化。第三如果目标表是Hive表CDC任务的写入模式与普通Flink Job写入Hive不同需要确认目标Hive表的存储格式和分区策略是否匹配。一个实际案例我们用Flink CDC做MySQL到Hudi的增量同步上线后数据一直正常但某天DBA调整了binlog的过期时间从7天改成了1天结果作业刚好那几天没触发过检查点恢复时发现binlog已经被清理只能全量重跑。从此之后我们的SOP里强制加了“每次发布前必须确认binlog保留时间大于检查点间隔的3倍”。4.2 自定义Data Source和Data Sink的正确姿势热词里反复出现“flink 实现自定义 data source”和“flink 实时计算 - 进阶篇如何自定义 data source 与 data sink”从学习路径而言这确实是从入门到进阶的必经之路。自定义Source有两种主流方式。一种是继承SourceFunction适合大部分常规场景。你在run方法里循环调用collect或ctx.collectWithTimestamp吐数据配合isRunning标志来管理停止逻辑。另一种是更现代化的接口实现SourceReader这适合Source开销比较大、需要异步拉取数据的场景。SourceReader配合SplitEnumerator可以达到更灵活的分片分配策略比如自己控制从Kafka多个分区拉取的顺序和速率。自定义Sink的核心接口是SinkFunction它的invoke方法会在每条数据到达时被调用。如果你的Sink目标是一个需要事务保护的系统那就要考虑继承TwoPhaseCommitSinkFunction来做精确一次语义这个我在前面讲Kafka Sink时已经提过。自定义Sink最容易犯的错是没有做批量缓冲。比如你一条一条地做HTTP调用或者一条一条地写数据库吞吐必然上不去。真正的高性能Sink应该内部用缓冲区攒批等攒够一批再一次刷出这样外部系统的压力也小得多。我常用ArrayList攒到256条或1秒时间窗口就flush一次实测性能提升非常大。4.3 词频统计与入门实战的进阶热词里还有“flink 实时计算 - 词频统计初体验”和“flink菜鸟教程”这基本是学习Flink的人动手写的第一个程序。别小看这个“WordCount”它背后涵盖了Source、Transformation、Sink和并行度调整的完整链路。词频统计如果只是用来入门我想强调两点进阶思考。第一点是keyBy后的累加本质上是状态操作每来一条数据底层都要读取当前key的旧值并更新为新值所以它天然演示了状态的工作原理。理解了这一点后面所有Keyed State的开发都能联想到这条最朴素的逻辑。第二点是WordCount里如果数据分布不均匀比如某些词出现频率极高它会形成一个天然的数据倾斜示例你可以顺手把加盐的解决方案在上面复现一遍这样学习一个例子就把状态、窗口、倾斜优化都给串起来了。很多面试者喜欢在简历里写“熟练使用WordCount”这种描述其实没什么含金量。建议至少有一个真实业务场景的项目比如实时大屏、实时风控、实时对账哪怕是自己搭的Demo也要把技术难点讲清楚。4.4 数据血缘OpenMetadata与Flink的集成价值热词里有一条“openmetadata 获取flink血缘关系”看起来有点冷门但其实戳中了数据治理方向的一个痛点。很多公司的数据团队都有这种经历某个实时任务的数据口径怎么来的、依赖哪张源表、影响哪些下游报表全靠人肉问一个员工离职数据链路就断了一半。数据血缘分两类。一类是解析静态元数据比如你在这个SQL里select了哪些字段、join了哪些表这一类通过Flink SQL的Calcite解析就能拿到AST和依赖列表。另一类是运行时动态血缘比如CDC同步里源表到目标表的数据流向是运行才能确定的。OpenMetadata的核心能力是做元数据管理它提供开放API可以把Flink作业的静态和动态血缘信息抽取并沉淀到元数据中心供数据地图、质量平台、治理平台统一查询。具体集成路径大概是先把Flink作业提交到集群时获取作业图JobGraph信息然后在OpenMetadata中注册作业接入schema解析出输入输出表再把Flink SQL解析出的字段级血缘写入OpenMetadata的Table Entity字段关系里。最后数据地图上就能看到MySQL某张表经过Flink CDC清洗产出到Hive某张表进而支撑某张看板整条链路一目了然。这个方向很多团队还没做但一旦做了价值很大面试时如果你能讲清楚“血缘如何帮助做影响分析和故障排查”在面高级岗位时是很大的加分项。4.5 线上作业常见故障与恢复策略速查积累了一堆真实案例后可以把高频问题做一张速查表。面试时如果被问到“你在生产上遇到过什么坑”从这下面挑一两个讲比自己临时编故事效果好得多。症状可能原因排查命令/工具恢复建议作业持续反压但CPU不高外部系统写入慢查看Sink子任务输出速率与下游负载调大Sink并行度前先确认下游容量否则可能压垮数据库Flink CDC同步延迟越来越大binlog消费不及时或Source并行度不足查看source端指标tabletFetchDelay增加Source并行度并调整chunk大小窗口结果不符合预期水位线设置不合理或数据乱序严重查看当前水位线与最大事件时间偏差调大乱序容忍度必要时使用allowedLateness侧输出状态无限膨胀没有设置TTL或key粒度过大查看RocksDB磁盘占用与状态条目数设置TTL调整key设计增加状态后端容量Restart次数过多代码逻辑异常或外部资源抖动查看JobManager的异常堆栈按异常类型分级瞬时网络抖动可自动恢复业务数据问题要加侧输出隔离再补充一下侧输出Side Output技巧。合理利用侧输出不仅能解决脏数据问题也是面试中很讨喜的“聪明处理”。正常流处理时遇到脏数据比如JSON解析失败、字段类型不符如果你直接把数据丢弃或者让作业失败丢失数据不可追溯。侧输出可以帮你把不能正常处理的数据分拣到专门的旁路分支里你可以单独写到一个死信队列或者加一条告警日志这样主流程不受影响问题数据一条都不会丢。我负责的风控实时计算里每天从Kafka进来几亿条行为日志总会有少量字段异常的脏数据。把它们扔进侧输出再攒批写回Kafka专门topic离线后再由数仓任务去清洗归档。有个同事在做离线复盘时还专门依赖这份脏数据来反推上报端的bug。这就是侧输出在生产里的实际价值。5. 写在最后的一些心得面了这么多人之后我发现一个有意思的规律面试题背得再熟不如对一个真实问题理解得透彻。Flink面试题本身是固定的但面试官的水平差异很大他追问的深度往往取决于你自己能在哪个细节上展开。所以与其花时间刷几百道“Flink题”不如花时间把一个端到端的实时计算作业从无到有、从遇到故障到解决问题的完整过程真正吃透。我个人在实际带团队的时候最看重的三个能力是第一能不能讲清楚任务的“数据流”从Source到Sink每一条记录经历了什么第二遇到背压或者数据不准时能不能用监控指标而不是“拍脑袋”去定位问题第三能不能认识到Flink并不是万能的外部系统的能力边界才是决定整体链路可靠性的关键。如果能把这三点体现在面试回答里基本就已经站在前5%的位置了。最后送上一个实用小技巧面试前拿自己工作里最核心的那个Flink作业把运行图打印出来对着图从Kafka消费开始一步一步讲清楚每个算子做了什么、状态存在哪里、检查点多久一次、发生过哪些问题、怎么解决的。用真实运行图来讲效果远比任何包装过的题目都强十倍这也是我在团队内训中必用的一招大家反馈准备任何实时计算面试都用得上。