服务器 频道

货拉拉A/B实验分流算法实践

  业务背景

  货拉拉成立于 2013 年,成长于粤港澳大湾区,是一家从事同城、跨城货运、企业版物流服务、搬家、汽车销售及车后市场服务的互联网物流公司。截至 2022 年 4 月,货拉拉的业务范围已经覆盖了国内 352 座城市,月活司机达到 66 万,月活用户达到 840 万。

  这些业务线里面产生了非常多的业务场景,而大部分业务场景又有A/B实验的诉求,来支撑他们完成对产品、算法、策略的优化方向的选取。目前货拉拉A/B实验平台总计已经有200+业务场景、完成10000+以上的实验,当前月活实验达到1000+。

  A/B实验介绍

  A/B实验的基本思想其实非常简单——通过控制变量法,随机抽取一些样本进行实验组和对照组的对比实验,回收实验数据,通过统计学相关知识判断两组的优劣。而目前互联网行业的A/B实验设计基本上都是参考Google公司的经典论文:《Overlapping Experiment Infrastructure:More, Better, Faster Experimentation》。通过“层”,“域”的设计,从宝贵的线上流量中选择一部分,验证产品的某个新特性,回收数据,以此选择产品迭代方向。大胆假设,小心求证,用科学的方式让产品的每一次迭代都走在正确的道路上。

  货拉拉A/B实验平台架构设计

  上图是货拉拉A/B实验平台架构图。按照实验步骤可分为实验前、实验中、实验后三个步骤。

  • 实验前,用户在实验配置平台上完成实验的设计,包括实验生命周期、目标受众、分组配置、流量管理等等。

  • 实验中,在实验SDK中完成实验的分流、实时埋点数据、监控数据的上报,在实验配置平台通过实时/离线的数据链路进行回收展示。

  • 实验后,将回收的数据通过显著性分析,OLAP引擎计算等进行显著性报告、指标详情报告等的展示。按照模块划分实验配置平台、分流上报的SDK、数据回收链路。

  实验配置平台

  实验配置平台是用户操作的界面。在上面用户完成实验的所有设计工作,包括实验流量的划分、分流方式的选择、配置关注的指标、圈定实验的受众人群等等。实验配置平台还可以实时观察实验中的状态,实时的进组流量、分流异常监控告警、命中诊断等等。实验结束之后,用户也需回到实验配置平台,查看实验数据的各项报告,置信度报告、指标详情报告等,完成实验的最终效果评估。对于产品、分析师等同学而言,从始至终可以都在A/B实验配置平台上完成整个实验的闭环。

  分流上报SDK

  分流上报的SDK则是业务研发同学需要接入的,首先业务申请流量的分层ID,业务研发根据分层ID结合他们产品同学设计的A/B的实验,构造请求参数,分别调用SDK的命中分流接口和埋点上报接口,根据命中分流接口的返回结果编写业务代码,进行业务逻辑控制。埋点上报接口则是为了进行最终的实验效果评估使用。

  数据回收链路

  数据回收链路依赖于货拉拉大数据团队搭建的底层链路。最初的回收链路是将SDK上报到kafka的埋点数据通过飞流平台(大数据实时计算平台)的数据采集服务,写入原始数据表,再由大数据链路进行T+1日的指标计算任务,计算结果写入mysql,最后由实验平台进行展示。另外少量简单的实时指标则直接通过flink走实时链路计算,写入到mysql中。随着大数据OLAP引擎的完善,能支持10 亿数据秒级关联,所以目前A/B实验已陆续将所有指标都迁移到OLAP引擎实时计算。

  五种分流算法

  对于A/B实验而言,最重要的就是保证实验结果科学性。A/B实验的目的就是用科学的方式去帮助产品决策,如果实验结果不科学的话,则会误导产品决策,从而造成诸如用户流失等严重后果。而保证实验结果科学性的关键点在于,总样本的选择和对总样本的划分。比如要做一个某款香水的香味浓郁和清香哪个销量会更好的实验,如果该香水针对女性用户,那么总样本应该选择女性用户。在女性用户中,实验组和对照组中的女性应该尽可能保证“同质性”,所谓“同质性”就是保证对可能影响实验指标的因素,实验组和对照组应该是一致的。在该实验中,可能就是女性用户的年龄、收入等等可能影响购买该香水的所有因素。

  为了保证不同的组的样本的“同质性”,最简单的办法就是随机,将总样本完全随机分成不同组,基本上能保证不同组样本的同质。这也是业内目前最常见的A/B实验分流算法——随机分流。而货拉拉A/B实验平台根据自身的业务场景需求,为了加快实验收敛速度和保障实验结果科学性,又设计了其他4种分流算法,分别为:时间片分流、时间片轮播分流、指定顺序时间片轮播分流、时空分流。

  下面将对5种分流算法进行一一介绍。

  随机分流/增强随机算法

  随机分流算法是业内最常见的A/B实验分流算法,能够满足大部分A/B实验场景,比如广告投放、UI样式、营销派券等场景对A/B实验的诉求。随机分流算法的设计也较为简单,通过将分流ID(用户ID/司机ID等)随机分到不同组的任意一组即可,但需要特别注意的是,A/B实验一般都需要满足:进组的用户不再出组,即:同一个分流id,在不调整分组流量占比的情况下,无论多少次进入A/B实验,都应该在同一个分组。

  如何实现这个“随机”算法?货拉拉A/B实验第一版随机分流如下图左侧所示,根据实验的分组信息和分流配置,为每一个分组初始化一个分桶,桶中有100个坑位,按照该分组比例,将其中的部分的坑位赋值。将分流ID通过murmurs3 hash算法hash的整数mod100,得到0~99之内的整数,遍历不同组的分桶中,该整数所对应下标的坑位是否被赋过值,若有,则判定该id命中改组。由于hash和mod的过程不变,所以能满足进组用户不在出组,而经过调研,murmur3的hash算法能保证结果在32位整形数上面的随机分布。

  上述随机算法要做到“随机”需满足,murmur3的hash值在mod100之后,在100的区间内能均匀散列。然而由murmur3的hash算法,保证的是32位整形数上面的均匀散列,mod100之后,不一定能做到均匀。实际生产中也遇到在部分场景下,分流key出现散列不均匀的情况。若直接保存一个32位的桶,占用的内存又较大。于是参考一致性hash算法,虚拟一个32位的hash环来表示全样本范围,每个分组根据其所占用的流量占比在环上记录其区间边界位置,判定命中的过程第一步和上述普通随机一致,经过murmur3算法hash得到一个32位的整形数,顺时针在环上找到的第一个节点所属的组,即落在了某个分组的区间内,完成判定。

  时间片分流

  时间片分流也作为业内比较常见的一种分流算法,其原理和随机分流一致,唯一差别在于:随机分流的分流对象是用户唯一ID(司机唯一ID),而时间片分流的分流对象是一段段的时间片。这种分流算法的应用在某些业务场景并不关注单个用户的选择,更关注在一个时间片内所有用户的选择。假定时间片大小为1s,那么在这1s内所有的用户都会进入同一个组。同时将城市id加入随机因子中,就可以观察不同城市在一个时间片内用户分流情况的对比,计算业务评估指标。

  时间片轮播分流

  时间片轮播分流是基于货拉拉运力调度场景催生的、由货拉拉A/B实验团队独立实现一种分流算法。货拉拉许多业务场景的分流对象是订单ID,订单涉及司机、用户,会有明显高低峰期,并且在某个时间段订单的积压会影响下个时间段的订单指标。比如一个研究不同调度算法对订单响应率的影响的实验,如果采用随机分流,对订单进行随机采用某个调度算法,就无法观察到该调度算法在高峰期和低峰期的对比表现,也无法消除,高峰期订单积压后导致后续时间段响应率变动对实验结果产生的影响。又或许有人提出可以采用时间片分流,并将其时间片大小设置得大一点能够覆盖住一个高峰期和低峰期。但这样又带来的问题是,如果将时间片长度设置太大,样本流量就会不足,A/B实验就无法快速收敛。实验的周期就会被拉长。线上流量是很宝贵的,功能迭代的验证阶段也一般要求快速验证,显然单纯时间片分流是无法满足要求的。

  所谓时间片轮播,首先需要划分一个周期,比如一天(24*3600s),再指定时间片大小3600s,同时设置不同组占用的时间片的个数,那么分流SDK就会按照该所设置不同分组占用时间片的个数进行分流,保证一个时间片内所有订单进入相同组,并且在一个周期内,不同组占用时间片的比例符合预先的设定。

  时间片轮播的实现关键在于如何保证分布式场景下的分流结果一致。根据流量请求SDK的时间(也可以设定为订单的创建时间)计算出来该样本所处的某个周期内的时间片下标,在每个周期第一个时间片的请求到达的时候,生成本轮周期内时间片对应分组的分布,并采用实验特定标识作为hash因子,对时间片总个数取模的方式交换周期内时间片分布,起到打散时间片的作用。由于每个实验特定标识都是一样的,就能保证在任意节点,相同的周期内打散的结果是一致的,实现了分布式场景下的分流结果一致。

  时间片轮播自推出后广受调度场景、分单场景欢迎,根据该分流算法的实现方式撰写的专利也成为货拉拉公司首份授权专利。

  指定顺序的时间片轮播分流

  指定顺序的时间片轮播分流其实和时间片轮播分流的区别就在于,时间片轮播分流会对周期内的时间片分布进行打散,是一个“随机化”的过程。而指定顺序轮播的时间片序列,完全由用户自行指定,并且可以指定多个序列,相当于给周期外层再套一个轮转周期,第一个周期按照序列一进行轮转,第二个周期按照序列二进行轮转,以此反复,周而复始。

  也许有读者会好奇有了时间片轮播,为何还需要指定顺序的时间片轮播?适用于什么场景呢?

  其实答案在分析时间片分流的时候已经指出了:

  • 线上的流量是非常宝贵的

  • A/B实验需要快速验证

  用时间片作为分流ID带来的副作用就是很多独立流量被聚合成一个样本,比如用3600s作为一个时间片,那么一天相当于只有24个样本。样本量减少的情况,又要保证实验结果的科学性,那么就得延长实验时间,而这与上述第二点又是相悖的。时间片轮播分流相比时间片分流优化了纯时间片分流的随机性导致部分分组样本不足的情况,而制定顺序的时间片轮播则更为彻底的解决,完全由用户去制定周期内不同分组所占用的时间片顺序和比例,并且可以添加多个序列,不同时间周期采用不同序列,使A/B实验更快的达到收敛,满足结果科学性所需的样本。

  指定顺序的时间片轮播的实验相比于时间片轮播而言更简单,只需要计算出来流量所处在哪一个周期,以及周期里面时间片的序号,然后找到该序号和分组对应的结果即可。

  时空分流

  催生时空分流的业务是智能附加费场景,该场景关注不同起终点在不同时间段的附加费指标。该场景也推广到任何同时关注空间(起终点、距离、坐标等)和时间(高低峰、时间段)的业务上。还是以附加费场景介绍,对一笔订单附加多少费用,需要综合考虑该笔订单的起终点和当前时间段的订单情况(高低峰),通过A/B实验的时空分流就可以验证不同附加费策略在空间和时间上的分布的优劣表现。

  要观察不同空间上的表现,对空间对象(起终点OD对、距离、坐标、城市等)等等进行随机分流就可以实现,不过此时随机分流的分流对象不再是用户ID/司机ID/订单ID,而是空间对象。不同时间段(高低峰)上的表现情况则可以通过上述已经介绍过的任何一种时间片分流算法来实现观测。

  时空分流的实现比较特别,从严格意义上来说,并不是一种新的分流算法,而是通过组合两种分流算法去实现。可以理解为两层实验,流量在经过第一层的时候(空间随机分流),会被分成不同群(空间分群1、空间分群2等等),然后每一个群里面的流量会经过第二层(时间片分流/时间片轮播/指定顺序的时间片轮播),最终映射到某一个具体的组上,实施具体的策略。所以时空分流实际是通过一个双层实验,或者也称之为父子实验的方式来实现的。

  结语

  自此货拉拉A/B实验平台的基本架构设计和分流算法基本原理介绍完毕。基本架构设计和分流算法是货拉拉A/B实验平台的核心,但是对于货拉拉A/B实验平台,还有非常多的关键点:实验中的实时监控模块、实验的诊断告警模块、实验的指标体系、实验的分析报告模块、实验配置的下发模块等等,每一个模块单独拎出来可能都需要较多的篇幅去介绍。这些关键模块在整体架构下和分流算法一起组成了目前的货拉拉A/B实验平台,为货拉拉全业务场景提供A/B实验的能力,目前已完成了货拉拉业务线5000+以上的实验、15000+以上的实验版本,赋能业务、助力货拉拉业务更好更快的向前发展。

  当然,货拉拉A/B实验平台目前也存在着一些不足,对比于火山引擎等业内一流的A/B产品,在实验设计的便捷性和实验结果指标的丰富度上面仍有差距。由于是内部使用平台而非商用平台,目前对用户而言有一定的使用门槛,用户体验不是非常友好。在分流算法上,我们也缺少分流过程实时调优(多臂老虎机)等AI能力。我们会在未来继续迭代,重点关注实验结果科学性、稳定性、用户体验等方面,打造业内一流的A/B实验平台。

0
相关文章