业务
抽奖 奖品分红包和实物 每个用户只能中一个实物
初始代码是这样
AwardPool getAwardPool(){ //选择奖品池
hasWinRealObject = getUserAwardFromDb(user); //查询数据库判断用户是否中了实物
for(Award a : awardList){
if(hasWinRealObject && a.getType()==实物){ //若中了实物 排除实物奖品
continue;
}
//...
}
}
award = chooseAwardFromPool(pool); //从奖池里根据算法随机选择一个奖品
//抽奖后处理 添加用户中奖记录 更新奖品中奖数 等等
现想使用redis
来防同一用户并发抽奖时 存在中多个实物的可能
加上如下的代码
//...
award = chooseAwardFromPool(); //从奖池里选择一个奖品
if(award.getType() == 实物){ //防超中实物
count = redisService.incr(key);
if(count == 1){
redisService.expire(key, 10*60); //设置过期时间10分钟
}
if(count > 1){ //若中了多个实物 奖品默认为未中奖
award = 未中奖;
}
}
//抽奖后处理 添加用户中奖记录 更新奖品中奖数 等等
设置过期10分钟原因
假如并发来了100个请求 有两个请求均中了实物 两个请求的处理时间应该不会超过10分钟吧 即请求1处理完了 等10分钟后 才处理请求2 此时redis已经过期了 于是同一用户中了2个实物
但为什么总觉的10分钟还是不保险呢, 假如是下面这样呢? 10万
个请求数呢?
ab -n 100000 -c 100 -T "application/x-www-form-urlencoded" -p post_draw http://localhost:8080/zmw/warmup/draw
会不会有两个请求均中了实物,
即但执行后面的incr
的时候相隔超过10分钟呢?
#请求1 此时数据库中尚无实物奖品记录 得到实物奖品
award = chooseAwardFromPool(pool); //从奖池里选择一个奖品
#请求n 此时数据库中尚无实物奖品记录 得到实物奖品
award = chooseAwardFromPool(pool); //从奖池里选择一个奖品
#请求1
if(award.getType() == 实物){ //防超中实物
count = redisService.incr(key);
//...
}
#请求n 与请求1相隔超过了10分钟 此时仍能成功抽中实物
if(award.getType() == 实物){ //防超中实物
count = redisService.incr(key);
//...
}
在这里我陷入了一个盲区 始终想不清楚, 实际存不存在两个请求相隔10分钟的情况? 如何正确的评估过期时间应该为多少合适? 1小时? 1天?