导语 | 腾讯外部每日都须要对海量的游戏营销流动数据做成果剖析,而流动参加人数的去重始终是一项难点。本文将为大家介绍腾讯游戏营销流动剖析零碎——奕星,在去重服务上的技术思路和迭代计划,心愿与大家一起交换探讨。文章作者:王方晓,腾讯经营开发工程师。
一、背景
奕星 (EAS) 是腾讯外部专一于游戏营销流动剖析的零碎,在营销流动成果剖析中,奕星遇到一个最大的问题就是对流动参加人数的去重,并给出对应的流动号码包。单个营销流动的周期是固定的,但流动与流动之间工夫很少会有完全相同的状况。
比方 A 流动工夫是 1 -10 号,B 流动是 5 -15 号,那么如果想别离失去 A 和 B 的去重参加人数,则必须别离开启工作对 A 和 B 在他们所属的工夫区间内进行计算去重。在海量日志中每天对数千个营销流动进行相似计算,对资源耗费是一个不小的挑战。
而理论状况下,须要计算的任务量还远远不止于此,奕星同时还提供游戏官网非流动链接的去重数据,甚至每个链接在每个推广渠道的去重数据,这个工作量级目前高达每天 50W+ 以上。
总结来看,面临的次要问题就是如何在海量数据的状况下,解决数量微小的而且周期各不相同的去重计算工作。
二、原有解决方案
对于这个问题,奕星之前尝试了不少计划,这里简略介绍一下。
1. 基于 TDW 长期表的计划
TDW 是腾讯外部通用的一站式大数据平台,服务稳固,功能强大。对于这些工作的计算,奕星最早是想借助于 TDW 的计算能力来实现。
思路很简略,就是在 pysql 中循环对每个流动执行对应的 hiveSQL 来实现 T+1 时效的计算。
但这个计划最大的毛病就是:工作根本都是程序执行,反复扫描大量日志,导致效率十分低下,而且从 HDFS 中拉取最终的去重文件也十分耗时。
尽管前面采纳多种思路优化,比方将原始日志先每天对立批量去重一次入到长期表里,所有计算基于长期表来实现等,但最终还是效率无奈进一步提高而放弃。
2. 基于实时计算 + 文件增量去重的计划
在奕星的数据统计中,基于 Storm 的实时计算工作,次要是提供各个流动的实时 PV 和参加次数等计数类数据。
因为内存资源无限,业界也有基于近似去重算法(如 hyperloglog)间接在 Storm 中算出近似去重后果的,但无奈给出准确的后果和最终的号码包文件,所以不合乎选型要求。
而内存资源无限,更不可能包容下这么大量的号码包数据,所以通过内存齐全得出最终准确去重后果的计划根本不事实。
但内存尽管不能包容整个流动期间的号码数据或者一天之内的号码数据,但是否能够包容 1 分钟,5 分钟的号码数据?
通过测试计算发现,在内存中缓存 5 分钟内的去重号码数据是齐全可行的,并且最高能够将原始日志升高 90% 以上的量级。缓存 1 分钟的话,最高也能够将原始日志升高 70% 以上的量级。
次要的起因是玩家参加流动的时候是即时参加行为,比方一个玩家来到一个流动页面后,个别是间断将流动中能参加的性能都参加下,不会参加完一个等很久再参加下一个,所以导致同一个玩家的日志工夫连续性较高,单位工夫窗口内去重后量级会升高很多。
基于此,目前奕星次要是基于 Storm 在单位工夫窗口内进行首次去重,以达到升高原始数据量级的目标。
最后的基于 TDW 的去重计划,除了反复扫描等问题外,还有一个问题就是:同一个流动不同日期之间的计算无奈前后连接,比方 A 流动在流动期间(1-10 号),每天的计算逻辑基本一致,都是要全量扫描 1-10 号之间的日志 (或两头后果) 来实现计算。
所以团队将眼光投向如何在流动后期去重的根底上来增量去重的问题上来。最终选定的计划是基于文件的计算计划,如下图所示,流动每天都滚动生成最新的去重号码包文件,而次日同一个流动的日号码包再与这个总包穿插后失去更新的号码包文件,如此反复,直到流动完结失去最终的流动号码包文件。
3. 基于实时计算 +LevelDB 增量去重计划
文件增量去重的计划,运行了一段时间后,就呈现了一个很大的问题:就是每日新增的文件量微小,日均几十万。
尽管没有达到把单台机器 inode 占满的状况,但在增量去重时,大量的小文件 IO 操作,导致增量去重效率非常低,最初被迫只反对高优先级业务的流动和单个流动参加量大于肯定阀值的大流动。
通过团队小伙伴的调研,最终将眼光锁定在 Google 的 LevelDB 上,LevelDB 是 Google 开源的长久化 KV 单机数据库,具备很高的随机写,程序读 / 写性能,然而随机读的性能很个别。
也就是说,LevelDB 很适宜利用在查问较少,而写入很多的场景,这正好合乎咱们号码包去重服务的利用场景。
另外号码包的存储自身也是一个 K - V 的存储,文件名为 key,文件内容为 value,正好跟 LevelDB 反对的 K-V 构造相似。
应用 LevelDB 后,能够毫秒级失去某个流动的精确去重人数,并且能够在 10 秒内导出千万量级的号码包文件,相比传统的文件操作,大大提高了号码包去重服务的整体效率。
三、基于 CLickHouse 的解决方案
尽管基于 LevelDB 的去重服务能够很好的满足大部分营销流动的人数去重需要。但扩展性较差,数据回溯艰难等问题比较突出,相似于基于预计算模式的 OLAP 零碎。比方零碎只反对流动整个期间内的去重人数计算,如果想晓得流动期间内某一段时间内的去重就无奈实现。
另外如果某个流动引入了脏数据后,只能将整个流动的 K-V 构造删除后重跑,十分耗时。团队通过调研后,将眼光锁定到基于 MPP 的 OLAP 计划上。
基于 MPP 的 OLAP 零碎,在数据库非共享集群中,每个节点都有独立的磁盘存储系统和内存零碎,业务数据依据数据库模型和利用特点划分到各个节点上,每台数据节点通过专用网络或者商业通用网络相互连贯,彼此协同计算,作为整体提供数据库服务。
绝对于基于预计算模式的 OLAP 零碎来说,它最大的长处就是灵便,扩展性强,而最大的毛病是响应工夫不及时,甚至须要较长的工夫期待。
而在营销流动成果剖析中,往往灵活性比效率要更加重要,或者说效率是能够略微斗争的一面,所以咱们抉择基于 MPP 的 OLAP 零碎。
目前市面上有很多优良的 OLAP 零碎,但要么是免费的(Vertica),要么是基于 hadoop 生态的(presto,Impala),整体架构比拟重。
而作为战斗民族开源神器的 ClickHouse 岂但领有本人的文件系统和极高的压缩比,在集群部署上甚至能够不必 zk 来独立部署,甚至在性能上“吊打”商业的 OLAP 零碎(详见官网测评数据:https://clickhouse.tech/benchmark/dbms/)。
综合以上思考,最终抉择了 ClickHouse,去重服务就变成了 SQL 查问,例如上面这条 SQL 就是查问 LOL 官网某个页面在 9 月 6 日这 1 天的 UV:
select uniqExact(uvid) from tbUv where date='2020-09-06' and
url='http://lol.qq.com/main.shtml';
在 24 核 96G 内存的机器上,理论测试下来在 1 亿条记录中,准确去重一个参加量为 100W 的流动,仅需 0.1 s 不到,而导出这个号码包文件只须要 0.2 s 不到。
尽管查问效率上比 LevelDB 有一点差距,但灵活性却大大提高,能够任意指定工夫区间和条件来做去重查问,合乎以后业务场景关注灵便度的需要场景,而且性能上从毫秒到秒级的提早根本也能够承受。
四、结语
去重服务的的问题随同奕星零碎整个开发和经营周期,期间经验过很多尝试,局部长期的尝试计划尚未在本文列出,但始终的出发点就是业务需要自身,并且联合过后的运维环境来选取对应的技术计划。
不谋求相对的高性能(象征老本也高),而关注最合适,易于扩容,搬迁,故障替换等有利于服务长期稳固经营的个性。当然,随着更多利器的呈现,也会去一直的尝试应用,毕竟科学技术才是第一生产力。
目前 ClickHouse 在奕星等多个数据系统和诸多个性化营销剖析的场景中落地应用,数据总规模超过 5 千亿,还在一直增长中。
本文只是通过对去重问题的历史回顾顺带简略介绍了一下 ClickHouse,更多对于 ClickHouse 的具体介绍和实操,能够自行搜寻官网文档和其余分享内容,最初欢送大家来评论区探讨 ClickHouse 无关的更具体的问题和利用场景。