使用Redis實現隨機時間任務排程
阿新 • • 發佈:2018-12-20
隨機時間任務排程,是指在某個隨機時間之後,觸發相應的任務。
比如某拼團電商場景中,使用者發起拼團後,如果超過一小時沒有人加入,會由系統強制新增虛擬使用者,強制拼團成功。這個排程時間不能是固定的,而是隨機雜湊分佈的,否則會產生虛假感。
以下是用Redis實現的,利用的是redis中zset的排序功能。
首先,需要生成隨機時間。在Java中可以用簡單的隨機演算法,
public Long forceGroupTimeout(OrderGroup group){ Map<String,Integer> probability=orderGroupConfig.getForceGroupProbability(); int rd = random.nextInt(100); int delay; //結果數字 if(rd < probability.get("10-30")){ //10-30分鐘執行機率 delay = 10+random.nextInt(20); }else if(rd < probability.get("30-60")){//30-60分鐘執行機率 delay = 30+random.nextInt(30); }else if(rd < probability.get("60-90")){//60-90分鐘執行機率 delay = 60+random.nextInt(30); }else{ delay = 90+random.nextInt(30);//90-120分鐘內強制執行 } Long forceTime = System.currentTimeMillis()+(delay*60*1000)+60*60*1000;//此處新增一小時 return forceTime ; }
其中,probability是一個隨機機率的Map,在配置檔案裡配置如下
forceGroupProbability.10-30: 10
forceGroupProbability.30-60: 20
forceGroupProbability.60-90: 30
forceGroupProbability.90-120: 100
表示10-30分鐘執行的機率是10%,30-60分鐘執行的機率是20%,最後一個數可以不用填。
生成的這個時間戳就是我們假定一定時間後將要執行任務的時間,將任務id作為key,時間戳作為value儲存到redis的zset中。
之後,建立每分鐘執行的定時任務,使用zset範圍取值方法取比當前時間戳小的任務id:
Set<String> result=zsetOperations.rangeByScore(getRedisKey(),0,currentTimestamp);
取出後根據任務id執行相應的任務,執行完後將對應的key移除即可。
zsetOperations.removeRangeByScore(getRedisKey(),0,currentTimestamp);