定時任務高效觸發

2021-08-02 02:16:38 字數 1821 閱讀 2973

圓通處事,方能達到目的!

開發中我們經常會遇到一些需要定時來解決的業務場景。比如,有這樣乙個需求:「如果連續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 ...