题目重点:从每秒1亿点击请求的显式规模出发,估算网络与持久日志,设计可重放、可修正的广告统计链路。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 100M request/s按收到的点击事件请求量估算,不自动当作唯一有效点击或同等广告主查询QPS;有效点击、计费点击与反作弊审定口径分别定义。
- 训练dashboard按advertiser/campaign/ad/region与分钟小时窗口聚合,读结果有界延迟;计费需要可审计的最终结果,不能仅依赖近似实时计数。
解题路线
- 先算物理量:100M/s即每日8.64万亿事件。若单事件100B,payload约10GB/s、864TB/day,三副本约2.592PB/day,均不含协议/索引/压缩。若500B则50GB/s、4.32PB/day;容量选择必须以真实event size和保留天数为依据。
- 入口按region分流,接收eventId、adId/campaignId、eventTime、receivedAt与必要验证字段。客户端重试需稳定ID,身份/签名和速率政策在边缘先校验;只在耐久日志达到明确ACK条件后回accepted,入口崩溃不应丢已确认事件。
- 日志按可平衡的key/hash分区,别只按advertiser分区导致大广告主热点。若单分区实测可承受50k events/s,仅事件吞吐已需约2000分区,bytes/磁盘/复制/恢复还可能要求更多;这个数字是示例除法,不是任何产品的性能保证。
- stream consumer按eventId去重,再做event-time窗口与标签维度聚合。去重状态按时间范围保留:若10分钟窗口,满速潜在600亿ID,16B裸ID就960GB,hash表开销更多;要讨论分片、retry窗口、稳定source序号/批ID与保留政策,不能一句Redis set无限解决。
- 先按(partition,ad,timeBucket)局部聚合,再merge至广告主查询模型降低数据库逐事件写入。窗口允许迟到修正,watermark、版本与重算批次明确。高基数字段组合不能全立方体预聚合,保留常用rollup,临时分析走独立列式离线路径。
- 同一批重放避免重复加数:输出(partition,bucket,aggregateVersion)的幂等绝对值或事务提交offset+结果,不能重复increment总计。exactly-once需限定在具体日志/状态/输出边界,外部多系统仍要幂等与对账。
- dashboard返回asOf、窗口口径和provisional/final状态,禁止把待审点击显示成最终计费。原始日志分层存储、压缩并设保留期,回放验证实时结果;反作弊撤销/广告映射变更使用修正事件和版本化维度。
手动走一遍
某分片一分钟先发布v1=count100,ACK丢失后再次发布同v1,dashboard不能变200。晚到5个有效事件后发布v2=count105,消费者只接受更高版本;离线发现2个重复/无效点击发布修正最终103,并保留审计原因。跨分片合并时每个分片版本独立,不能把一个全局version混用。
规模与取舍
吞吐、网络bytes、耐久写带宽、去重状态与查询维度分别是约束。100M/s只有按区域/分区水平扩展才可行,节点数以实测S events/s与带宽计算至少ceil(100M/S)并加故障余量。日志积压恢复吞吐必须高于持续输入,否则恢复永远追不上;存储保留7天按100B裸payload即6.048PB,复制/压缩再单独计。
易错点与追问
容易失分的边界
- 把100M request/s当10M或忽略副本开销,架构容量会差数量级。
- 提前ACK内存队列,再把异步落盘称为已可靠接收。
- 按advertiser热点分区或每事件同步数据库increment,会遭单key/写放大瓶颈。
- 无限去重集合和全维度组合预聚合忽略状态爆炸。
继续深挖
- 某region失联时入口能否当地ACK继续?日志耐久、跨区灾难RPO与dashboard缺口如何定义?
- 反作弊延迟几小时才定案,实时可见量与计费最终量如何共存并向广告主解释差异?
