業務
抽獎 獎品分紅包和實物 每個使用者只能中一個實物
初始程式碼是這樣
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天?