什么是ABTest
产品的改变不是由我们随便「拍脑袋」得出,而是需要由实际的数据驱动,让用户的反馈来指导我们如何更好地改善服务,「有些东西是需要 Sense,但大部分东西是可以用 Science 来做判断的。」

简单来说,ABTest就是将用户分成不同的组,同时在线试验产品的不同版本,通过用户反馈的真实数据来找出采用哪一个版本方案更好的过程,很多时候,一个按钮、一张图片或者一句文案的调整,可能都会带来非常明显的增长。

我们将原始版本作为对照组,以每个版本进行尽量小的流量迭代作为原则去使用 ABTest。一旦指标分析完成,用户反馈数据表现最佳的版本再去全量上线。

2022-08-23T01:12:30.png

ABTest的特性
先验性:采用流量分割与小流量测试的方式,先让线上部分小流量用户使用,来验证我们的想法,再根据数据反馈来推广到全流量,减少产品损失。
并行性:支持更多的实验,多个实验可以并行扩展,同时又不影响每个实验的灵活性,减少实验周期与复杂度。
科学性:更好地保证实验的准确性和合理性,确保分析的实验结果基于合理的用户分流,依据统计指标来判断这个结果,避免依靠经验主义去做决策
为了让我们的验证结论更加准确、合理并且高效,基于Goolge论文:《Overlapping Experiment Infrastructure:More, Better, Faster Experimentation》制定了分层、分流规则

稳定的分流保障
分流算法我们采用的FNV哈希算法,参与算法的Hash因子有类型名,流量层id,设备id,用户id

1.能快速hash大量数据并保持较小的冲突率

2.高度分散特性使它适用于hash一些非常相近的字符串,比如设备号

分流模型:同层互斥,分层正交。
同层互斥:同一分层上的实验,用户只能参与其中一个。不能同时参与的实验要放在同一分层上,用户群会完全独立。
分层正交:每一个层的流量都会重新打散,用户进入不同层实验之间没有必然关系,相互不影响,从而同时进行很多实验。

2022-08-23T01:13:04.png

规则描述:

1)按分层1为100%流量,分层1的流量=隔离域1+域2

2)域1和域2拆分流量,此时域1和域2是互斥的。

3)流量流过域2中的分层2、分层3、分层4时,2,3,4层的流量都是与域2的流量相等。此时2、3、4层的流量是正交的。

4)正交:实验1和实验3在不同分层上,同时实验。参与实验1的对照组的人 进入实验3的对照组和实验组这两个组的人数是一样的,同理实验1的实验组进入实验3的两个组的人数也是一样的。

5)流量流过域2中的分层4时,又把分层2分为了实验6、实验7、实验8,此时实验6、7、8之间又是互斥的。

根据以上规则我们可以不断的在此模型中增加域、层,并且可以互相嵌套。这要与实际的业务相匹配,拆分过多的结构可能会把简单的业务复杂化,拆分过少的结构又可能不满足实际业务。
2022-08-23T01:13:25.png

流量层内实验分流
流量层内实验的 hash 因子有设备 id、流量层 id。当请求流经一个流量层时,只会命中层内一个实验,即同一个用户同一个请求每层最多只会命中一个实验。首先对 hash 因子进行 hash 操作,采用FNV哈希算法,可以保证 hash 因子微小变化但是结果的值变化激烈,然后对 100 求余之后+1,最终得到 1 到 100 之间的数值。
2022-08-23T01:13:45.png

实验内版本分流
实验的hash因子有设备id\用户id、流量层 id。采用相同的策略进行版本匹配。匹配规则如下:
2022-08-23T01:14:04.png
多级缓存策略
每一个请求来临之后,系统都会尝试去获取与之匹配的实验。实验是在从后台配置的,我们通过主动刷新的形式,将经过配置之后的策略,同步到我们的分流实验池当中。

最初的方案是每一个请求来临之后,都会从 Redis 当中去读取数据,这样的话对 Redis 的稳定性要求较高,大量的请求也会对 Redis 造成比较高的压力。因此,我们引入go-cache一种内存缓存机制

第一层 go-cache 是一个简单高效的缓存策略,类似于Memcached的key:value缓存,适用于单机应用程序,它的特点是伴随着go服务进程的生命周期存在,十分高效,不需要通过网络序列化或传输其内容。

可以在给定的持续时间内或永久存储任何对象,并且可以由多个goroutine安全使用缓存。

第二层 redis 一个高性能的key-value数据库,数据都是缓存在内存中的,高效使用,实现了master-slave(主从)同步,数据可以从主服务器向任意数量的从服务器上同步,对突发大流量场景有很好的水平扩展能力。

分流服务设计
计算出当前用户命中哪些实验的哪个分组,或命中哪个隔离域。

主要流程如下:

  1. 流量过滤即流量筛选
  2. 流量正交hash分桶:隔离域/分层 hash分桶
  3. 流量匹配:管理后台上设置好了分组/隔离域 的流量,已分配好了对应的桶号。分流hash得到桶号后与所占用桶号匹配,一致就算命中。

2022-08-23T01:14:48.png

逻辑优先级:分组白名单>隔离域白名单>隔离域黑名单>自然分桶流量命中