如何正確的評估redis過期時間

zhuguowei2發表於2016-05-05

業務

抽獎 獎品分紅包和實物 每個使用者只能中一個實物

初始程式碼是這樣

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

相關文章