Ads Staff · HM/Technical Discussion

Apple Ads:反规范化与缓存如何降低数据库读延迟

先拆解读路径和慢查询,再比较预计算字段、物化视图、缓存键与失效策略。

题目重点:先拆解读路径和慢查询,再比较预计算字段、物化视图、缓存键与失效策略。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练场景为读取一个广告活动概览,需要活动元数据、最新预算与聚合指标;此对象只是例子,不代表原 Apple Ads 系统。
  • 优化目标应具体到 P95/P99 延迟与正确性窗口,并同时监控写入成本、缓存命中、数据新鲜度和存储量。

解题路线

  1. 先用真实 trace、查询计划和慢日志定位瓶颈:过滤/索引、join、网络往返、计算聚合或热点锁。能加合适索引/批量取数时先验证,避免直接引入重复数据。
  2. 若读路径持续重复跨表 join 或聚合,可在写侧维护按 campaign_id 的读模型/物化汇总;定义更新事务或 CDC 流、版本号、迟到事件修正与重算机制。
  3. 缓存时明确 key 包含租户、权限与影响表示的参数,值带版本/TTL;写入可选择失效或按版本更新。TTL 只是容忍过期窗口的上界方案,不保证立即一致。
  4. 用 singleflight 或请求合并抑制热 key 失效后的回源风暴;负缓存和容量淘汰防穿透。故障时退回数据库并限流,避免缓存失效放大主库压力。
  5. 上线前后按相同负载测 P95/P99、DB CPU/IO、命中率和 stale-read 率;用 shadow read 比较新旧读模型,异常时可切回。

手动走一遍

原查询每次 join 活动、预算与小时统计;训练方案把小时汇总预先写入按活动 ID 的读模型,页面再查缓存。预算变更写成功后先更新版本/失效缓存;指标允许几分钟延迟则在 UI 标注数据截至时间。若预算要求强一致,则不能无条件读旧缓存。

规模与取舍

读路径从多表 join/聚合成本降到一次索引读取或命中缓存,但写放大、物化存储与一致性维护上升。热 key 的读 QPS、写频率、汇总维度和过期容忍度决定实际收益,题目未明确数值。

易错点与追问

容易失分的边界

  • 只说加 Redis,没有定义键、失效和新鲜度。
  • 把广告预算这类可能需强一致的数据与可延迟指标混为一谈。
  • 反规范化后忽略回填、迟到事件和数据修复。
  • 缓存 key 漏租户/权限,造成跨用户数据暴露。
  • 仅看平均延迟,遗漏 P99、数据库回源和失效风暴。

继续深挖

  • 预算与展示统计要求不同一致性时如何拆读模型?
  • CDC 消费失败/重复时汇总如何幂等修复?
  • 缓存节点全失效时数据库如何保护?
  • 什么情况下合适的复合索引比反规范化更好?
✓已复制微信号!