大发一分彩 首页 > 学霸

每天数百亿用户行为数据,美团点评怎么实现秒级转化分析?

2019-10-07 06:23 Hadoop技术博文

导读

用户行为分析是数据分析中非常重要的一项内容,在统计活跃用户,分析留存和转化率,改进产品体验、推动用户增长等领域有重要作用。美团点评每天收集的用户行为日志达到数百亿条,如何在海量数据集上实现对用户行为的快速灵活分析,成为一个巨大的挑战。为此,我们提出并实现了一套面向海量数据的用户行为分析解决方案,将单次分析的耗时从小时级降低到秒级,极大的改善了分析体验,提升了分析人员的工作效率。

本文以有序漏斗的需求为例,详细介绍了问题分析和思路设计,以及工程实现和优化的全过程。

问题分析

下图描述了转化率分析中一个常见场景,对访问路径“首页-搜索-菜品-下单-支付”做分析,统计按照顺序访问每层节点的用户数,得到访问过程的转化率。

统计上有一些维度约束,比如日期,时间窗口(整个访问过程在规定时间内完成,否则统计无效),城市或操作系统等,因此这也是一个典型的OLAP分析需求。此外,每个访问节点可能还有埋点属性,比如搜索页上的关键词属性,支付页的价格属性等。从结果上看,用户数是逐层收敛的,在可视化上构成了一个漏斗的形状,因此这一类需求又称之为“有序漏斗”。

这类分析通常是基于用户行为的日志表上进行的,其中每行数据记录了某个用户的一次事件的相关信息,包括发生时间、用户ID、事件类型以及相关属性和维度信息等。现在业界流行的通常有两种解决思路。

from(selectuuidid1, timestampts1 fromdatawheretimestamp>= 1510329600andtimestamp< 1510416000andpage = '首页') t1

leftjoin

(selectuuidid2, timestampts2 fromdatawheretimestamp>= 1510329600andtimestamp< 1510416000andpage = '搜索'andkeyword = '中餐') t2

展开全文

ont1.id1 = t2.id2 andt1.ts1 < t2.ts2 andt2.ts2 - t1.ts1 < 3600

leftjoin

(selectuuidid3, timestampts3 fromdatawheretimestamp>= 1510329600andtimestamp< 1510416000andpage = '菜品') t3

ont1.id1 = t3.id3 andt2.ts2 < t3.ts3 andt1.ts1 < t3.ts3 andt3.ts3 - t1.ts1 < 3600

funnel(timestamp, 3600, '首页') stage0,

funnel(timestamp, 3600, '首页', '搜索', keyword = '中餐') stage1, funnel(timestamp, 3600, '首页', '搜索', '菜品') stage2

fromdata

wheretimestamp>= 1510329600andtimestamp< 1510416000groupbyuuid

对于第一种解法,最大的问题是需要做大量join操作,而且关联条件除了ID的等值连接之外,还有时间戳的非等值连接。当数据规模不大时,这种用法没有什么问题。但随着数据规模越来越大,在几百亿的数据集上做join操作的代价非常高,甚至已经不可行。

第二种解法有了改进,通过聚合的方式避免了join操作,改为对聚合后的数据通过UDAF做数据匹配。这种解法的问题是没有足够的筛选手段,这意味着几亿用户对应的几亿条数据都需要遍历筛选,在性能上也难以接受。

那么这个问题的难点在哪里?为什么上述两个解法在实际应用中变得越来越不可行?主要问题有这么几点。

基于上述难点和实际需求的分析,可以总结出几个实际困难,称之为“坏消息”。

另一方面,还是能够从问题的分析中得到一些“好消息”, 这些也是在设计和优化中可以利用的点。

如果用一句话总结这个问题的核心本质,那就是“多维分析和序列匹配基础上的去重计数”。具体来说,最终结果就是每层节点符合条件的UUID有多少个,也就是去重后的计数值。这里UUID要符合两个条件,一是符合维度的筛选,二是事件序列能匹配漏斗的定义。去重计数是相对好解的问题,那么问题的重点就是如果快速有效的做维度筛选和序列匹配。

算法设计

下图是部分行为日志的数据,前面已经提到,直接在这样的数据上做维度筛选和序列匹配都是很困难的,因此考虑如何对数据做预处理,以提高执行效率。