51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个游戏用户行为实时分析系统,要求能够实时计算用户次日留存率、付费转化率等核心指标,并支持实时查询。请描述系统的架构设计,包括数据采集、处理、存储和查询模块,以及如何应对游戏活动带来的流量峰值。

游卡大数据开发难度:困难

答案

1) 【一句话结论】

采用“流计算(Flink)+实时数据库(ClickHouse)”混合架构,通过日志采集(Kafka)、实时窗口计算(Flink)处理用户行为数据,计算次日留存率(今天活跃用户数/昨天活跃用户数)、付费转化率等指标,存储后支持实时API查询,并配置弹性扩容(Kafka分区、Flink并行、ClickHouse分片)应对游戏活动流量峰值。

2) 【原理/概念讲解】

老师解释,系统分为四层:数据采集、流处理、存储、查询,并配置弹性资源。

  • 数据采集:游戏客户端通过SDK发送用户行为日志(如登录、充值、关卡完成),通过Flume或Kafka收集,形成实时数据流,日志先存入Kafka缓冲。
  • 流处理:使用Flink处理数据流,按用户ID分组,用滑动窗口(1天)计算指标,比如留存率(今天活跃用户数除以昨天活跃用户数),利用Flink的Exactly-Once语义保证数据一致性。
  • 存储:计算结果存入ClickHouse(列式存储,支持高并发查询),原始日志存入Kafka持久化。
  • 查询:通过REST API(如GET /metrics/retention?date=2023-10-01)实时获取指标。
    类比:数据采集是“管道”引入行为流,流处理是“流水线”实时计算指标,存储是“水库”支持快速查询,活动时管道扩容(增加Kafka分区)、流水线加闸(Flink并行)、水库分库(ClickHouse分片),确保高流量下低延迟。

3) 【对比与适用场景】

数据采集方式对比(日志采集 vs 数据库CDC):

方式定义特性使用场景注意点
日志采集(Flume/Kafka)通过SDK收集日志,写入消息队列实时性高,可扩展,支持复杂日志格式游戏实时行为(如点击、登录、充值)需处理日志格式统一,过滤无效数据(如无效用户ID、异常事件)
数据库CDC(Debezium)监听数据库变更,推送变更数据适用于关系型数据库,数据结构清晰,变更数据实时游戏用户信息变更(如等级、付费记录、用户属性更新)需数据库支持CDC(如MySQL Binlog),仅适用于结构化数据变更

4) 【示例】

次日留存率计算伪代码(含数据清洗):

// 数据清洗:过滤无效用户ID(不在用户表中)和无效事件
DataStream<UserEvent> events = kafkaSource()
    .filter(event -> event.userId != null && isUserValid(event.userId) && isValidEvent(event.eventType));
    
// 流处理:按用户ID分组,滑动窗口1天,计算留存率
DataStream<RetentionResult> result = events
    .keyBy(user -> user.userId)
    .window(TumblingEventTimeWindows.of(Time.days(1), Time.hours(0))) // 昨天的事件时间窗口
    .apply(new ProcessWindowFunction<UserEvent, RetentionResult, String, TimeWindow>() {
        @Override
        public void process(String userId, TimeWindow window, Iterable<UserEvent> input, Collector<RetentionResult> out) {
            long todayActive = 0; // 昨天登录且今天登录的用户数
            long yesterdayActive = 0; // 昨天登录的用户数
            for (UserEvent e : input) {
                if (e.eventType == "login" && e.timestamp >= window.getEnd() - Time.days(1)) {
                    todayActive++; // 今天活跃
                }
                if (e.eventType == "login" && e.timestamp >= window.getEnd() - Time.days(2)) {
                    yesterdayActive++; // 昨天活跃
                }
            }
            double retention = yesterdayActive > 0 ? (double) todayActive / yesterdayActive : 0;
            out.collect(new RetentionResult(userId, retention));
        }
    });
result.addSink(new ClickHouseSink()); // 存入ClickHouse

5) 【面试口播版答案】

面试官好,我来设计一个游戏用户行为实时分析系统。核心是构建“流计算+实时数据库”架构,用于实时计算用户次日留存率(今天活跃用户数除以昨天活跃用户数)、付费转化率等指标,并支持实时查询。

首先,数据采集:游戏客户端通过SDK发送用户行为日志(如登录、充值、关卡完成),通过Flume或Kafka收集,形成实时数据流,日志先存入Kafka缓冲。然后,流处理:使用Flink对数据流进行窗口计算,比如按用户ID分组,设置滑动窗口(1天),计算每个用户昨天是否活跃(昨天登录)以及今天是否活跃(今天登录),得到留存率;付费转化率则是付费用户数除以活跃用户数。处理结果存入ClickHouse(列式存储,支持高并发查询),原始日志存入Kafka持久化。查询时通过API实时获取指标,例如调用GET /metrics/retention?date=2023-10-01。

应对流量峰值:流处理引擎(Flink)配置高并行度,数据库(ClickHouse)分片,活动期间增加Kafka分区数或启用Redis缓存热点指标(如留存率、转化率),确保系统在高流量下仍能保持低延迟。这样既能保证实时性,又能有效应对游戏活动带来的流量冲击。

6) 【追问清单】

  • 问:系统如何保证数据一致性?
    答:通过Flink的Exactly-Once语义(结合Kafka幂等消费),确保每个事件只被处理一次,避免重复计算。
  • 问:如何处理冷启动或初始数据可用性?
    答:活动前用离线数据预计算初始指标,或启动时加载离线历史数据,保证系统启动后立即提供可用指标。
  • 问:指标计算逻辑是否正确?
    答:次日留存率计算为今天活跃用户数(昨天登录且今天登录的用户数)除以昨天活跃用户数(昨天登录的用户数),符合业务定义;付费转化率为付费用户数除以活跃用户数,逻辑正确。
  • 问:如何监控和应对流量峰值?
    答:设置监控指标(如Flink任务延迟、ClickHouse查询延迟、Kafka队列长度),活动期间自动触发弹性扩容(如增加Flink任务实例、ClickHouse分片、Kafka分区),并启用Redis缓存热点指标以减少数据库压力。

7) 【常见坑/雷区】

  • 坑1:数据清洗不足,原始日志包含无效用户ID或异常事件,导致指标计算错误。
  • 坑2:技术选型不当,使用传统关系型数据库,无法支持高并发查询,导致查询延迟高,影响实时决策。
  • 坑3:未配置弹性扩容机制,活动时计算延迟增加,影响用户体验和指标准确性。
  • 坑4:未考虑离线补全,活动结束后数据缺失,影响后续分析。
  • 坑5:指标计算逻辑错误,如将留存率计算为昨天活跃/今天活跃,导致业务理解偏差。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1