
1) 【一句话结论】
采用“写入层(Kafka+InfluxDB)+分析层(ClickHouse)的混合架构”,通过消息队列缓冲高写入压力(Kafka分区数10、副本数2),时序数据库保证高吞吐写入(InfluxDB按天分片),宽表支持多维度分析(ClickHouse列压缩zstd),结合最终一致性(1-5秒延迟,通过消息队列持久化+定期校验)满足业务需求。
2) 【原理/概念讲解】
老师口吻解释各组件:
3) 【对比与适用场景】
| 组件 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 消息队列(Kafka) | 分布式消息系统 | 高吞吐(百万级)、持久化(日志持久化)、异步解耦、支持分区扩容 | 缓冲业务写入,解耦业务与存储 | 需监控消费延迟,避免积压 |
| 时序数据库(InfluxDB) | 专为时间序列设计 | 高写入吞吐(每秒百万条)、按时间分片、支持聚合查询 | 用户行为日志(按时间统计,如点击、曝光) | 不适合多维度复杂查询,需定期清理历史数据 |
| 宽表(ClickHouse) | 列式存储分布式数据库 | 高查询性能(列式存储)、支持复杂聚合、列压缩优化 | 用户行为分析(按用户、时间、设备等维度) | 写入性能一般,需合理设计列存储 |
| 数据一致性策略 | 最终一致性 | 写入后1-5秒同步,通过消息队列持久化保证不丢失,定期校验 | 投放系统对实时性要求高,允许延迟 | 需定义校验机制(如时间戳、数据量匹配) |
4) 【示例】
用户点击事件写入流程:
SELECT user_id, COUNT(*) as click_count FROM user_click WHERE time >= '2023-10-01' AND time < '2023-10-02' GROUP BY user_id,ClickHouse列压缩用zstd。kafka_producer.send(topic="user_click", value=JSON.stringify({user_id:1001, ad_id:2001, device:"Android", time:"2023-10-01T10:00:00Z"}))influxdb.write(point="user_click", fields={user_id:1001, ad_id:2001, device:"Android"}, time="2023-10-01T10:00:00Z")clickhouse.query("SELECT user_id, SUM(click_count) FROM user_click WHERE time BETWEEN '2023-10-01' AND '2023-10-02' GROUP BY user_id")5) 【面试口播版答案】
面试官您好,关于用户行为日志的存储方案,我考虑采用分层架构。写入层用消息队列(比如Kafka)缓冲业务写入压力,避免写入阻塞业务;再通过时序数据库(比如InfluxDB)处理,因为日志是时间序列数据,时序数据库支持高吞吐写入(每秒百万条)和按时间聚合。分析层用宽表(比如ClickHouse),列式存储适合多维度查询,比如按用户、时间、设备分析点击量。对于数据一致性,我们采用最终一致性,允许写入后1-5秒同步到分析层,通过消息队列持久化(日志持久化、副本数2)保证数据不丢失,每小时定期校验一致性(检查Kafka未消费消息数与InfluxDB数据量是否匹配)。具体参数上,Kafka分区数设为10,InfluxDB按天分片,ClickHouse列压缩用zstd。总结来说,就是用消息队列解耦写入,时序数据库保证高吞吐,宽表支持分析,结合最终一致性满足投放系统的需求。
6) 【追问清单】
7) 【常见坑/雷区】