一、概述
WMDA是58自主开发的用户行为分析产品,同时也是一款支持无埋点的数据采集产品,只需要在第一次使用的时候加载一段SDK代码,即可采集全量、实时的PC、M、APP三端以及小程序的用户行为数据。同时,为了满足用户个性化的数据采集需求,在无埋点之上,WMDA又提供了手动埋点的数据采集方式。
WMDA支持的统计、分析功能主要包括:
- “概览”和“实时”模块用来监控网站的流量情况;
- “圈选”定义重要的指标;
- “单图”和“看板”可以统计不同维度、时间下指标的页面访问量和用户量等数据;
- “漏斗”和“智能路径”用于分析不同指标下的转化率;
- “留存”可以基于不同维度、分群来考察网站的用户流失率,分析用户的忠诚度;
- “用户细查”和“用户分群”用于分析所关心条件下的用户群体以及相关的用户行为明细。
以上简单的介绍了WMDA功能模块,接下来侧重于WMDA数据端的架构以及相关大数据技术栈的实践。
二、架构设计
在架构上,WMDA遵循标准的数据分析模型,将整体的架构分成数据采集、数据传输、数据建模/存储、数据统计/分析和数据可视化五个部分。架构如下图所示:
数据采集:58的业务方覆盖PC、M、APP三端以及小程序。WMDA在数据收集阶段为PC、M、H5、提供SDK完成数据采集,在APP端提供IOS SDK和Android SDK完成数据采集,小程序也有相应的SDK来完成数据采集。
数据传输:主要包括数据收集服务完成前端上报数据的信息补全、脏数据过滤、设备标识等,最后将数据格式化之后落地存储,通过Flume收集到Kafka中,完成实时总线和离线总线的拆分。
数据建模/存储:后端收集上来的数据经过ETL的清洗,将上报的数据格式化之后保存在HDFS上,供后续分析使用。同时Kafka分发一份数据到Spark Streaming中,进行实时数据分析。
数据统计/分析:除了Spark Streaming的实时分析外,落地到HDFS上的数据在Kettle的调度下,由OLAP子系统、Bitmap子系统、分群计算子系统、智能路径计算子系统完成单图、漏斗、留存、分群、智能路径的最终计算。
三、实时分析系统
实时分析系统用于解决用户监控网站、APP实时流量需求,采用SparkStreaming+Druid来实现。实时ETL程序中设置5s为Spark Streaming处理批次间隔,同时将圈选配置信息在实时ETL程序中定义为广播变量,完成指标id的实时匹配,最后将数据通过缓冲kafka摄入到Druid中。
四、离线分析系统
离线分析系统主要完成单图、漏斗、留存、智能路径、分群等数据分析工作,是WMDA的核心组成,也是数据建模/存储,数据统计/分析的具体实践。
基础数仓:使用HDFS作为存储系统,DW+DM+DA是标准的数据中台角度的数仓分层,同时基于基础事件模型(Event)搭建基础数仓。
Hive:完成基础数仓的核心ETL。
Spark+ETL:完成数据圈选规则匹配、脏数据的过滤和标准日志格式化。
离线计算集群:包括OLAP系统、Bitmap计算系统、分群计算系统、智能路径计算系统,主要完成单图、漏斗、留存、分群、智能路径相关计算工作。
Kettle:负责离线计算集群的调度。
TaskServer:任务执行系统,负责执行由Kettle调度的Hive sql任务、MapReduce任务。
数据服务接口层+回溯接口层:供可视化服务获取数据和指标变更回溯任务的触发。
离线计算逻辑复杂,保证系统容错性尤为关键,WMDA离线和实时数据系统都遵循Lambda架构,保证了系统较好的容错特性。
4.1 基于Kettle的任务调度系统
Kettle是基于java开源的ETL工具集,可以在windows、Linux、Unix上运行,数据抽取高效稳定。通过可视化界面设计ETL流程,无需代码去实现。在Kettle中,有两种基本的脚本文件job和transformation,job是完成整个工作流的控制,transformation完成针对数据的基础转换。在job下的start模块,有一个定时功能,可以每日、每周等方式实现对ETL任务的定时调度。
Kettle体系结构分为Kettle平台、各类插件,其中Kettle平台是整个系统的基础,包括UI、插件管理、元数据管理和数据集成引擎。UI显示Spoon这个核心组件的界面,通过xul实现菜单栏、工具栏的定制化,显示插件界面接口元素。元数据管理引擎kjb、ktr以及一些元数据信息,插件通过该引擎获取基本信息。插件管理引擎主要负责插件的注册。数据集成引擎负责调用插件,并返回相应信息。
Kettle是众多“可供插入的地方”(扩展点)和“可插入的东西”(扩展)共同组成的集合体。在Kettle中不管是以后的扩展还是系统集成的功能,本质上都是插件,管理的方式和运行机制是一致的。系统集成的功能也均是实现了对应的扩展接口,只是插接的方式略有不同。
Kettle的扩展点包括step插件、job entry插件、Database插件、Partioner插件、debugging插件等。
在Kettle中一个job代表ETL控制流中的一项逻辑任务。Job会按照连线的方式顺序执行,每个job产生一个执行结果,作为其他分支上job的条件。同时数据会从一个entry组件传递到另一个entry组件,并在entry组件中进行相应的处理。
在Kettle负责调度各个子计算系统ETL任务的同时,TaskServer负责任务的执行,这样使得任务的调度与任务的执行完全分离,方便任务的管理以及任务执行的灵活性。在Kettle中集成TaskSever相关的组件,需要关注Kettle中的两个接口:JobEntryInterface和JobEntryDialogInterface。JobEntryInterface是Job Entry插件的主要实现接口,主要的功能如下:
- 保存Job Entry设置
实现类使用私有变量保存设置的参数,通过get、set方法获取和设置。Dialog实现类会通过这些方法设置界面上的参数。同时,需要提供一个深度拷贝的方法,在保存的参数被修改时进行调用。
- 序列化插件
- 输出信息提供
一个Job Entry支持三种类型的输出:true、false和无条件。这三种情况不是所有的Job Entry都会同时支持,例如dummy job entry仅支持true和false。通过JobEntryInterface接口的evaluates()方法可以设置一个Job Entry的输出结果是否支持true和false,isUnconditional()方法则是设置是否支持无条件执行。
- 执行任务
JobEntryDialogInterface接口负责构建和打开参数设置对话框。
4.2 基于TaskServer的任务执行系统
TaskServer是一个高可用的、可扩展性强的分布式任务执行系统。整体架构采用Master-Slave的设计模式,支持横向扩展,兼备资源隔离、服务容灾等功能,为线上任务的运行提供可靠的执行环境。WMDA各个子计算系统中的Hive sql和MapReduce都在TaskServer上执行,极大的确保WMDA离线任务的稳定性。
TaskServer主要包括三个部分:JobTracker集群、TaskTracker集群和Zookeeper集群。
- JobTracker:负责任务接受、资源计算和任务分配。
- TaskTracker:负责任务执行和保持心跳。
- TaskQueue:任务队列。
- Zookeeper:协同调度。
在JobTracker中主要是资源的计算和任务分发,一个任务被提交之后会由JobTracker中的任务分发器(Dispatcher)发给对应的事件处理器(EventHadler),事件处理器完成之后会将任务相关的元数据信息写入到Zookeeper中。TaskTracker监听并拉取Zookeeper中新增的任务信息,抽象成TaskRunner放到线程池中运行,同时TaskTracker中任务调度器(TaskScheduler)跟JobTracker保持心跳用来更新机器信息。如果JobTracker监听到某一个TaskTracker宕机会重新进行任务分配,由其他的TaskTracker来执行。资源的隔离方面,TaskTracker中采用硬性资源划分机制和分时资源扩容机制。硬性资源是指资源被某种方式划分之后,就只会接受这一类任务。在TaskServer中就为WMDA的任务划分出来了WMDA Tier,只服务于WMDA提交的任务。分时资源扩容是指可以按照不同时间段来分担其他Tier的任务。比如,在9点到10点是WMDA任务量的高峰,划分的WMDA Tier不足以满足当前任务所需要的计算资源,此时利用分时资源扩容机制从Share Tier中扩容一些Tier来满足当前任务对计算资源的需求。
4.3 Druid在OLAP计算系统的实践
WMDA中主要涉及OLAP场景模块有概览、单图、即席圈选7日数据预览、热图、维度阅览以及用户行为统计。OLAP引擎在选择上尝试过kylin和Druid。Kylin采用预计算,因为数据已经提前计算好,所以在前端查询展示的时候相对较快。但是,因为WMDA支持多个维度任意组合,所以采用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将数据的索引节点划分为HistoricalNodes和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,BrokerNodes会请求Zookeeper获取集群内数据分布拓扑图,从而知晓请求应该发给哪些Historical Nodes以及Real-Time Nodes,汇总各节点的返回数据并将最终结果返回给用户。
4.4 Bitmap计算系统在WMDA中的实践
Bitmap是漏斗、留存和分群数据分析中,用来较快计算满足某些条件下用户数量的数据结构。Bitmap计算系统分为Bitmap计算模块和Bitmap检索模块,Bitmap计算模块通过MapReduce从基础日志中计算出指标Bitmap、维度Bitmap和分群Bitmap,并提交至WTable中。Bitmap检索模块则是通过BitMapEngine查询出符合查询条件的用户包。
五、总结
本文主要阐述了WMDA数据端的架构设计,主要从数据采集、数据计算、数据应用、调度系统等方面逐一进行了介绍。当然,大数据处理相关的架构以及技术选型并不是本文介绍的这一个方向,好的架构应该是根据具体的业务来设计的,而且是随着业务的拓展不断演变的。
欢迎大家关注“58架构师”微信公众号,定期分享云计算、AI、区块链、大数据、搜索、推荐、存储、中间件、移动、前端、运维等方面的前沿技术和实践经验。