项目中遇到哪些问题及如何解决?
项目中哪里用到状态编程,状态是如何存储的,怎么解决大状态问题
1)Dim 动态分流使用广播状态,新老访客修复使用键控状态
状态中数据少使用 HashMap,状态中数据多的使用 RocksDB
2)大状态优化手段
(1)使用 rocksdb
(2)开启增量检查点、本地恢复、设置多目录
(3)设置预定义选项为 磁盘+内存 的策略,自动设定 writerbuffer、blockcache 等
项目中哪里遇到了反压,造成的危害,定位解决(*重点*)
1)项目中反压造成的原因
流量洪峰:不需要解决
频繁 GC:比如代码中大量创建临时对象
大状态:新老访客修复
关联外部数据库:从 Hbase 读取维度数据或将数据写入 Clickhouse
数据倾斜:keyby 之后不同分组数据量不一致
2)反压的危害
问题:Checkpoint 超时失败导致 job 挂掉
内存压力变大导致的 OOM 导致 job 挂掉
时效性降低
3)定位反压
(1)利用 Web UI 定位
定位到造成反压的节点,排查的时候,先把 operator chain 禁用,方便定位到具体算子。
Flink 现在在 UI 上通过颜色和数值来展示繁忙和反压的程度。
上游都是 high,找到第一个为 ok 的节点就是瓶颈节点。
(2)利用 Metrics 定位
可以根据指标分析反压: buffer.inPoolUsage、buffer.outPoolUsage
可以分析数据传输
4)处理反压
反压可能是暂时的,可能是由于负载高峰、CheckPoint 或作业重启引起的数据积压而导致反压。如果反压是暂时的,应该忽略它。
(1)查看是否数据倾斜
(2)使用火焰图分析看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题。
(3)分析 GC 日志,调整代码
(4)资源不合理造成的:调整资源
(5)与外部系统交互:
写 MySQL、Clickhouse:攒批写入
读 HBase:异步 IO、旁路缓存
数据倾斜问题如何解决(****重点***)
1)数据倾斜现象:
相同 Task 的多个 Subtask 中,个别 Subtask 接收到的数据量明显大于其他 Subtask 接收到的数据量,通过 Flink Web UI 可以精确地看到每个 Subtask 处理了多少数据,即可判断出 Flink 任务是否存在数据倾斜。通常,数据倾斜也会引起反压。
2)数据倾斜解决
(1)数据源倾斜
比如消费 Kafka,但是 Kafka 的 Topic 的分区之间数据不均衡
读进来之后调用重分区算子:rescale、rebalance、shuffle 等
(2)单表分组聚合(纯流式)倾斜
API:利用 flatmap 攒批、预聚合
SQL:开启 MiniBatch+LocalGlobal
(3)单表分组开窗聚合倾斜
第一阶段聚合:key 拼接随机数前缀或后缀,进行 keyby、开窗、聚合
注意:聚合完不再是 WindowedStream,要获取 WindowEnd 作为窗口标记作为第二阶段分组依据,避免不同窗口的结果聚合到一起)
第二阶段聚合:按照原来的 key 及 windowEnd 作 keyby、聚合
在我们项目中,用到了Clickhouse,我们可以第一阶段打散聚合后,直接写入Click house,查 clickhouse 再处理第二阶段
数据如何保证一致性问题
上游:kafka 保证 offset 可重发,kafka 默认实现
Flink:Checkpoint 设置执行模式为 Exactly_once
下游:使用事务写入 Kafka,使用幂等写入 Clickhouse 且查询使用 final 查询
FlinkSQL 性能比较慢如何优化
(1)设置空闲状态保留时间
(2)开启 MiniBatch
(3)开启 LocalGlobal
(4)开启 Split Distinct
(5)多维 Distinct 使用 Filter
Kafka 分区动态增加,Flink 监控不到新分区数据导致数据丢失
设置 Flink 动态监控 kafka 分区的参数
Kafka 某个分区没有数据,导致下游水位线无法抬升,窗口无法关闭计算
注入水位线时,设置最小等待时间
Redis 和 HBase 的数据不一致问题
对 Redis 和数据库的操作有 2 种方案:
(1)先操作(删除)Redis,再操作数据库
并发下可能产生数据一致性问题
上面的图表示,Thread-1 是个更新流程,Thread-2 是个查询流程,CPU 执行顺序是:Thread-1 删除缓存成功,此时 Thread-2 获取到 CPU 执行查询缓存没有数据,然后查询数据库把数据库的值写入缓存,因为此时 Thread-1 更新数据库还没有执行,所以缓存里的值是一个旧值(old),最后 CPU 执行 Thread-1 更新数据库成功的代码,那么此时数据库的值是新增(new),这样就产生了数据不一致行的问题。
解决上述问题的两种方案:
①加锁,使线程顺序执行:如果一个服务部署到了多个机器,就变成了分布式锁,或者是分布式队列按顺序去操作数据库或者 Redis,带来的副作用就是:数据库本来是并发的,现在变成串行的了,加锁或者排队执行的方案降低了系统性能,所以这个方案看起来不太可行。
②采用双删:先删除缓存,再更新数据库,当更新数据后休眠一段时间再删除一次缓存。
(2)先操作数据库,再操作(删除) Redis
我们如果更新数据库成功,删除 Redis 失败,那么 Redis 里存放的就是一个旧值,也就是删除缓存失败导致缓存和数据库的数据不一致了
上述二种方案,都希望数据操作要么都成功,要么都失败,也就是最好是一个原子操作,我们不希望看到一个失败,一个成功的结果,因为这样就产生了数据不一致的问题。
双流 join 关联不上如何解决
(1)使用 interval join 调整上下限时间,但是依然会有迟到数据关联不上
(2)使用 left join,带回撤关联
(3)可以使用 Cogroup+connect 关联两条流
生产经验
Flink 任务提交使用那种模式,为何选用这种模式
项目中提交使用的 per-job 模式,因为每个 job 资源隔离、故障隔离、独立调优
Flink 任务提交参数,JobManager 和 TaskManager 分别给多少
JobManager:内存默认 1G,cpu 默认 1 核
TaskManager:数据量多的 job,例如:Topic_log 分流的 job 可以给 8G
数据量少的 job,例如:Topic_db 分流的 job 可以给 4G
实时:并行度与 Kafka 分区一致,CPU 与 Slot 比 1:3
20M/s -> 3个分区 -> CPU与Slot比 1:3 -> 3个Slot -> Core数1个 -> CPU与内存比 1:4 -> TM 1 slot -> TM 4G 资源
JobManager 2G 内存 1CPU
平均 一个 Flink 作业 6G 内存,2Core
Flink 任务并行度如何设置
全局并行度设置和 kafka 分区数保持一致为 5,Keyby 后计算偏大的算子,单独指定。
项目中 Flink 作业 Checkpoint 参数如何设置
Checkpoint 间隔:作业多久触发一次 Checkpoint,由 job 状态大小和恢复调整,一般建议 3~5 分钟,时效性要求高的可以设置 s 级别。
Checkpoint 超时:限制 Checkpoint 的执行时间,超过此时间,Checkpoint 被丢弃,建议10 分钟。
Checkpoint 最小间隔:避免 Checkpoint 过于频繁,可以设置分钟级别。
Checkpoint 的执行模式:Exactly_once 或 At_least_once,选择 Exactly_once。
Checkpoint 的存储后端:一般存储 HDFS 。
迟到数据如何解决
(1)设置乱序时间
(2)窗口允许迟到时间
(3)侧输出流
生产中侧输出流,需要 Flink 单独处理,在写入 Clickhouse,通过接口再次计算
实时数仓延迟多少
反压,状态大小,资源偏少,机器性能,checkpoint 时间都会影响数仓延迟。
一般影响最大就是窗口大小,一般是 5s。
如果启用两阶段提交写入 Kafka,下游设置读已提交,那么需要加上 CheckPoint 间隔时间。
项目开发多久,维护了多久
开发周期半年,维护半年多
如何处理缓存冷启动问题
初次启动,Redis 没有缓存数据,大量读请求访问 Habse,类似于缓存雪崩
从离线统计热门维度数据,最近三天用户购买,活跃的 sku,手动插入 Redis。
如何处理动态分流冷启动问题(主流数据先到,丢失数据怎么处理)
在 Open 方法中预加载配置信息到 HashMap 以防止配置信息后到。
代码升级,修改代码,如何上线
Savepoint 停止程序,通过 Savepoint 恢复程序。
代码改动较大,savepoint 恢复不了怎么办,看历史数据要不要,要从头跑,不要就不适用 savepoint 恢复直接提交运行。
如果现在做了 5 个 Checkpoint,Flink Job 挂掉之后想恢复到第三次 Checkpoint 保存的状态上,如何操作
在 Flink 中,我们可以通过设置 externalized-checkpoint 来启用外部化检查点,要从特定的检查点(例如第三个检查点)恢复作业,我们需要手动指定要从哪个检查点(需要指定到chk-xx 目录)恢复。
需要使用 flink 记录一群人,从北京出发到上海,记录出发时间和到达时间,同时要显示每个人用时多久,需要实时显示,如果让你来做,你怎么设计?
按照每个人 KeyBy,将出发时间存入状态,当到达时使用到达时间减去出发时间。
flink 内部的数据质量和数据的时效怎么把控的
内部的数据质量:内部一致性检查点
数据的时效:结合 3.9.5 回答
实时任务问题(延迟)怎么排查
实时任务出现延迟时,可以从以下几个方面进行排查:
(1)监控指标:看是否反压
(2)日志信息:查看任务运行时的日志信息,定位潜在的问题和异常情况。例如,网络波动、硬件故障、不当的配置等等。
(3)外部事件:如果延迟出现在大量的外部事件后,则可能需要考虑其他因素(如外部系统故障、网络波动等)。框架混部,资源争抢!
维度数据查询并发量
未做优化之前,有几千 QPS,做完 Redis 的缓存优化,下降到几十
Prometheus+Grafana 是自己搭的吗,监控哪些指标
是我们自己搭建的,用来监控 Flink 任务和集群的相关指标
1)TaskManager Metrics:这些指标提供有关 TaskManager 的信息,例如 CPU 使用率、内存使用率、网络 IO 等。
2)Task Metrics:这些指标提供有关任务的信息,例如任务的延迟时间、记录丢失数、输入输出速率等。
3)Checkpoint Metrics:这些指标提供有关检查点的信息,例如检查点的持续时间、成功/失败的检查点数量、检查点大小等。
4)Operator Metrics:这些指标提供有关 Flink 操作符的信息,例如操作符的输入/输出记录数、处理时间、缓存大小等。
怎样在不停止任务的情况下改 flink 参数
动态分流,其他没有做过!
hbase 中有表,里面的 1 月份到 3 月份的数据我不要了,我需要删除它(彻底删除),要怎么做
在 HBase 中彻底删除表中的数据,需要执行以下步骤:
(1)禁用表
(2)创建一个新表
(3)复制需要保留的数据,将需要保留的数据从旧表复制到新表。
(4)删除旧表
(5)重命名新表
在执行这些步骤之前,建议先进行数据备份以防止意外数据丢失。此外,如果旧表中的数据量非常大,复制数据到新表中的过程可能会需要很长时间。
如果 flink 程序的数据倾斜是偶然出现的,可能白天可能晚上突然出现,然后几个月都没有出现,没办法复现,怎么解决?
Flink 本身存在反压机制,短时间的数据倾斜问题可以自身消化掉,所以针对于这种偶然性数据倾斜,不做处理。
维度数据改变之后,如何保证新 join 的维度数据是正确的数据
(1)我们采用的是低延迟增量更新,本身就有延迟,没办法保证完全的正确数据。
(2)如果必须要正确结果,只能直接读取 MySQL 数据,但是需要考虑并发,MySQL机器性能。
实时---业务
数据采集到 ODS 层
1)前端埋点的行为数据为什么又采集一份?
时效性
Kafka 保存 3 天,磁盘够:原来 1T,现在 2T,没压力
2)为什么选择 Kafka?
实时写、实时读
=》 消息队列适合,其他数据库受不了
3)为什么用 Maxwell?历史数据同步怎么保证一致性?
FlinkCDC 在 20 年 7 月才发布
Canal 与 Maxwell 区别:
Maxwell 支持同步历史数据
Maxwell 支持断点还原(存在元数据库)
数据格式更轻量
保证至少一次,不丢
4)Kafka 保存多久?如果需要以前的数据怎么办?
跟离线项目保持一致:3 天
我们的项目不需要,如果需要的话可以去数据库或 Hive 现查,ClickHouse 也有历史的宽表数据。
ODS 层
1)存储原始数据
2 个 topic:埋点的行为数据 ods_base_log、业务数据 ods_base_db
2)业务数据的有序性:
maxwell 配置,指定生产者分区的 key 为 table。
DWD+DIM 层
1)存储位置,为什么维度表存 HBase?
事实表存 Kafka、维度表存 HBase
基于热存储加载维表的 Join 方案:
随机查
长远考虑
适合实时读写
2)埋点行为数据分流
(1)修复新老访客(选择性):以前是前端试别新老访客,不够准确
(2)分流:侧输出流
分了 3 个 topic: 启动、页面、曝光
(3)用户跳出、独立访客统计
3)业务数据处理
(1)动态分流:FlinkSQL 读取 topic_base_db 数据,过滤出每张明细表写回 kafka
(2)订单预处理表设计:双流 join,使用 leftjoin
(3)字典表维度退化
4)维度数据写入 Hbase
(1)为了避免维度数据发生变化而重启任务,在 mysql 存一张配置表来动态配置。
动态实现:通过广播状态
=》 读取一张配置表 ===》 维护这张配置表
source 来源 sink 写到哪
操作类型 字段 主键 扩展
=》实时获取配置表的变化 ==》CDC 工具
=》 FlinkCDC
=》 使用了 sql 的方式,去同步这张配置表
=》sql 的数据格式比较方便
(2)怎么写 HBase:借助 phoenix
没有做维度退化
维表数据量小、变化频率慢
(3)Hbase 的 rowkey 怎么设计的?有没有数据热点问题?
最大的维表:用户维表
=》百万日活,2000 万注册用户为例,1 条平均 1k:2000 万*1k=约 20G
使用 Phoenix 创建的盐表,避免数据热点问题
DWS 层
1)为什么选择 ClickHouse
(1)适合大宽表、数据量多、聚合统计分析 =》 快
(2)宽表已经不再需要 Join,很合适
2)关联维度数据
(1)维度关联方案:预加载、读取外部数据库、双流 Join、LookupJoin
(2)项目中读取 Hbase 中维度数据
(3)优化 1:异步 IO
异步查询实际上是把维表的查询操作托管给单独的线程池完成,这样不会因为某一个查询造成阻塞,单个并行可以连续发送多个请求,提高并发效率。
这种方式特别针对涉及网络 IO 的操作,减少因为请求等待带来的消耗。
Flink 在 1.2 中引入了 Async I/O,在异步模式下,将 IO 操作异步化,单个并行可以连续发送多个请求,哪个请求先返回就先处理,从而在连续的请求间不需要阻塞式等待,大大提高了流处理效率。
Async I/O 是阿里巴巴贡献给社区的一个呼声非常高的特性,解决与外部系统交互时网络延迟成为了系统瓶颈的问题。
(4)优化 2:旁路缓存
旁路缓存模式是一种非常常见的按需分配缓存的模式。如图,任何请求优先访问缓存,缓存命中,直接获得数据返回请求。如果未命中则,查询数据库,同时把结果写入缓存以备后续请求使用。
(5)怎么保证缓存一致性
方案 1:当我们获取到维表更新的数据,也就是拿到维度表操作类型为 update 时:
更新 Hbase 的同时,删除 redis 里对应的之前缓存的数据
Redis 设置了过期时间:24 小时
方案 2:双写
3)轻度聚合
(1)DWS 层要应对很多实时查询,如果是完全的明细那么查询的压力是非常大的。将更多的实时数据以主题的方式组合起来便于管理,同时也能减少维度查询的次数。
(2)开一个小窗口,5s 的滚动窗口
(3)同时减轻了写 ClickHouse 的压力,减少后续聚合的时间
(4)几张表? 表名、字段
访客、商品、地区、关键词
ADS 层
1)实现方案
为可视化大屏服务,提供一个数据接口用来查询 ClickHouse 中的数据。
2)怎么保证 ClickHouse 的一致性?
ReplacingMergeTree 只能保证最终一致性,查询时的 sql 语法加上去重逻辑。
3)Flink 任务如何监控
Flink 和 ClickHouse 都使用了 Prometheus + Grafana。