互联网流量下的分层实验平台是咋作的

前言

对于如今拥有大流量的互联网平台来讲,一个微小的页面改版或者是一个微小的后台内容推荐模型参数的修改都会产生很是大的影响,如何安全的在线上流量验证这些改进是否真有助于提升公司的收益或者是用户的体验呢?后端

A/B Test

很容易想到作A/B Test,咱们能够用一种方式把全网流量分红100份,取其中两份流量来进行实验:一份做为对照组,一份做为实验组。因为实验所占流量为全网的1%,故而影响范围小,即便出现了负收益也不影响大盘。安全

假设每次请求中都有req_id,咱们对req_id取模,而后根据余数来划分流量。在实际工程开发中,一般会对每一个实验产生一个惟一的sample_id做为试验标识,后端日志记录该sample_id的相关信息,统计组对离线日志进行统计,对一个实验下的两个sample_id(对照组sample_id,实验组sample_id)的各类统计指标进行对比,来确认试验效果。以下图所示:
cookie

有两个实验:实验1和实验n。 每一个实验又分为对照组(基线)和实验组,每组流量大小相等。 实验1对照组流量是req_id % 100 = 0,实验组是req_id % 100 = 1;实验n对照组流量是req_id % 100 = 98,实验组是req_id % 100 = 99。只要req_id最后两位分布够均匀,那么每份流量大小基本相同。app

实验分层

可是这么作有一个问题,就是最多容许同时进行50个实验(每一个实验占用两份流量)。在今天的互联网企业中,可能同时进行成千上万的功能开发,而每一个功能背后都须要进行实验,如何尽量同时知足这些需求呢?咱们对实验进行分层:即同一份流量可能同时命中两个或者多个实验,以下图所示,一份流量能够同时命中实验1和实验n:
字体

可是这么作须要有一个前提,就是两个层的实验不能互相冲突,每一个层只能修改本身的参数,即若是实验1和实验n同时修改参数A,则这两个实验必须在同一层,层与层之间的划分就看层间参数是否有交集。优化

最终咱们根据参数来划分层,有依赖关系的参数必须划分在同一层(例如页面背景颜色和字体颜色必须在同一层,若是页面背景颜色和字体颜色都被设置成蓝色,那么咱们就看不到页面上的字了),没有依赖关系的参数能够划分在不一样层,每一个参数只出如今一个层中,不会出如今多层中。ui

原来每层能作50个实验,如今把参数分了n层,每层均可以同时进行50个实验,那么如今可同时进行50 * n 个实验,n为实验层数。设计

流量正交

可是如今还有一个问题,如上图所示实验1和实验n用的是彻底相同的流量,这可能会有一些问题:咱们虽然确认实验1和实验n没有参数冲突,可是没法肯定实验1和实验n的实验效果是否互相影响。好比实验1进行页面改版使得页面更美观,实验n对后端推荐模型进行参数优化使得推荐内容更有趣,这两个实验不修改相同的参数因此能够分在不一样的层中,可是这两个实验都会影响用户页面停留时长和用户的点击率,若是流量彻底同样,咱们统计的结果究竟是实验1产生的影响仍是实验n产生的影响呢?咱们必须消除这个影响。3d

  • 流量正交:实验1的流量必须均匀分布在后一层中,这样才能保证明验1观察的效果主要是由页面改进带来的效果,一样实验n的流量也必须均匀分布在后一层而且均匀来自于前一层。咱们采用哈希值取模代替原始req_id取模,而且哈希时传入层ID,这样层与层之间的哈希值不一样,从而达到均匀分布。

以下图所示:
日志


实验1的流量均匀分布在下一层,实验n的流量来源均匀分布在前一层

流量划分

大多时候,咱们须要保持用户在产品使用上的体验一致性,例如:不能前一次看到页面字体颜色为蓝色,刷新一次页面字体变成绿色。这就提醒咱们在进行流量划分的时候,不是全部实验都可以用req_id的哈希值进行划分,咱们必须使用uid的哈希值进行划分,若是没有uid咱们可使用cookie的哈希值进行划分。因此,这里面有一个流量优先级划分顺序: uid > cookie > req_id。

实验转全

当咱们在小流量下验证了一种改进是有效的,那么如何把这个改进在全流量上生效呢?有如两种方法。

  • 直接修改代码,使其在全流量上生效。这种方式比较暴力,若是直接在全流量上修改代码使其生效,那么当遇到一些在大流量下才能发现的问题时,咱们不得不从新回滚代码。
  • 慢慢增大实验流量,最终使其在全流量上生效。这种方式比较稳妥,即便发生没有预料到的问题也能经过控制实验流量来止损,可是它会挤占同一层的其它实验流量,若是实验流量增大到100%,那么同一层其它实验就得不到流量。

咱们针对第二种方式对试验平台进行一个改进,对每个参数增长一个新的发射层(Launch Layer),以下图所示:

  • 每一个实验参数能够同时既在发射层,又在实验层。
  • 实验层能够覆盖发射层的参数值。
  • 每一个参数最多只能在一个发射层。

当小流量实验须要全量上线时,实验进行层间转移:把实验从实验层搬到发射层,经过调节发射层的实验组与对照组(通常是基线,即线上流量用的参数默认值)比例来使得改进最终用于全流量,这样既不影响原有的实验流量分配,又可以快速调节流量大小。在调节期间,若是发现问题,能够控制发射层实验组与对照组的流量比例来止损。当咱们的改进在发射层上全流量上线后,观察一段时间没有什么问题,就能够放心经过修改代码来把改进应用到线上全流量,而且撤掉发射层。

工程开发与实验评估

到此为止,咱们讨论了实验平台的设计的理论依据,接下来就是工程开发。实验平台应该在一次访问的入口处,根据本次请求的相关信息来决定命中哪一个实验并生成一个惟一的sample_id,以后把sample_id传递到下游服务;下游各个服务根据sample_id来人为修改代码,根据sample_id作不一样的动做,而且记录相关日志。

对于一个成熟的实验平台来讲,其应该具有以下几个功能:

  • 可以灵活配置试验流量并快速生效(一般使用配置下发)。
  • 可以检查实验配置合法性。
  • 有一套信服的评估标准体系(由专门的统计组人员进行专业评估)。

结语

以上就是一个实验平台建设时须要考虑的基本的原理性的东西,但愿能对小伙伴有帮助。因为水平有限,文中某些地方讲的不合理或者不对,但愿小伙伴留言指教。

参考文献

《Overlapping Expeeriment Infrastructure: More, Better, Faster Experimentation》, Diane Tang, Ashish Agarwal, Deirdre O'Brien, Mike Meyer, Google, Inc.

相关文章
相关标签/搜索