随着年龄的增加,能够留给自己的时间越来越少。大部分时间都贡献给了工作、家庭和其他各种各样的事务。能够静下心来阅读论文、书籍的机会变得越来越宝贵。这一系列希望能够介绍个人在阅读论文的过程中比较令我印象深刻的论文。不知道能够坚持多久,

今天的主角是 Google 在 2010 年发表在 KDD’10 上的,关于 A/B 测试的论文 Overlapping Experiment Infrastructure: More, Better, Faster Experimentation。论文的一作是 Diane Tang,Google Fellow。她在 Udacity 上有一门关于 AB 测试的课程,如果有兴趣可以额外关注一下。

这篇文章可以视作是互联网大规模 A/B 测试(之前的工作主要关注在 web-based experiment 和小规模)系统领域的开山之作。工业界无论是 ToB 的 A/B 测试产品,还是内部的 A/B 测试工具,都或多或少借鉴了这篇论文的思想:

  • https://firebase.google.com/docs/ab-testing/abtest-config 谷歌 Firebase AB 测试
  • http://ab.testin.cn/docs/ Testin 云测 AB 测试产品
  • https://www.optimizely.com/ Optimizely AB 测试产品
  • https://www.volcengine.cn/product/datatester 字节跳动火山引擎 AB 测试产品

谷歌在一些算法的改动,和 UI 的改动等方面,都在上线前进行 A/B 测试。比如一个按钮的样式是 A 好还是 B 好,一个算法的改动对 CTR 是否真的有帮助,都是需要通过线上的 A/B 实验来验证的。谷歌的这篇文章所描述的系统的目标是:

  • 高并行:支持更多的并行实验和更灵活的实验配置。谷歌作为世界上最成功的互联网公司之一,对 A/B 测试的需求是非常旺盛的,因此需要在线上支持同时运行不同的 A/B 测试实验,同时也需要支持对流量进行更多灵活配置。比如某些实验只想在日本地区的流量中进行等
  • 易用性:不合法的实验和质量较低的实验应该在运行前就被识别出来,同时一些标准的指标,如点击率等,应该被通用化,可以被任何实验使用而不需要做过多的采集工作
  • 通用性:系统的受众不只是软件工程师,应该可以让业务 BP 也能够简单快捷地建立实验。同时也应该支持流量灰度上线的功能,支持将效果好的实验组快速灰度发布到线上
  • 一个最简单的实现:实现一个系统,能够对流量根据实验中实验组的数量进行分流。这样流量很容易就不够用了,因为每一个实验都需要占用一部分流量,如果流量不够多,就不够得到统计学意义上有价值的结果。谷歌对这个问题的方案是分层实验的设计。

在谷歌内部的 web search 架构中,所有的功能可以理解是微服务(文章里把它称作 binary)的,一个微服务有 binary 和 data 两部分,对应现在的微服务概念就是镜像和配置两部分。其中镜像的更新频率大约在周级别,而配置的更新会更加频繁,比如几个小时。一个微服务可能有几百个配置,一个新的 feature 通常也会有一到几个配置控制。

因此一个典型的最简单的 A/B 测试,会将一个微服务的一个参数选不同的取值,比如 A 和 B,建立对比实验。参数会更新到不同的微服务实例中,流量导到不同取值的对照组上,观察它们的指标差异,得出统计学的观察,取值对指标是否有显著影响,什么取值更合适等。

这里会涉及到分流算法的问题,怎么把用户到这一实验的流量划分到不同的对照组中。一个最简单的算法是随机分配,但是这样存在一个很大的问题,那就是一个用户的多个请求可能会被路由到不同的对照组中,这会对它的用户体验造成很大困扰。因此我们可以根据 user_id 分桶。比如将 user_id 哈希到不同的桶中,不同的桶分配给不同的对照组,这样可以保证不同的对照组有相同的流量,同时同一个用户的请求会路由到同一个对照组中。

但是,这样还存在其他的问题:为每一个实验都需要占用一部分流量,如果流量不够多,就不够得到统计学意义上有价值的结果。谷歌对这个问题的方案是分层实验的设计。

为了解决这个问题,谷歌扩展了之前的单层分流的方式,设计了多层的方案,并且引入了三个抽象:

  • A domain is a segmentation of traffic.
  • A layer corresponds to a subset of the system parameters.
  • An experiment is a segmentation of traffic where zero or more system parameters can be given alternate values that change how the incoming request is processed.

在引入多层的概念后,不同的实验可以放置在不同层中。有些实验的取值是互斥的,比如蓝色背景对照组和蓝色字体对照组,是不应该同时对一个用户开启的。所以这样的实验可以放在同一层中。同一层的流量会保证一个请求只会经过一个实验。而独立的实验,则可以放在不同层中。

在分流时,流量不再按照 hash(user_id) % 桶数量去划分,而是会根据 hash(user_id, layer_id) % 桶数量去划分。带上 layer_id 的目的是为了在层与层之间把流量打散。

目前有公开资料的 AB 测试系统基本都是多层的设计,这样可以尽最大的可能复用流量,在流量有限的情况下进行更多的实验。作为 AB 测试系统的鼻祖,这篇论文无论从 writing 还是内容都非常扎实,推荐一读。

PS:目前我也在基于这篇论文造一个轮子:github.com/dyweb/cloudab,求关注(不知道啥时候能发布第一个版本

License

  • This article is licensed under CC BY-NC-SA 3.0.
  • Please contact me for commercial use.

评论