JJava 知识库
JAVA INTERVIEW

高频面试题

CK进阶约 3 分钟

业务数据会重复上报和更新,用 ReplacingMergeTree 能保证查询绝对不重复吗?

参考回答约 3 分钟 · 口语表达
先说结论

先说结论:ReplacingMergeTree 在数据片段后台合并时,对排序键相同的行保留一行;指定版本列后通常保留版本最大的行。合并是异步的,因此写入后旧版本可能暂时共存,它提供最终去重而不是写入时唯一约束。 没有版本列时保留哪一行取决于合并顺序,不应承担明确的业务版本选择。

01

我先给结论,再说明它在项目里解决什么问题。理解后台合并去重、版本列、FINAL 查询及最终一致边界。ReplacingMergeTree 在数据片段后台合并时,对排序键相同的行保留一行;指定版本列后通常保留版本最大的行。合并是异步的,因此写入后旧版本可能暂时共存,它提供最终去重而不是写入时唯一约束。 没有版本列时保留哪一行取决于合并顺序,不应承担明确的业务版本选择。

02

核心机制我会按一次真实执行过程来讲。沿着「写入同一排序键多个版本 → 版本共同存在于不同 Part → 后台 merge 选择最新行 → 查询可用 FINAL 强制合并视图 → 业务按最终一致性读取」观察输入、状态与输出,这些阶段都可以从日志、指标或源码里验证。 写入同一排序键多个版本 ReplacingMergeTree 的“重复”由 ORDER BY 键定义,主键设计不当会误合并不同业务行。

03

实现细节只抓关键入口,不会整段背源码。ReplacingSortedAlgorithm:版本替换逻辑。 system.parts:旧新版本所在 Part。 我会先确认请求实际走到了哪条路径,再用运行数据验证,不会只看类名或配置猜测。

04

放到生产使用时,我会关注参数和验证数据。同键写 3 个乱序版本,比较普通查询、FINAL 与 argMax 的正确性和成本。 固定输入和基线 先在没有故障注入的环境执行上述配置,固定数据规模、并发度、运行时版本和预热时间。以「同键版本数」为主基线,记录值应满足「记录稳态基线」;同时保存 同键版本数、merge 延迟,使后续变化能够回到同一时间轴比较。

05

最后补充常见误区和使用边界。服务写入新版本后立即普通 SELECT,旧新两行尚未 merge,调用方随读取顺序拿到旧行。改用 version + argMax 读取当前态,并把明细与当前快照模型分开后语义稳定。 把后台 merge 当实时去重:同键版本数:显式 version 列。 ORDER BY 包含变化字段导致无法匹配旧版本:merge 延迟:高频读用 argMax/快照。 方案:更适合的场景:主要收益:代价与边界。 普通查询:允许重复行短暂存在的分析:速度最快:结果需容忍未合并版本。 SELECT FINAL:低频且必须获得替换视图:查询语义直接:大范围查询成本高。 argMax/物化当前态:高频按键获取最新版本:可控且无需全表 FINAL:查询或写入模型更复杂。 选型至少带上 日增量、分区规模、查询并发、扫描行数和压缩比,并用上面的量化基线验证;未知数据应明确为待测假设。