4万字《腾讯云技术实践精选集 2021》发布,点击下载 了解详情
写点什么

天猫 App A/B 测试实践

  • 2016 年 3 月 20 日
  • 本文字数:3073 字

    阅读完需:约 10 分钟

在一篇文章《天猫App 的动态化配置中心实践》中我们聊了关于Native App 动态化的问题。无疑Native 的动态化能力较Web 要弱很多,很多操作是依赖版本节奏的。这就导致在Native App 上许多决策无法快速验证,对存在不足的逻辑没办法快速修正。受到这些条件的限制,那个唯快不破的铁律在Native App 上遭遇到了尴尬。每一个产品决策会变得异常谨慎,因为一个错误的决策要持续整个版本周期可能被修复。慢慢的我们就会发现,不出错会成为做出决策的重要因素,而有意义却退居二线。

所以具备快速验证及时修正这两个能力就显得非常重要,打造这样的能力需要一个完整的解决方案。我们认为,这个方案是一个以 A/B 测试为核心,结合周边多个系统能力,共同组成的一个试错平台。在这个平台上,我们的团队,不管是业务方还是工程师,都可以快速应变,不畏惧出错,变得灵动起来。

A/B 测试

说到 A/B 测试,这到底是个什么东西?我个人的理解是:狭隘的说,A/B 测试是以分桶为核心,以依据分桶结果执行不同逻辑为基本原理,以获取最优解为目的一种测试方案。

一般认为,A/B 测试的主要场景有两种:对比实验和灰度发布。

对比实验

所谓对比实验,就是同一时间执行两套甚至多套方案,通过对比反馈数据,对这些方案作出评价。

灰度发布

灰度发布则是,某个新功能或版本正式发布前,先圈一部分人作为小白鼠,试用这个功能或版本。我们从稳定性,业务效果等多方面观察这部分试用者的反应,对这个新功能或版本作出评价。

不管是对比实验还是灰度发布,最终目的都是期望只是发布带来的效果最大化。

体系

一个单一的 A/B 测试框架并不能帮助我们达成目的,还需要诸多周边能力辅助。要实现丰富的分桶条件,需要设备和用户的信息收集机制;要实现线上逻辑 实时调整,要 Native 逻辑动态化方案;要实现动态调整分桶逻辑,需要分桶条件下发系统;实现观察对比实验结果,需要数据收集和分析平台,等等。

在天猫,我们整合各方能力搭建了一个称为AirTrack的试错平台。在 AirTrack 平台上动态实验条件,实时运算 SDK 和数据收集和反馈平台三部分是重中之重。

动态实验条件

在传统的 Web A/B 测试中,实验条件的计算和分桶逻辑执行都在后端完成,具有非常好的动态性,可以随时发布随时生效。在 Mobile 场景下,很多时候我们惯性的延续这 种思路,把这些逻辑放在后端,通过 API 吐出不同的数据来控制 App 端的不同形态。这种方式固然有很好的动态性,但一个致命问题在于,这样的设计依赖数据 API,只能用于数据层面的实验。

我们认为数据 API 在 Mobile 场景中仅仅占一小部分,而我们要建设的是一个代码级别的 A/B 测试框架,必然不能依赖数据 API,而是要具备在端 上完成此前后端承担的全部工作。具体的说,就是我们需要在 App 端实时运算实验条件和执行分桶逻辑。所有的逻辑都在 App 端,那么动态化的问题怎么解决? 幸好我们具有成熟的基础设施建设,可以通过配置中心实现实验条件动态化。

我们把实验条件的数据结构设计为一棵树。根节点是运算起点,非叶子节点是一个逻辑表达式,叶子节点都是实验条件运算的结果。

通过一段 JSON 描述这棵实验条件树,再利用配置中心的动态能力把数据动态下发到端,从而实现了实验条件动态化。

复制代码
{
"name": "demo",
"expired": 1458403200,
"tree": {
"prop": "device.version",
"op": "eq",
"val": "9.0",
"son": [
{
"prop": "device.city",
"op": "in",
"val": " 杭州市, 北京市, 上海市 ",
"son": [
{
"per": [
0.33,
0.33
],
"son": [
{
"node": 1
},
{
"node": 2
},
{
"node": 3
}
]
}
]
}
]
}
}

App 端的业务代码调用 AirTrack SDK,初始化一个 AirTrack 实例,指定该实例需要进行的实验名称,把需要加入实验的若干逻辑注册到这个实例中。AirTrack 实例在执行阶段, 根据实验名称,通过配置中心获取实验条件,从条件树的根节点开始计算,最终找到一个叶子节点,通过叶子节点中携带的信息定位到需要执行的实验逻辑,并执行 该逻辑。从而完成整个实验过程。

在条件树的 Demo 中我们可以看到非叶子节点有两种类型

  • 带属性的运算
  • 哈希运算

带属性的运算,利用了天猫状态中心的数据能力,通过条件节点中指定的状态名称获取状态中心中的当前属性值,与给定值进行运算符指定的运算,当运算结果为真,则落入左子树,假,落入右子树。

哈希运算,则是使用设备 ID,条件名称和当前节点深度三个因素组合成一个因子,并对该因子进行 0-10,000 的哈希,通过哈希结果可知当前设备落入那一段区间内。根据给定的子节点和比例关系决定落入哪一棵子树。

数据收集和反馈平台

在天猫 App 中有一套成熟的数据采集 SDK,数据以界面为线索被收集并同步到后端。我们对这个收集 SDK 进行一些改造,在 AirTrack SDK 中自动调用数据采集接口,把执行结果的分桶信息写入埋点。

根据数据采集收集的日志,我们有一套完整的以页面为线索的数据分析平台。在这个平台上我们可以看到页面维度的全部信息,除了 PV,UV,点击率等常规数据,该页面的入口和出口流量,转化率等等。

而我们对 A/B 测试数据的要求也正是这些,所以我们对数据分析平台改造支持分桶统计,可以平行看到各个分桶的数据。

实践

配置灰度发布

之前我们说 A/B 测试的两个主要场景之一是灰度发布,配置中心是一个典型场景。修改一份配置后,需要对这次变更进行灰度发布,以求安全稳定。

我们预先定义若干灰度方案,每一个灰度方案就是一份 A/B 测试的实验条件。例如,我们有一份实验条件是:

  • 第一个 20 分钟生效 10%
  • 第二个 20 分钟生效 50%
  • 第三个 20 分钟生效 80%

通过 1 个小时的灰度逐步上线。在灰度过程中,我们可以在数据监控平台上实时发现问题,随时终止灰度进程。如果一切正常,那么这个变更就会自动全量发布。

首页模块对比测试

在天猫 App 的首页上有很多坑位,我们会在坑位变更中,使用了对比测试方案。

在某次变更中,首先切 20% 的流量作为样本,把样本五五开,10% 执行旧逻辑,10% 执行新逻辑,在线上试运行两天。根据反馈的数据显示,我们对比 两个坑位的转化率和展示效果,发现新坑位效果并没有达到预期。所以撤回新方案,并实施改造,再次上线对比实验,直至达到预期效果。

在整个决策过程中,花费了 1 周时间。然而这样的决策在没有试错平台的情况下,需要跨越一个甚至更多个版本。

个性化弹窗

在实施 A/B 测试的过程中,发现这个平台除了处理以上的两个场景,还可以有更多功能。甚至可以在常规业务中发挥效果。

大家经历过天猫 App 首页的红包雨,擦雾霾等功能。这是一个独立的弹窗系统支持的,然而这个系统并没有很好的解决在什么条件下出现弹窗这件事。最初的方案只是分时间段弹窗,也就是说,弹窗有一个生效队列,到了某个时间点某个界面一定会弹出某个框。

我们希望弹窗逻辑可以更加聪明,能根据设备和用户信息个性化的出现。这个需求刚好与 AirTrack 所提供的能力契合,A/B 测试并不一定要决定好 坏,做出决策,当然也可以支持个性逻辑区分。我们使用 AirTrack SDK 的配置,把不同的弹窗条件单做桶来看待。通过动态配置 AirTrack 的分桶逻辑,并指定弹窗桶号来实现了这个个性化弹窗的需求。

以上就是我们在天猫 App 上最主要的三个实践场景。天猫在 A/B 测试领域的探索刚刚开始,我们相信随着探索的深入,A/B 测试一定可以在 App 开发和维护中衍生出更加强大的能力,起到越来越重要的作用。

2016 年 3 月 20 日 20:2011523

评论

发布
暂无评论
发现更多内容

带着面试题学习红黑树操作原理,解析什么时候染色、怎么进行旋转、与2-3树有什么关联

小傅哥

Java 数据结构 小傅哥 红黑树 2-3树

ARTS打卡第一周(200511-200517)

老胡爱分享

ARTS 打卡计划 ARTS活动

LeetCode152-乘积最大子数组-medium

书旅

LeetCode 动态规划

疫情按下快进键,电商抢占市场红利需可靠的助力

华为云开发者社区

高并发 电商 华为云 流量 云服务器

MySQL下的DB Link

Simon

MySQL

高效程序员的45个习惯:敏捷开发修炼之道(4)

石云升

读书笔记 敏捷开发

力扣题 - 29 解析大佬题解

Geek_663541

Java算法

糖果不需要意义

zhoo299

随笔杂谈 电影

Docker入门与简单使用

Simon

Docker Linux

MySQL容器化详细教程

Simon

MySQL Docker 容器

LeetCode题解:11. 盛最多水的容器,while循环双指针,JavaScript,详细注释

Lee Chen

大前端 LeetCode

天地玄黄,宇宙洪荒

zhoo299

随笔杂谈

学习笔记2

Qx

学习

不完满的选择,要不要放弃

zhoo299

随笔杂谈

Docker 架构及工作原理

哈喽沃德先生

Docker 容器 微服务

GrowingIO 数据采集 iOS SDK 测试实践

GrowingIO技术专栏

ios 数据采集 sdk

常用SQL语句分享

Simon

MySQL sql

MySQL中几种常见的日志

Simon

MySQL 日志

CDN百科11 | 担心纸质病例被洪水淹没?ECS+CDN+OSS如何助力医疗上云

阿里云Edge Plus

CDN 存储 云服务器

互联网公司建网站时最应该注意什么?

姜奋斗

互联网 网络安全 网站 网站搭建 互联网公司

领导发表的报告,你真的读懂了吗?

罗小龙

工作经验

不说再见

太以

疫情 毕业季 遗憾 大学

云上攻击太多怎么办?不妨试试这些工具

华为云开发者社区

黑客 云服务 数据安全 华为云 企业上云

一个域名值百万, 现在不注册,未来价更高

华为云开发者社区

备案 商标 DNS 域名配置 SSL证书

MySQL常用函数介绍

Simon

MySQL mysql常用函数

安全系列之——RSA的公钥私钥有多少人能分的清楚?RSA的签名验签与加密解密如何使用公私钥?

诸葛小猿

加密解密 非对称加密 rsa 签名验签

学习源码的第八个月,我成了Spring的开源贡献者

程序员DMZ

spring 开源

Docker从入门到放弃---基础篇

书旅

Docker 容器

带你认识MySQL sys schema

Simon

MySQL

Flink任务执行-3

小知识点

大数据 flink

SecureBoost算法

soolaugust

学习 同态加密 secureboost

天猫App A/B测试实践-InfoQ