
1) 【一句话结论】
采用“埋点采集-消息队列-分布式实时计算-时序数据库”分层架构,通过Flink实现连续性指标(如MAU 30天活跃)计算,结合Kafka分区扩容、Flink并行度动态调整及时序数据库分片,支持活动期间弹性扩容,保障指标实时性与准确性。
2) 【原理/概念讲解】
老师口吻解释系统核心组件:
3) 【对比与适用场景】
| 组件 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 埋点采集层 | 游戏客户端/服务器SDK,上报用户行为事件 | 低延迟上报,支持自定义事件 | 游戏行为数据采集 | 适配多平台,过滤无效事件(测试用户等) |
| 消息队列(Kafka) | 分布式消息系统 | 高吞吐、持久化、解耦 | 埋点数据缓冲、异步处理 | 管理分区数、消费者组,避免数据积压 |
| 分布式计算引擎(Flink) | 流处理框架 | 低延迟、状态管理、容错 | 实时计算指标(DAU/MAU/留存) | 配置并行度(活动期间动态调整)、状态后端(如Redis) |
| 时序数据库(InfluxDB) | 专为时间序列设计的数据库 | 高效时间维度查询、聚合 | 存储实时指标(DAU/MAU) | 适合高频数据,不适合复杂关联查询,需优化索引 |
| 补偿任务 | 定时任务(如Cron) | 修复数据异常 | 处理延迟或丢失数据 | 低优先级运行,避免影响主流程 |
4) 【示例】
{
"userId": "user_001",
"event": "login",
"timestamp": 1672531200,
"gameId": "Honor of Kings",
"platform": "Android",
"sessionId": "session_123"
}
-- 定义状态:用户最近30天登录记录
SELECT
userId,
COUNT(DISTINCT DATE(ts)) AS active_days
FROM
user_events
WHERE
event = 'login'
GROUP BY
userId
HAVING
active_days >= 30
(注:实际Flink中需用keyBy(userId) + window(TumblingEventTimeWindows.of(Time.days(30))) + reduce聚合,确保连续30天有登录记录的用户被统计。)5) 【面试口播版答案】
“面试官您好,我设计的系统采用分层架构,核心是埋点采集通过SDK上报,然后通过Kafka消息队列解耦,再由Flink实时计算DAU等指标,存储在InfluxDB。具体来说,游戏客户端埋点事件(如登录、充值),通过SDK发送到Kafka,Flink消费并计算当天活跃用户(DAU),同时通过状态管理计算MAU(连续30天活跃用户),结果写入时序数据库。活动期间,我会通过扩容Kafka分区、提升Flink并行度(增加任务实例数和并行度)以及调整时序数据库的分片策略,快速支持高并发。数据一致性上,Kafka保证最终一致性,计算延迟通过缓存和补偿机制处理,确保指标准确性。”
6) 【追问清单】
TumblingEventTimeWindows.of(Time.days(30)))结合状态管理(如keyBy(userId) + reduce聚合),确保连续30天有登录记录的用户被统计。7) 【常见坑/雷区】