如何正确的评估redis过期时间

业务

抽奖 奖品分红包和实物 每个用户只能中一个实物

初始代码是这样

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天?

    原文作者:zhuguowei2
    原文地址: https://segmentfault.com/a/1190000005068358
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞