文章目录
AB ? Angelababy ? 噢不,拒绝老板拍板决策的神器 !用数据说话的决策实验平台 —— AbTest !
在工作中,你们部门的决策权是否被老板紧紧掌控?而决策背后的实际责任却被部门所有人承担?
拒绝老板拍板决策!用 AbTest 数据说话 !
运营方式由增长转型至精细化
随着互联网下半场的到来「注,互联网何为下半场 - 见 -为何使用云原生应用架构 四 :独霸天下之四大绝技 — 终端多样性 篇」,互联网用户趋近饱和。
各大公司的运营方向逐步由以增长为主转型为精细化运营,提供精准、定制化、高质量的用户服务。
数据驱动运营决策更科学、准确
以往的各种运营需求,大都是 PM or 运营 进行活动策划及方案的最终选型,通过 RD 人员实现上线,最终评估收益。
这样的方式往往存在两个问题:
- 1、活动策划及方案最终选型是通过人工经验计算其收益最高的形式确定。
人工经验是非绝对正确的,它是一种主观决策,不代表最优收益!而且实际价值和预估可能存在较大差异! - 2、实际效果数据只有在活动结束,尘埃落定的数据盘点才可得出。
发现策划及方案的真实效益数据,和人工经验预估结果,存在过大的偏差时,已无补救机会!
我们在进行产品一些新的特性和挖掘一些已有特性的提升空间的方案设计选型时,如果以实际生产数据替换人工经验去决策选型,就可以解决上述问题,使每次对产品的改动效益最大化!
为了解决这样的问题,“ 数据驱动 ” 顺应而生!让数据作为决策唯一标准。
「注:Google 数据驱动型公司,数据驱动实验平台 - Overlapping Experiment Infrastructure: More, Better, Faster Experimentation 」
那么如何在获取各种方案的实际生产数据呢? —— 实验
AbTest – 实验获取数据的最佳手段
” 实践是检验真理的唯一标准 “
这句话用在精细化运营上同样适用,它给了我们一种获取实际生产数据的思路 —— 实践。
我们需要通过做实验的途径去进行各方案的验证,最终依据实验产生的数据进行终极决策。工科的同学可能接触的比较多,做实验往往有 实验对象、实验名称、实验组、对照组、数据分析…等等环节。
那么针对互联网产品,我们需要如何进行实验呢?—— AbTest
AbTest 入门名词诠释
AbTest 实验 是将预选方案分为 A、B、C…多组,通过纵向、横向类型进行流量拆分,使流量完全以实验组、对照组的实验走向分布,最终统计分析各组流量生产的链路日志,通过对比目标指标数据,最终选择最佳实验方案。
下面简单介绍下 AbTest 实验的专业术语:
-
Layer 层,流量分层统称。产品主体根据实验规模进行流量层划分,每一层实验组流量分布完全互斥且随机,每层之间流量分布完全正交。
-
Experiment 实验,实验的主体。针对目的数据指标构建实验,比如 “ 提升 app 某块功能性图标的点击率 ” 、”优化广告算法模型,提高广告转化率 “,可以构建 experiment 为 ” icon “、“ trans ad “ 两个实验。
-
Target 实验分流因子,实验主体属性。主体将依据此进行流量拆分,一般可为,userId、requestId、deviceId 等,是目的指标的最小数据分析单元
-
Partitions 实验分桶,实验主体属性。实验将会对目标流量进行拆分,全部流量规模会以分桶的数量进行表示,比如,icon 实验,有三组,分别给实验组A、B、C分配 30%的流量,剩余10%为自然流量。「A、B 分组 icon 为不同设计,C 分组 icon 为原样式」
-
Group 实验分组,实验主体的实验组。实验将会以实验组的实验模式进行,一般包含实验组,对照组…用于最终数据对比分析。
-
WhiteList 实验分组白名单,实验分组的属性。每个实验组中都将配备黑白名单,方便测试等特殊流量的实验命中。
-
BlackList 实验分组白名单,实验分组的属性。每个实验组中都将配备黑白名单,方便测试等特殊流量的实验命中。
-
BucketBit 实验分组 bit 位图,实验分组的属性。每个实验组分配的流量比通过位图的形式进行表述,方便流量的命中判断及确保大规模下的资源占用率
-
Hash 实验分组 Hash 算法,实验分组的属性。指出当前实验支持的流量命中 hash 策略。
上面是一些入门名词的解释,是不是感觉入门就很晕,完全不知道都是干什么的?没事,往下读,你需要构建一个完整的实验背景及链路,甚至是实验目的,驱动决策的真正诉求!
AbTest 实验类型
生物学中,研究小白鼠对甜、酸、辣等食物的喜爱度,一种简单的 Case 是直接水平分四组实验,三组实验,一组对照,且每组小白鼠都是随机挑选,每个实验互不影响。
AbTest 同科学中的实验一样,包含了水平维度,还有纵向维度,下面表述下各自的类型区别。
- 横向,也叫水平,即实验独占一个 Layer ,每个实验覆盖若干个桶,水平维度配置,互斥且同层。
上图中,共有三层,分别为 Lay1 、Lay2、Lay3 ,每层有一个水平实验,分别分为三组实验。
- 纵向、也叫垂直,即每个实验跨越不同的层区。
上图中,共有一层,为 Lay4,每层有三个垂直实验。
造成不同实验的类型的原因,是各个实验的配置项隐含关联关系决定的。
比如,
- icon 的实验是 icon 样式,相同位置的 icon 无法展示 不同实验中的多个样式;
- 不能与相同背景的实验同时命中,如果命中,那么这个 icon 将和背景融为一体…
AbTest 实验流量 正交性 & 随机性 保证
每个实验之间的配置存在隐含的关联关系,这导致实验的不同类型,那么我们该如何保障这些实验类型的正确性,即确保实验之间关联关系呢?
我们类比科学中的实验,隐含的关联关系 抽象为 同层实验的互斥、及流量拆分的随机 —— 正交性 & 随机性。
正交性
正交性的含义是指同层实验之间互不影响,那么我们如何确保同一个流量在每层都是随机分布的呢?
我们在进行流量拆分时,使用 Hash 算法完成分桶的随机映射,将分层 ID 作为 Hash 参数之一,与分层确定唯一关系,这样可实现分层流量的正交。
随机性
随机性的含义是指流量在每个实验分桶配比及实验命中是完全随机的,那么我们该如何实现呢?
使用随机散列算法,从数据概率学角度解决这一问题,选用冲突率极低的 hash 算法。
AbTest 实验平台架构概要设计
上面大家了解了 AbTest 实验的目的、实验的基本元素、实验的类型、实验关键的特性保证,那么下面来介绍流量的分流,也是 AbTest 的核心部分,流量做实验的过程实现。
一个企业级的 AbTest 平台,遵守 更多、更快、更好 的原则,下面将介绍业界通用型平台架构概要设计。
在企业中,AbTest 平台往往作为一个中台模块为各场景产品线提供实验服务。它提供两种接入方式 SDK 、RPC ,三种分流链路 本地、服务端、本地 & 服务端。
SDK 接入方式是跨语言的集成途径;RPC 接入方式是同语言的远程调用;
本地分流
本地分流是将 AbTest 作为服务同机与产品线服务部署,在本地进行流量实验。
AbTest 本地分流详细设计
产品线服务将流量放至本地服务,本地分流服务将以 API 的方式拉取 AbTest 实验信息作为分流物料缓存至内存 or Redis …,通过 Hash 算法进行实验命中策略,完成流量的分流,同时将命中的实验配置反馈至产品线服务,进行实验配置的渲染或其他执行逻辑。
下面是完整 一 本地分流详细设计图
在左侧是物料更新部分,保证物料的实效性。
右侧是本地分流的主链路,可以看到首先是黑白名单的判断,黑名单跳过,白名单进行实验配置信息的记录;未命中黑白名单策略时,将进行 Hash 分流算法,算法命中后记录实验配置信息;
「注意:命中配置信息需含优先级,即同一配置只能命中一实验,产品同一参数同一时间只能进行一个实验」
Hash 命中策略
BucketBit 中包含了实验流量配置比例的位图信息,我们需要将 base64 之后的 String 转为 []byte,假设当前是 1000 的 partitions 分桶,那么 String 将转化成长度为 125 的 []byte,继续转为长度为 1000 的 []int .
「注意:也可以直接 import 位图包进行实现」
有了 bit 数据,还缺少 index . 我们采用效率极高,冲突来极低的 xxhash 算法进行处理。
首先与层级进行耦合,target */+ layerId,作为 xxhash 的参数进行散列,之后对 partition 进行取模操作,即得到 index 。
有了 index + bit 位图,Hash 命中策略就已经完成了。
实验命中过程 Case
buckets「实验流量规则 —— base64 编码 String 串」:
hcWPNteoY2minPeI/6X4ylo5CnP2xUjcJuqfhJCSBiu9F5a0aL8ZqtL5ia3GtsfFsqIny4JuKTjvGJP+nb1VmFAkNAHMJb3GnXNrmP8tRJNNZlVA9KnkvndJ1TTSTbOJqDPUlM6YrTZ0Q4GvGJkaAnILrrmxkJp5mx8oHMU=
对 buckets 进行解码后为 125 长度的 []byte :
[133 197 143 54 215 168 99 105 162 156 247 136 255 165 248 202 90 57 10 115 246 197 72 220 38 234 159 132 144 146 6 43 189 23 150 180 104 191 25 170 210 249 137 173 198 182 199 197 178 162 39 203 130 110 41 56 239 24 147 254 157 189 85 152 80 36 52 1 204 37 189 198 157 115 107 152 255 45 68 147 77 102 85 64 244 169 228 190 119 73 213 52 210 77 179 137 168 51 212 148 206 152 173 54 116 67 129 175 24 153 26 2 114 11 174 185 177 144 154 121 155 31 40 28 197]
byte数组转换为长度为 1000「默认分桶数」 的 bit 分桶位图 :
[1 0 0 0 0 1 0 1 1 1 0 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 1 0 1 1 0 1 0 1 1 1 1 0 1 0 1 0 0 0 0 1 1 0 0 0 1 1 0 1 1 0 1 0 0 1 1 0 1 0 0 0 1 0 1 0 0 1 1 1 0 0 1 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 0 1 1 1 1 1 1 0 0 0 1 1 0 0 1 0 1 0 0 1 0 1 1 0 1 0 0 0 1 1 1 0 0 1 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 1 1 1 1 1 0 1 1 0 1 1 0 0 0 1 0 1 0 1 0 0 1 0 0 0 1 1 0 1 1 1 0 0 0 0 1 0 0 1 1 0 1 1 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 1 0 1 1 1 1 0 1 0 0 0 1 0 1 1 1 1 0 0 1 0 1 1 0 1 0 1 1 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 1 0 1 0 0 1 0 1 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 0 1 1 0 1 1 1 0 0 0 1 1 0 1 0 1 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 0 1 1 0 1 1 0 0 1 0 1 0 1 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 0 0 1 0 1 1 1 0 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0 0 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 1 1 0 1 1 1 1 0 0 0 1 1 0 0 0 1 0 0 1 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 1 1 0 1 1 0 1 1 1 1 0 1 0 1 0 1 0 1 0 1 1 0 0 1 1 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 1 0 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 0 0 1 1 0 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 1 0 1 1 0 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 1 0 1 0 0 1 1 0 1 0 1 1 0 0 1 1 0 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 1 1 0 1 0 0 1 0 1 0 1 0 0 1 1 1 1 0 0 1 0 0 1 0 1 1 1 1 1 0 0 1 1 1 0 1 1 1 0 1 0 0 1 0 0 1 1 1 0 1 0 1 0 1 0 0 1 1 0 1 0 0 1 1 0 1 0 0 1 0 0 1 0 0 1 1 0 1 1 0 1 1 0 0 1 1 1 0 0 0 1 0 0 1 1 0 1 0 1 0 0 0 0 0 1 1 0 0 1 1 1 1 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 1 0 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 0 1 1 0 1 0 0 1 1 0 1 1 0 0 1 1 1 0 1 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 1 1 0 0 1 1 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 1 1 0 1 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 1 0 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 1 0 1]
对 useID 做 xxhash % partitions 取得 分桶 index ;
按照 index 取 value , 分桶命中策略完成。
服务端分流
服务端分流是指各产品线实验包含特殊字段的设计,比如,用户年龄、用户所在地,这类字段信息数据规模比较庞大,且过滤策略相对复杂,依赖额外数据众多,无法通过 API 形式至本地,故需要服务端分流。
AbTest 服务端分流详细设计
服务端的实验分流策略几乎与本地分流机制一致,只不过是在最后的实验配置命中配置项结果集上,做了特殊字段的过滤逻辑。由于文章篇幅有限,过滤逻辑暂不做介绍,可私信博主详聊。
服务端 & 本地分流
服务端 & 本地分流 是为联合实验场景而设计的,当产品线 A 与 B 进行实验的联动,但 A 进行的是本地分流、B 进行的是服务端分流,那么这时就需要 服务端 & 本地分流进行处理。
AbTest 本地 & 服务端分流详细设计
服务端 & 本地分流是将本地分流链路与服务端分流链路进行了部分耦合,整体对外提供服务,这部分相对复杂,后续单独文章介绍。
AbTest 制造效应数据驱动科学决策
AbTest 可以保证流量实验,更多、更好、更快的有序进行,各组实验产生的结果数据通过反复对比,可以爽快的选择最优的方案进行全量发布。
这种运作模式就是数据驱动运营决策,用科学严谨的实验数据有效的评估各方案的实际生产效果。随着工具和专业知识在实验领域的发展,AB实验已成为越来越普遍的一种做法。
Q&A
1、垂直和水平实验类型的分流逻辑一致吗?
垂直和水平是从实验特性类别上进行的区分。
在实现角度上逻辑一致,垂直类型在一定程度上可视为水平类型的特例,有点像除以一个数就是乘以它的倒数一样的关系。
2、服务端 & 本地 分流是如何解决 实验特性配置的规模等问题的呢?
整体来讲,是进行两者的部分链路耦合,封装对外提供服务,详细的请见后续文章。
3、AbTest 既然往往作为一个中台对外提供服务,为什么还需要提供不同类型的分流服务呢?
对,作为中台,在某种角度上来讲是对资源的复用,对外的整体性是有相关规范;
但针对不同场景提供更合适的解决方案才是最佳的抉择!
这里补充下各自类型服务的优势:
本地分流的优势是,
1、解决了跨语言的问题
2、极大的简化链路,降低各链路接口的平响
3、…
服务端的优势是,
1、支持功能更加丰富,人群属性、地域规模,服务端的存储及算力等能力充分发挥
2、…
4、你的这个整体感觉缺少一个配置平台?
对,完整的 AbTest 需要一个平台提供 PM / 运营 …配置实验使用,这里篇幅有限,主要介绍分流主链路,额外信息可以关注后续文章,或私信博主细聊。
5、有些公司进行 AbTest 实验就没那么多分流策略,全都走一个配置平台,你这咋那么多呢?
对,有些公司,像 美团、滴滴等,技术栈一致,AbTest 平台就单纯一个通用功能,没有什么服务端/本地链路。
这个和公司调性、服务部署方式、技术团队的侧重,等多种因素有关。
举个例子,
团队 A - 使用共同的配置平台,整体链路平响 200ms ,对用户来讲,无明显感知,就把精力放在了其他的业务中;
团队 B - 改用平台的本地分流,整体链路平响由 200ms 降至 150ms ,对用户来讲,感知到更顺滑了,但貌似没有比把精力花在其他商业业务中收益多。
你品,细品!
附录
互联网公司的实质就是对数据的处理加工!
欢迎加入Q群聊【编程技术交流分享群717647116】,微信群请私信博主添加