時間輪算法
摘要:
最近上了一些課,記一下,好記性不如爛鍵盤不是
場景:
如:我們在RPC框架中每個請求肯定都會有超時的設計,那么我們怎么去設計這個超時的機制呢?都會說我們設置定時任務呀,定時多久執行一次,判斷請求是否超時,思路可以,但是具體我們怎么實現呢?
方案1:
我們做一個定時任務1S遍歷一次請求列表,查看多個請求哪個請求超時了就從列表中刪除,當然,這是一種解決方案。
我們來看一下上面這種思路,如果有10個請求的超時時間是1S、5S、10S....30S,我們每次遍歷都需要把每個請求都處理一遍才能找到超時的那個任務,那么中間是不是就出現了很多無意義的操作呢?
有什么更高效的方法嗎?
方案二:時間輪:
帶着這個問題我們看看如果用我們的時間輪怎么去處理這個問題。先看一張圖。這就像我們平時看到的鍾表一樣,在時間輪中有時間槽和時鍾輪的概念,時間槽就是我們看到的每個槽位,時鍾輪就是整個輪盤,也就是一個周期。
我們就按照上圖事例,將每個任務放到對應的時間槽位上,如:設我們當前時間是0S,有一下3個不同超時時間的請求:2S、4S、10S,那么我們將不同定時任務放到不同的槽位上就得到了如下圖的一個結果
我們可以看到不同超時時間的請求被掛在了不同的時間槽上,根據我們的時間走動,我們會找到不同的超時請求接下來我們按照按照這個思路去走一下看看是怎樣的一個情況:
當前時間:進入三個請求,分別是2S、4S、10S,分別放到了2、4、10時間槽上
1S:無請求,無需處理
2S:有一個超時的請求,將該請求從列表中清理掉(無需關注其他請求,節省了一次處理其他請求的時間)
4S: 有一個超時請求,將該請求從列表中清理
7S:假設這里有進來一個12S后超時的請求那么我們應該掛在哪呢? 從7往后數12個時間槽是在6那個槽位,我們繼續往下走
10S:這里有一個請求,那么我們清理掉
當我們走到12的時候第13秒我們就像時鍾一樣又回到了0。依次反復。當我們再到6的時候會遇到我們那個12S后超時的那個請求
這里注意【遇到】而不是【找到】,我們只管大膽的往前一步一步的走,當該時間槽上有請求的時候我們處理一下該時間槽上的請求即可,無需刻意去找。(你我的相遇都是上天注定,無法逃脫)
有思想的人會想到如果有多個請求被划分到了同一個時間槽上怎么辦呢?那就掛在原來那個請求后面呀,再多呢?那就繼續掛呀,其實這里用鏈表或者紅黑樹都可以,看你個人的一個選擇,但是需要注意的是,這里我們要做一個處理,排序,要保證每個最快到達超時時間的請求放在最上面,這樣也是為了將來能節省下來很多的無效遍歷
總結:
截止到這里我們再回過頭去看看我們的第一個方案,做個比較:總共四個請求
方案一:從0S開始遍歷,總共遍歷了
前三秒:3 * 3 = 9
4~5: 2 * 2 = 4
6~8: 3 * 1 = 3
9~11:3 * 2 = 6
12~20:9 * 1 = 9
總共是:31次
方案二:從0S開始,在沒有請求的時間槽上沒有遍歷
第2秒一次、第4秒一次、第10秒一次、第20秒一次
總共4次
哦~天吶,這是一種毫無可比性的了兩種方案呀。乖乖里格隆地洞
很久不寫了,有點不知道怎么寫了,請多多原諒