public class Test {
@Data
private static class ABTestEntity {
private long id;
private int percent;
public ABTestEntity(long id, int percent) {
this.id = id;
this.percent = percent;
}
}
public static void main(String[] args) throws Exception {
long uid = 4L;
long strategyId = 123456L;
List<ABTestEntity> configs = new ArrayList<>();
configs.add(new ABTestEntity(1, 10));
configs.add(new ABTestEntity(2, 20));
configs.add(new ABTestEntity(3, 30));
configs.add(new ABTestEntity(4, 40));
System.out.println(executeDiversion(uid, configs, strategyId));
}
/**
* 执行分流请求
*
* @param strategyId 策略ID,由于用户分组结果对于某个策略是一定的,所以我们的业务上使用策略ID作为离散因子
*/
private static Long executeDiversion(long uid, List<ABTestEntity> abTestEntityList, Long strategyId) throws Exception {
if (abTestEntityList != null) {
ArrayList<Long> abTestIdArr = new ArrayList<Long>();
ArrayList<Integer> percentArr = new ArrayList<Integer>();
int value = 0;
for (ABTestEntity abTestEntity : abTestEntityList) {
long abtestId = abTestEntity.getId();
value += abTestEntity.getPercent();
abTestIdArr.add(abtestId);
percentArr.add(value);
}
return getDivResultMap(Long.toString(uid), Long.toString(strategyId), abTestIdArr, percentArr, value);
}
return -1L;
}
/**
* 返回层分流结果
*
* @param uid eg:4
* @param shuffle eg:123456 离散因子
* @param bucketIdArr eg:[1,2,3,4] 四个分组
* @param percentArr eg:[10,30,60,100] 当前分组和前几个分组累加的比例
* @param value eg: 100 所有分组共占得比例
* @return
*/
private static Long getDivResultMap(String uid, String shuffle, ArrayList<Long> bucketIdArr, ArrayList<Integer> percentArr, int value) throws Exception {
MessageDigest md5 = MessageDigest.getInstance("MD5");/* 用来生成MD5值 */
long hashValue = splitBucket(md5, uid, shuffle);
if (value > 0) {
int bucket = (int) (hashValue % value) + 1;// 将比例分成value份,看每次请求落在某份上
// eg: bucket = 83
for (int i = 0; i < percentArr.size(); i++) {
if (bucket <= percentArr.get(i)) {
return bucketIdArr.get(i);
}
}
}
return -1L;
}
/**
* 对用户标识进行hash
*
* @param md5 加密算法
* @param val 用户请求标识(uv:uid pv:uid+timestamp)
* @param shuffle :离散因子
* @return
*/
public static long splitBucket(MessageDigest md5, String val, String shuffle) {
String key = val + ((shuffle == null) ? "" : shuffle);
byte[] ret = md5.digest(key.getBytes());
String s = byteArrayToHex(ret);
long hash = Long.parseLong(s.substring(s.length() - 16, s.length() - 1), 16);
if (hash < 0) {
hash = hash * (-1);
}
return hash;
}
public static String byteArrayToHex(byte[] byteArray) {
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char[] resultCharArray = new char[byteArray.length * 2];
int index = 0;
for (byte b : byteArray) {
resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
return new String(resultCharArray);
}
}
Java-ABTest对用户按策略分组
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- !DOCTYPE html>Bizpower商城系统演示站 - Powered by Bizpowerhttp:/...
- 今天是钉钉应用云开发实战营的第3课,听课的时候,感觉老师讲得内容挺好,只是知识点有点散,一度担心,像我这样的小白能...
- [https://github.com/GourdErwa/review-notes/blob/master/la...
- 1. jps : 虚拟机进程状况工具[#1-jps-%E8%99%9A%E6%8B%9F%E6%9C%BA%E8%...