基于Flink SQL 1.13通过登录日志实时计算游戏新用户数的方案咨询
基于Flink SQL 1.13实时统计游戏新用户的可行方案
核心需求本质为按game_id分组,对user_id做全局去重,仅保留每条user_id + game_id组合首次出现的记录,以此统计对应游戏的新用户数量,以下是可落地的实现方案:
方案1:内置近似去重统计(最推荐,无外部存储依赖)
- 利用Flink SQL内置的
approx_distinct()函数,底层基于HyperLogLog实现,默认误差率约1%,完全满足游戏新用户统计的业务精度要求 - 不需要依赖任何外部存储,所有计算在Flink内部完成,开发和运维成本极低
- 参考SQL示例:
-- 实时统计每小时各游戏的新用户数,误差1%以内 SELECT game_id, TUMBLE_START(login_time, INTERVAL '1' HOUR) as stat_time, approx_distinct(user_id) as new_user_cnt FROM login_log GROUP BY game_id, TUMBLE(login_time, INTERVAL '1' HOUR);
- 如果需要更高精度,可以调整函数的第二个参数调整误差率,比如
approx_distinct(user_id, 0.005)可把误差控制在0.5%,对应内存占用仅会有小幅提升
方案2:精准去重+RocksDB状态后端优化
如果业务要求100%精准统计,可选择无外部依赖的Flink原生方案:
- 状态后端选择RocksDB,开启增量检查点和LZ4/ZSTD压缩,状态存储在本地磁盘即可
- 用Flink SQL的去重语法,给
user_id + game_id的组合设置永久状态TTL(用户只要登录过一次对应游戏,永远不算新用户) - 参考SQL示例:
-- 筛选出所有游戏的新用户首次登录记录,可后续基于该结果做聚合统计 SELECT user_id, game_id, login_time FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id, game_id ORDER BY login_time ASC) as rn FROM login_log ) t WHERE rn = 1;
- 存储成本测算:按1亿个
user_id+game_id组合计算,每个组合仅需约20字节存储,总占用仅2GB左右,成本极低;如果量级达到十亿级以上,可优先选择方案1控制成本
方案3:外部存储优化方案
如果不想把状态长期存在Flink内部,可选择优化外部存储的存储成本:
- HBase优化:仅存
md5(user_id + game_id)作为rowkey,值仅存1字节的标记位,开启SNAPPY压缩,10亿条记录占用仅约10GB,远低于存全量登录日志的成本 - Redis非官方连接器:可以使用社区开源的Flink Redis SQL连接器,支持HyperLogLog的写入和查询,性能足够支撑大流量的登录日志处理
内容的提问来源于stack exchange,提问作者user2894829
相关产品推荐
相关产品推荐

