AB测试实战项目:从零搭建高可用分流系统
·
在互联网产品的快速迭代中,AB测试(A/B Testing)是验证新功能效果的金标准。但新手搭建分流系统时,常会遇到三个致命问题:
- 分流不均:手动写if-else导致实验组/对照组流量比例失控
- 数据污染:用户多次命中不同分组造成行为数据无法归因
- 统计失真:忽略样本量估算导致误判实验结果

技术选型:Cookie还是用户ID?
两种主流分流方案对比:
- Cookie分流:
- 优点:无需登录即可追踪用户
-
缺点:用户清除Cookie会导致分组变化
-
用户ID分流:
- 优点:长期稳定的用户标识
- 缺点:依赖登录系统
推荐方案:对未登录用户使用Cookie,已登录用户自动切换至UserID。采用哈希取模算法(Hash Modulo)确保相同ID始终落入同一分组。
核心代码实现(Go语言)
定义分流策略接口:
// 分流策略接口
type Splitter interface {
GetBucket(identifier string, trafficRange []float32) int
}
// 哈希取模实现
type HashModSplitter struct{}
func (s *HashModSplitter) GetBucket(identifier string, trafficRange []float32) int {
h := fnv.New32a()
h.Write([]byte(identifier))
hash := h.Sum32() % 100 // 取模范围0-99
var sum float32
for i, ratio := range trafficRange {
sum += ratio
if float32(hash) < sum*100 {
return i
}
}
return len(trafficRange) - 1
}
单元测试验证分流均匀性:
func TestHashModSplitter(t *testing.T) {
splitter := &HashModSplitter{}
count := [3]int{}
trafficRange := []float32{0.5, 0.3, 0.2} // 50%/30%/20%
// 模拟1万个用户请求
for i := 0; i < 10000; i++ {
id := fmt.Sprintf("user%d", i)
bucket := splitter.GetBucket(id, trafficRange)
count[bucket]++
}
// 验证误差在±2%内
assert.InDelta(t, 5000, count[0], 200)
assert.InDelta(t, 3000, count[1], 120)
assert.InDelta(t, 2000, count[2], 80)
}
数据验证(Python版)
检查分流是否均匀:
from scipy.stats import chisquare
# 模拟分组数据(实际应从数据库查询)
observed = [5032, 2985, 1983] # 实际观测值
expected = [5000, 3000, 2000] # 理论期望值
# 卡方检验(Chi-Square Test)
chi2, p = chisquare(observed, f_exp=expected)
print(f"P值={p:.3f}") # P值>0.05说明无显著差异
样本量估算公式(以转化率为例):
所需样本量 = 16 * 基线转化率 * (1-基线转化率) / (最小检测提升)^2
生产环境避坑指南
- Cookie禁用处理:
- 一级降级:使用localStorage
-
二级降级:随机分配+会话级缓存
-
多实验正交:
// 对不同的实验使用不同的hash种子 func getExperimentSeed(expName string) uint32 { return crc32.ChecksumIEEE([]byte(expName)) } -
新用户预热:
- 前5%流量只分配老用户
- 逐步放开新用户比例

延伸思考:灰度发布系统
在AB测试系统基础上扩展:
- 流量标签路由:
- 用户标签(VIP/地区/设备)
-
环境标签(客户端版本/渠道)
-
分级下发规则:
graph TD A[全局流量] --> B{是否在白名单?} B -->|是| C[全量新功能] B -->|否| D{是否命中5%灰度?} D -->|是| E[新功能] D -->|否| F[旧功能]
这套系统我们已经稳定运行2年,单机QPS可达1.2万。关键点在于:分流均匀是基础,数据校验是保障,正交设计是进阶。建议先用小流量验证核心链路,再逐步叠加复杂规则。
更多推荐

所有评论(0)