查看原文
其他

数据驱动增长:58无埋点用户行为分析实践之路

The following article is from 58技术 Author 黄海,黄世钱

用户行为分析,是利用用户访问网站、APP产生的相关数据,进行统计、分析来发现用户行为规律,进而结合这些规律制定合理的营销策略,或有针对性的对网站、APP进行优化,来提升用户粘性,提高运营效率,精细化运营需求。

58集团有着较为丰富的业务场景,包括了58同城、赶集网、安居客、中华英才在内的多款产品,覆盖了PC、M、APP三端。在用户行为分析方面,58各个产品或业务线都投入了大量人力到相关分析工作中。但依据人力投入情况的不同,数据分析的丰富度和准确度却不尽相同。考虑到业务线对用户行为的分析需求大体相似,我们自研了一款用户行为分析平台,WMDA。在解决用户数据统计、漏斗和留存等分析需求的同时,也能保证公司内部数据不外泄。

WMDA是一款支持无埋点的数据采集产品,只需在第一次使用时加载一段 SDK 代码,即可采集全量、实时的用户行为数据。同时,为了满足用户个性化数据采集的需求,在无埋点基础上,WMDA又提供了手动埋点的数据采集方式。同时支持PC、M和APP三端的数据采集。

WMDA支持的统计、分析功能主要包括:

  • “实时”和“概览”:用来监控网站的流量情况。

  • “圈选”:定义需要的重要指标。

  • “单图”和“看板”,统计不同维度、时间下指标的点击量和用户量等数据。

  • “漏斗”:用于分析转化效果,包括不同维度、分群的转化情况。

  • “留存”:用于考察网站或者APP的质量和保留用户的能力。

  • “用户细查”和“用户分群”:用于分析所关心条件下的用户群体大小,以及浏览这些用户的行为明细。

除此之外,WMDA可以为用户提供原始数据,方便用户结合后端日志进行更为精细化的数据分析。

WMDA当前处于业务接入的初期,日均分析日志数亿条,覆盖千万量级用户。

在架构设计和落地开发之前,产品的功能设计和用户行为模型设计都十分重要。所以,以下内容首先会针对WMDA的产品功能模型、用户行为模型进行介绍,然后对整体架构、前端数据采集、实时数据分析、离线数据分析等几个方面分别介绍。


一、产品功能模型

WMDA在产品设计上将功能划分为项目、应用、指标和数据分析四个部分。用户首先申请获得一个项目,项目之间的数据完全隔离。然后可以在项目下管理自己的应用,包括了Web、iOS和Android应用。用户在不同的应用下圈选获得指标,圈选就是将需要分析的关键元素告诉WMDA,是利用WMDA进行数据分析的第一步。在这些指标的基础上,WMDA完成了概览、实时、单图、留存、漏斗和分群的计算。


二、用户行为模型

WMDA将用户行为分为三级:会话->页面浏览->行为事件

  • 会话:用户访问一次网站或者APP定义为一个会话,一个会话包含多个页面浏览和行为事件

    • Web端:30分钟未产生新的页面浏览或者行为事件,则一次会话结束

    • APP端:APP切换到后台超过30秒,则一次会话结束

  • 页面浏览:当加载一个页面时,则产生页面浏览事件。一个页面浏览可以产生多个行为事件

  • 行为事件:在一个页面下所有的点击等操作算作行为事件

 


在用户标识设计上,考虑到像58同城、安居客等大部分用户浏览是不进行登录的。而英才这种招聘业务场景用户是需要登录到APP上才能查看招聘或简历信息的。所以,WMDA包括了两种用户标识,分别是访问用户和登录用户:

  • 访问用户:以设备为准,多个用户在一个设备上访问都算作一个用户

  • 登录用户:以账号为准,一个登录用户在多个设备上访问算作一个用户,需用户手动上传登录用户ID


三、架构设计

在架构上,WMDA遵循标准的数据分析模型,将整体的架构分成数据收集、数据传输、数据建模/存储、数据统计/分析和数据可视化五个部分。架构如下图所示。

 


数据收集:58的业务场景覆盖PC、M和APP三端,WMDA在数据收集阶段为PC、M和H5提供JS SDK完成数据采集。在APP端提供iOS SDK和Android SDK完成数据采集。

数据传输:主要包括一个数据收集服务,完成前端上报数据的信息补全、脏数据过滤、设备指纹生成等工作。最后将格式化的数据落地存储,通过Flume收集到Kafka中。

数据建模/存储:收集上来的数据经过ETL的清洗,将上报的数据格式化后保存在HDFS上,供后续分析使用。同时,通过Kafka分发一份数据到Storm,进行实时数据分析。

数据统计/分析:除了Storm的实时分析外,落地到HDFS上的数据在Azkaban的调度下,由OLAP子系统、Bitmap子系统、分群计算子系统完成单图、漏斗、留存和分群的最终计算。

数据可视化:WMDA通过Vue和58自研的Web框架WF完成可视化平台的搭建,最终通过数据分析统一的查询接口完成业务逻辑的组合,将分析结果清晰完整的展现给用户。

3.1 数据采集方案选型

对于用户行为分析,第一步也是最重要的一步就是数据的采集。数据采集质量的好坏将直接影响后续的数据分析质量。因此,我们对数据采集选型做了大量调研。前端数据采集上,业界主要包括代码埋点、可视化埋点和无埋点三种技术。下面来对这三种埋点技术逐一对比:

  • 代码埋点

    • 需要埋点处手动调用SDK数据采集接口

    • 简单、精准控制、方便设置自定义属性和时间

    • 埋点代价大,更新代价大,数据不全面,数据无法回溯

  • 可视化埋点

    • 使用可视化交互手段来代替写代码,通过网络更新配置和资源

    • 埋点和更新代价小

    • 覆盖的功能有限,不能设置自定义属性,数据无法回溯

  • 无埋点

    • 尽可能收集所有控件的操作数据,通过页面配置哪些数据需要分析

    • 数据可回溯,可获取启发性信息,开发工作量小

    • 不能灵活自定义属性,服务器和网络传输负载大

58各个业务线之前使用的大都是代码埋点,对于APP端依赖发版才能获得需要查看的数据,占用了产品、运营和研发人员大量的时间。但每个业务线都有一些个性化的数据需要采集。基于这些需求考虑,WMDA在采用无埋点的基础上,同时提供代码埋点的数据采集手段。既可以满足产品和运营同学随时获取分析数据的需求,又能满足用户个性化数据采集的需求。

具体实现上,在APP端,SDK为每个事件绑定一个回调函数,当事件被触发时通过回调函数获取当前的事件信息,并保存在本地。在用户网络允许的情况下,采集的信息会上报到后端服务器完成数据采集。在Web端,SDK通过捕获和冒泡两种消息传递机制获取事件信息,并即刻上报事件完成信息采集。

3.2 圈选

采用无埋点方案后,用户所有的行为数据都会被收集到数据服务器上进行保存,但是并不会全部进行分析。用户需要通过圈选操作,告诉WMDA对哪些关键元素进行匹配,聚合日志数据进行分析。

考虑到用户的需求,圈选可以是页面,可以是一个元素或同类的一批元素,也可以是列表页某个位置的帖子。为了满足这些圈选的需求,在Web端,WMDA通过Domain、Path、Query、XPath、Value、Index和Link这7个元素的组合去找到用户关心的数据进行分析。APP端,WMDA通过AppPage、ElemPath、Value和Index的组合去完成圈选。

圈选实现上,Web端圈选相对简单,用户分析平台对所有Web端网站相当于一个浏览器,WMDA可以获得网站的Dom树结构。然后将Dom树的叶子节点及其父节点作为可圈选的节点,用Dom树结构拼接XPath就可以唯一标识一个元素了。

对于APP端,考虑到用户操作的方便性。WMDA通过在用户行为分析平台扫描二维码唤醒APP,用户在手机端操作APP的同时,停留页面的截图以及页面上元素的坐标和元素信息会以秒级的速度,通过WebSocket协议同步到后端MySQL数据库保存。用户行为分析平台通过轮询从MySQL数据库中获得截图、元素坐标、元素路径、元素Value、元素Index等关键信息,并将APP页面截图展示在用户分析平台上,这样用户在平台上即可完成操作,获得圈选关键因素完成圈选。

 


除了无埋点数据分析,代码埋点数据同样也需要数据分析。我们通过手动添加代码埋点配置,告知一个埋点的名称和对应的EventID,就可以统计每个EventID对应的事件量和用户量。如果在手动埋点中用户自带了自定义事件,也可以配置相关的自定义事件为维度,使用户可以进一步了解该维度下的流量细分情况。

针对58实际的业务场景,一个手动埋点包含了多个自定义事件,每个自定义事件可以做维度分析或累加和分析。维度分析是指根据自定义事件上传的Key-Value,分析不同Value下手动埋点的事件量和用户量;累加和分析是指,统计一个Key对应Value在一段时间内的累加总和,常常用于视频通话、IP电话统计时长等场景。

3.3 数据收集服务

数据收集服务作为前端采集和数据分析的纽带,主要完成了用户注册、APP端配置下发、时间纠错、信息补全、爬虫标记等主要功能。

  • 用户注册:考虑到UUID生成策略灵活调控,WMDA的UUID采用服务端下发的方式来完成。APP端需要保证APP更新、卸载重装等UUID不变,那么Android端以IMEI或Mac为凭证进行UUID的计算,iOS端则以IDFA和OpenUUID为凭证计算UUID。对于Web端,因为有一定重合率的问题,我们采用随机生成UUID,前端本地保存的方式来标识一个Web端用户。当然,为了满足个性化需求,三端SDK也支持用户使用自己的UUID来代替我们服务端下发的UUID。

  • 配置下发:对于APP端,考虑不同业务场景对数据采集间隔、数据采集量有着不同的要求。WMDA开发了APP配置下发功能。用户可以在平台上针对不同APP版本配置上报数据量、时间间隔、是否采集数据等关键因素进行配置,进而控制用户APP数据采集的行为特性。甚至可以关闭一个APP版本的数据采集。

  • 时间纠错:无论是Web端还是APP端,终端的时间都是不可信的,比如一个新的手机在没有配置时间的情况下访问了你的网站或者APP。为了解决这个问题,数据收集服务计算数据上报时间与收到数据的时间差,并使用时间差校正事件发生时间和数据上报时间,进而解决终端时间不可信的问题。

  • 信息补全:通过IP补全国家/省份/城市、补全58同城表现类全路径等信息

  • 爬虫标记:根据UA里面的Spider标记是否为爬虫请求,供数据分析时过滤

3.4 实时分析系统

实时系统用于解决用户监控网站、APP实时流量的需求,采用Storm+HBase来实现。实时分析系统设计每5分钟为一个窗口期,Storm中保留2个窗口期,当前窗口期和上一窗口期。从Kafka中获取的实时数据,根据时间戳找到对应的窗口期,将PV和UV累加到相应的事件索引中,时间戳不在两个窗口期的数据将被丢弃。当前窗口期时间到达时,如下图1:10分,Storm会将上一个窗口期(1:00-1:05)的数据写入HBase,并创建一个新的窗口期作为当前窗口期,而原当前窗口期就变成了上一个窗口期。这样设计是为了避免数据延时到达带来的数据不准的问题。

 


3.5 离线分析系统

离线系统主要完成了单图、漏斗、留存、分群等数据分析工作,是WMDA的核心组成,也是数据建模/存储、数据统计/分析的具体实践。

 


Dw+Dm+Da:底层使用HDFS进行存储,是标准数据仓存模块。

Spark+ETL:完成数据圈选规则匹配、脏数据清洗和标准化日志格式适配。

Azkaban:负责离线系统任务调度。

离线计算集群:包括OLAP系统、Bitmap计算系统、明细列表系统、分群计算系统,主要完成单图、漏斗、留存、分群的计算分析工作。

数据服务接口层+回溯接口层:供可视化服务获取结果数据和指标变更回溯任务触发。

离线计算逻辑复杂,保证系统容错性尤为关键,WMDA离线和实时数据系统都遵循Lambda架构,保证了系统较好的容错特性。

3.5.1 回溯调度实现

无埋点的一个主要优点就是圈选即可回看历史7天数据,那么就需要一套完善的回溯调度系统来支持。

回溯调度系统每30分钟从后端服务获取最近一个周期新建或变更的指标、单图和分群,放入待执行队列中。考虑到正在执行的回溯任务可能执行超过30分钟,回溯调度系统设计了正在执行队列和待执行队列两个队列。待执行队列中保存一个待执行任务,当正在执行的任务完成后,待执行队列中的任务进入正在执行队列开始计算。如果一个新任务到达时,待执行队列中仍有任务未进入执行队列,那么两个待执行任务将合并为一个任务等待执行。

因为分群、单图和Bitmap计算都依赖于基础数据,而分群可以指定依赖某个指标,所以回溯任务在执行时依照基础数据先回溯,再回溯单图和指标Bitmap,最后回溯分群的顺序执行。当然,如果指标没有被创建和修改,那么分群就不必依赖基础数据和指标Bitmap的回溯任务,而并行计算。

 


3.5.2 OLAP模块在离线计算中的应用

OLAP模块主要完成概览、单图、即席圈选7日PV、维度阅览及用户行为统计。OLAP在选型上尝试过Kylin和Druid。Kylin采用预计算,因为数据已经提前计算好,所以在前端查询展示的时候相对较快。但是,因为WMDA支持最多任意5个维度的组合,所以采用Kylin需要根据不同组合情况进行计算,这就使得随着维度的增加,计算量指数增大。而产品和运营人员在使用的时候往往不会涉及如此多的组合,这就造成了一定的资源浪费。Druid则需要根据查询条件即时计算,查询相比Kylin慢,但是优化后基本在1秒以内。WMDA最终基于Druid实现OLAP模块,其包括的角色有:

  • Real-Time Nodes:负责实时数据处理 

  • Historical Nodes:负责加载非实时窗口内满足加载规则的所有历史数据Segment

  • Coordinator Nodes:负责Druid集群中Segment的管理与发布,包括加载新Segment,丢弃不符合规则的Segment,管理Segment副本以及Segment负载均衡

  • Broker Nodes:整个集群的查询入口,提供查询路由和结果组装

  • Indexing Service:负责“生产”Segment的高可用、分布式、Master/Slave架构服务

 

Druid将数据的索引节点划分为Historical Nodes和Real-Time Nodes,切割了历史数据的加载与实时流数据处理,因为二者都需要占用大量内存与CPU;另一方面,划分Coordinator Nodes和Broker Nodes,切割了查询需求与数据如何在集群内分布的需求,确保用户的查询请求不会影响数据在集群内的分布情况。

在时间窗口内的数据会停留在Real-Time Nodes内存中,而时间窗口外的数据会组织成Segment存储到Deep Storage中;批量数据经过Indexing Service也会被组织成Segment存储到Deep Storage中,WMDA使用HDFS作为Druid的Deep Storage,同时Segment的元信息都会被注册到元信息库中,Coordinator Nodes会定期(默认为1分钟)去同步元信息库,感知新生成的Segment,并通知在线的Historical Node去加载Segment,Zookeeper也会更新整个集群内部数据分布拓扑图。 

当用户需要查询信息时,会将请求提交给Broker Nodes,Broker Nodes会请求Zookeeper获取集群内数据分布拓扑图,从而知晓请求应该发给哪些Historical Nodes以及Real-Time Nodes,汇总各节点的返回数据并将最终结果返回给用户。 

3.5.3 Bitmap计算子系统在WMDA中的实践

Bitmap是漏斗、留存和分群数据分析中,用来较快计算满足某些条件用户数大小的数据结构。主要包括指标Bitmap,维度Bitmap和分群Bitmap。比如漏斗计算中,需要得到满足某个维度下指定指标的用户数,那么我们就用维度Bitmap和指标Bitmap取交集即可得到同时满足两个条件的用户数大小。

Bitmap基于开源包Roaring Bitmap实现。与EWAH、Concise Bitmap等开源Bitmap框架使用RLE压缩算法不同,Roaring Bitmap是将32位的int整数分割成2的16次方个整数的数据块来共享相同的16个最高有效位,使用专门的容器来保存它们的16个低位。 

当一个数据块内整数不超过4096个时,采用面向稀疏数据块的数组容器(ArrayContainer)。当超过4096个整数时,使用面向密集数据块的位图容器(BitmapContainer)。ArrayContainer用容量为4096的short[]数组存储真实低位数据以减少数据获取时的开销。BitmapContainer中则定义了长度为1024的long 型数组存储bit数据,每个long型值占用64位。1024个值刚好是1024×64 = 65536位,等于一个长度为4096*16的short[]数组空间大小。使用BitmapContainer存储可以在保证数据空间使用量的同时,减少short数组过长导致的查找和位移过多造成的资源开销。

当前Roaring Bitmap被使用于Spark、Kylin、Lucene、Druid.io等主流开源框架中。相比较于EWAH、Concise Bitmap而言,Roaring Bitmap具有压缩率高、乱序添加速度快、支持bit元素遍历等优点。


四、后记

以上是58对用户行为分析做的一次探索和实践,更为深入的技术细节和实践中遇到的问题不做深入的探讨,欢迎感兴趣的同学进一步交流。WMDA当前仍处在业务发展的初期,为了服务更多的58业务,WMDA已完成百亿数据量的测试,相信WMDA会成为提升58产品质量和运营效率的重要武器之一。


觉得内容还不错的话,请分享给更多的朋友哦












▼ 福利时刻 ▼ 


01. 公众号后台回复「06」领取「数据仓库」「数据治理」等经典电子书籍或视频赠送。


02. 如要获取《大牛带你从0到1建设数据仓库》实战高清PPT或数仓实战视频,请关注公众号后添加小助手微信[ IDiom1128 昵称:紫霞仙子],备注:PPT。

03. 高手如云,拉您入群「数仓BI」,「Python」、「资料分享」,公众号后台回复:加群。技术大佬们在等你,各种资源定期分享~


Q: 关于数据仓库,你还想了解什么?

欢迎加群与大家分享

觉得不错,请把这篇文章分享给你的朋友哦

加群请联系小助手:iom1128『紫霞仙子』

更多干货、福利,请在后台点击“数仓之路”查看

 

 

关注不迷路~ 各种福利、资源定期分享

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存