很多時候,業務有定時任務或者定時超時的需求,當任務量很大時,可能需要維護大量的timer,或者進行低效的掃瞄。
一般來說怎麼實現這類需求呢?
方案一:只啟動乙個timer,但需要輪詢,效率較低
方案二:不需要輪詢,但每個請求包要啟動乙個timer,比較耗資源
廢話不多說,三個重要的資料結構:
1)30s超時,就建立乙個index從0到30的環形佇列(本質是個陣列)
2)環上每乙個slot是乙個set,任務集合
3)同時還有乙個map,記錄uid落在環上的哪個slot裡
同時:1)啟動乙個timer,每隔1s,在上述環形佇列中移動一格,0->1->2->3…->29->30->0…
2)有乙個current index指標來標識剛檢測過的slot
當有某使用者uid有請求包到達時:
1)從map結構中,查詢出這個uid儲存在哪乙個slot裡
2)從這個slot的set結構中,刪除這個uid
3)將uid重新加入到新的slot中,具體是哪乙個slot呢 => current index指標所指向的上乙個slot,因為這個slot,會被timer在30s之後掃瞄到
(4)更新map,這個uid對應slot的index值
哪些元素會被超時掉呢?
current index每秒種移動乙個slot,這個slot對應的set中所有uid都應該被集體超時!如果最近30s有請求包來到,一定被放到current index的前乙個slot了,current index所在的slot對應set中所有元素,都是最近30s沒有請求包來到的。
所以,當沒有超時時,current index掃到的每乙個slot的set中應該都沒有元素。
優勢:(1)只需要1個timer
(2)timer每1s只需要一次觸發,消耗cpu很低
(3)批量超時,current index掃到的slot,set中所有元素都應該被超時掉
這個環形佇列法是乙個通用的方法,set和map中可以是任何task,本文的uid是乙個最簡單的舉例。
10w定時任務,如何高效觸發超時
二 環形佇列法 廢話不多說,三個重要的資料結構 1 30s超時,就建立乙個index從0到30的環形佇列 本質是個陣列 2 環上每乙個slot是乙個set,任務集合 3 同時還有乙個map,記錄uid落在環上的哪個slot裡 同時 1 啟動乙個timer,每隔1s,在上述環形佇列中移動一格,0 1 ...
定時任務沒觸發 10W定時任務,如何高效觸發超時
需求背景 1.延遲訊息功能。例如 滴滴打車訂單完成後,如果使用者一直不評價,48小時後會將自動評價為5星。2.無效連線斷開。在im系統中,客戶端會與服務端建立大量的長連線,當客戶端與服務端30s內沒有心跳的話,需要把這個連線斷開。一 最傳統的方案 建立一張延遲訊息表,滴滴訂單完成後插入一條延遲訊息,...
定時任務高效觸發
圓通處事,方能達到目的 開發中我們經常會遇到一些需要定時來解決的業務場景。比如,有這樣乙個需求 如果連續30s沒有請求包 例如登入,訊息,keepalive包 服務端就要將這個使用者的狀態置為離線 將所有任務都新增到某集合中,定時輪詢掃瞄,如果達到條件則進行相關處理 let map new map ...