背景概述

在互联网电商平台上,广告是提升成交总额(GrossMerchandise Volume)和拉取新客的常见途经。在广告系统或广告运营中都需要基于人群数据分析进行定向的用户广告投放。在第三方平台进行广告投放,同样需要使用人群数据分析计算。根据计算分析方的不同,可以分为两类,第一类是基础数据全部发送给第三方广告平台,如抖音,腾讯等,由第三方在投放人群时候进行人群计算并作选择;第二类是人群计算工作在电商平台内部完成,推送给第三方的只是单个的人群包数据(设备数据)。在唯品会,我们目前采用第二类方式进行人群计算投放。我们每天需要完成数万的人群包计算,这些计算都是基于几张位于HDFS的之上的Hive表完成,这些表每天通常都行需要被访问上万次。

原先架构及场景问题分析

在原先的架构中,我们的YARN与HDFS集群是计算存储混布的。一个节点即是存储节点同时也是计算节点。支持人群计算的引擎包括HiveMR和Spark,其中Spark任务占比90%左右。所有人群计算需要的基础数据是T-1的离线数据。这些基础数据正常情况下,在每天的8:00能够准备完成。考虑到广告具有一定的及时性要求,这里需要在每天人群计算的20:00前运行完成。

唯品会商品数据分析工具 唯品会数据分析案例_spark

图1:人群计算架构现状(DMPapp代表人群计算的YarnContainer)

原有运行架构中如图1所示。在集群相对稳定的情况下,一个人群计算任务的执行时间约3分钟。在集群不稳定的情况下,执行时间的变化会比较大,具体部分运行时间如下图2所示。在这种情况下,计算任务的资源消耗比正常情况大很多,大约能达到30/3=10倍左右,同时人群计算也难以达到业务时间要求(20:00前运行完成)。

我们将运行不稳定的原因总结为以下几个方面:

  • 人群计算任务的数据本地性不好。
  • 在单个节点计算热点数据,交换机80G上下行带宽也常常打满(DN节点双万兆网络)。
  • HDFS读写本身存在长尾现象。
  • 唯品会商品数据分析工具 唯品会数据分析案例_大数据_02

  • 图2:人群数据在HDFS集群上的运行情况

新的架构方案

为了更好地满足热点数据的计算需求,我们需要取得较好的数据本地性。因此,我们希望能够达到以下目标:

  1. 计算与存储同置,这样数据就不需通过网络反复读取,造成网络流量浪费。
  2. 减少HDFS读写长尾对人群计算造成的额外影响,同时减少人群计算对于HDFS稳定性的影响。
  3. 广告人群计算介于线上生产任务跟离线任务之间的任务类型。这里我们希望能保证这类应用的可靠性和稳定性,从而更好地为公司业务赋能。

为了达到上述三点目标,我们设计了基于Alluxio部署架构方案,具体如图3所示。

唯品会商品数据分析工具 唯品会数据分析案例_hdfs_03

图3:Alluxio与Spark计算节点混布的架构方案

我们基于HDFS的缓存有两套Alluxio集群(另外的团队也部署了一套Alluxio)。所有人群计算任务都是基于数据服务进行调用的。所以我们在数据服务的计算集群上面单独部署了Alluxio集群。为了使数据服务的数据访问在任何情况下不影响HDFS集群的数据读写。我们采取的方案是新建一张表(库名不同,表名称一致),新建的表通过AlluxioUFS指向原hive表在同一个HDFS物理地址,避免数据拷贝以及不一致性。通过在运行SQL前对SQL进行改写,使其能够读取数据服务计算集群的Alluxio的数据。进一步地,我们还希望两套Alluxio集群上的数据能够互相访问。当前官方(https://docs.alluxio.io/ee/user/stable/en/deploy/Running-Alluxio-On-a-HA-Cluster.html)并没有给出类似HDFS federation如何兼容两套Alluxio集群的配置方式,因此我们采用了如下方式进行了部分workaround。首先,我们的主Alluxio集群的配置基于官方标准进行,在spark配置文件中加入:

spark.executor.extraJavaOptions-Dalluxio.zookeeper.address=******:2181, 
******:2181,******:2181-Dalluxio.zookeeper.leader.path=/alluxio/leader-Dalluxio.zookeeper.enabled

数据通过mount UFS指向HDFS路径,在需要将Hive表数据存放到Alluxio时,修改Hive表的metastore,使其地址指向Alluxio即可。具体地,我们采取的方式是将数据服务Alluxio集群上HiveMetastore的location设置为:
alluxio://zk@zkHost1:2181;zkHost2:2181;zkHost3:2181/path。

在这样的配置下,我们能够实现所有主Alluxio集群的数据都可以由Hive、Spark、Presto访问。数据服务Alluxio集群的数据可以通过Spark进行访问。但是当前Hive,Presto 还不能访问数据服务Alluxio集群的数据。

在新的架构下计算的效果如图4,

唯品会商品数据分析工具 唯品会数据分析案例_hadoop_04

图4:基于Alluxio新架构下的部分计算性能展示

线上SQL实验测试分析

测试环境:1.92TSSD, 40C, 10000M/s 网络。10台物理机(1)100个线上SQL,每个SQL执行五次。

唯品会商品数据分析工具 唯品会数据分析案例_hadoop_05

(2)500个线上SQL,每个执行1次。

唯品会商品数据分析工具 唯品会数据分析案例_大数据_06

线上测试结论:Alluxio 提速效果还是不错,基本都能够达到10 %以上,有些查询性能甚至能够提升 30%。

Alluxio带来的优势与总结展望

基于Alluxio的新架构解决了HDFS热点数据的读取问题,从而使得广告人群计算这类准生产应用也能得以保障,实现了技术赋能业务。另外,计算效率的提升也对带来了可观的资源的节约,额为支撑的硬件只是少量SSD盘。

目前,我们只是利用Alluxio解决单纯的HDFS热点数据读取问题。我们通过社区学习到其他公司很多很好的Alluxio使用场景也非常适合我们,后续我们将继续探索如何更好地结合实际情况来使用Alluxio进行稳定以及加速。当然,文中提到的我们场景下的多Alluxio集群的互访问题需要进一步解决。