圓通處事,方能達到目的!開發中我們經常會遇到一些需要定時來解決的業務場景。比如,有這樣乙個需求:「如果連續30s沒有請求包(例如登入,訊息,keepalive包),服務端就要將這個使用者的狀態置為離線」。
將所有任務都新增到某集合中,定時輪詢掃瞄,如果達到條件則進行相關處理;
let map = new map();
function
doaction
(uid)
setinterval(function
()超過30s未做任何操作,設定為離線!`);}}
}, 10000);
方案的不足:每來乙個任務,啟動乙個定時器,達到定時器時間,執行相關處理;
function
doaction
(uid) 超過30s未做任何操作,設定為離線!`);
}, 30000);
}
方案的不足:資料結構:執行過程:
第一步:啟動乙個timer,每隔1s,在上述環形佇列中移動一格,0->1->2->3…->29->30->0…
有乙個currentslotindex指標來標識剛檢測過的slot ;
第二步:當有某使用者uid有請求包到達時,從map結構中,查詢出這個uid儲存在哪乙個slot裡;
第三步:如果存在,從這個slot的set結構中,刪除這個uid,否則跳過該步驟;
第四步:將uid重新加入到新的slot中(currentslotindex指標所指向的上乙個slot)因為這個slot,會被timer在30s之後掃瞄到
第五步:更新map,重新設定該uid對應slot的index值
// no,陣列中所有set集合為同乙個
let listloop = new
array(31),
map = new map(), // 記錄每個uid的slotindex
currentslotindex = 1; // 當前要檢測的slot
function
doaction
(uid)
// 每秒鐘移動乙個slot,這個slot對應的set集合中所有uid都為超時
// 如果所有slot對應的set集合都為空,則表示沒有uid超時
setinterval(function
() >超過30s未做任何操作,設定為離線!`);
}// 置空該集合
slotset.clear();
}// 指標繼續+1
currentslotindex = (++currentslotindex) % 31;
}, 1000);
// 思路、注意map集合的內心移除情況。
方案的優點:參照文章:10w定時任務,如何高效觸發超時、1分鐘實現「延遲訊息」功能
上述展示描述了一種業務場景,通過環形佇列的方式我們還可以處理很多類似場景。
定時任務沒觸發 10W定時任務,如何高效觸發超時
需求背景 1.延遲訊息功能。例如 滴滴打車訂單完成後,如果使用者一直不評價,48小時後會將自動評價為5星。2.無效連線斷開。在im系統中,客戶端會與服務端建立大量的長連線,當客戶端與服務端30s內沒有心跳的話,需要把這個連線斷開。一 最傳統的方案 建立一張延遲訊息表,滴滴訂單完成後插入一條延遲訊息,...
10w定時任務,如何高效觸發超時
很多時候,業務有定時任務或者定時超時的需求,當任務量很大時,可能需要維護大量的timer,或者進行低效的掃瞄。一般來說怎麼實現這類需求呢?方案一 只啟動乙個timer,但需要輪詢,效率較低 方案二 不需要輪詢,但每個請求包要啟動乙個timer,比較耗資源 廢話不多說,三個重要的資料結構 1 30s超...
10w定時任務,如何高效觸發超時
二 環形佇列法 廢話不多說,三個重要的資料結構 1 30s超時,就建立乙個index從0到30的環形佇列 本質是個陣列 2 環上每乙個slot是乙個set,任務集合 3 同時還有乙個map,記錄uid落在環上的哪個slot裡 同時 1 啟動乙個timer,每隔1s,在上述環形佇列中移動一格,0 1 ...