乙個超時功能的設計

2021-10-08 03:52:23 字數 1470 閱讀 6371

有乙個產品需求,需要執行某個動作之後,需要生成乙個超時的任務,在超時時間到了之後執行後續的動作,後續動作的執行大約耗時1秒鐘。

任務允許在未到超時間刪除,超時時間不超過30天。要求在現有的產品架構上實現此功能。

存在問題:

方案二既然方案一存在持久化的問題,那麼只要解決這個問題即可,比如儲存在乙個公共的儲存上面,如mysql和開啟持久化功能的redis。那麼到底應該選擇什麼

來儲存呢。mysql和redis都是天然支援有序的記錄。只是兩者使用的資料結構不同,mysql採用b+樹,而redis採用的是跳表。對於查詢而言,兩者的時間

複雜度都為n(logn)(redis直接在記憶體中相比mysql而言還少了io)。但是由於我們過期時間插入是非順序的,對於mysql索引插入和刪除同時還會帶來頁的**,而跳表插入和刪除

更加簡單。綜合考慮這裡採用redis儲存。

存在問題:

方案三所有新增的超時任務都儲存到同乙個zset中,所有例項的超時執行緒去消費這個zset。但是這就帶來了乙個問題,由於之前不同例項是不同zset因此不需要去分配

具體消費什麼任務,自己的zset中有什麼任務到期就消費什麼任務。現在所有的任務都在乙個zset中應該如何去分配呢,獲取到期任務的指令是zrange,只能獲取sorce範圍內的所有

資料,如果每個例項都是這麼獲取任務,那麼必然都是在重複消費。在redis5.0之後的版本中存在zpopmax/zpopmin命令可以滿足這個需求,每次例項執行緒取任務時彈出第乙個任務。但是在這之前的版本並不支援。

存在問題

方案四由於方案三存在任務分配問題,那麼是否可以單獨做乙個執行緒來分配所有已經到期的任務呢。因此就單獨使用乙個執行緒來獲取所有已經到期的任務,然後在將這些任務均勻的

分配到所有例項執行緒中去。最好的方式就是採用mq了。將該執行緒從redis中獲取的所有已經到期的任務都丟到佇列中,所有例項執行緒都消費佇列即可,不但解決了分配問題,

同時也不存在併發問題,任務丟失等問題。

缺點 方案五

是否有更簡單的方法來實現這個功能呢,答案是有的。既然使用了mq,可以在任務生成的時候直接傳送到mq中,利用mq延遲佇列的屬性來直接完成這個功能。當佇列中的訊息

到了過期時間之後才會被消費者消費。如rabbitmq可以採用ttl和死信佇列來完成這個功能。

缺點 其實這個是在研發時候經常會遇到的需求,在不同的需求下有不同的解決方案。以上是自己在遇到這個需求時候的考慮,最終選擇的是方案五。但是可能存在更好的解決方式。

再此也是記錄一下這個看似簡單的需求,背後自己的思考。如果有更好的解決方案,也希望大家不吝賜教。

設計乙個具有getMin 功能的棧

設計乙個具有getmin 功能的棧 1.push pop getmin 時間複雜度為o 1 2.設計棧時可以使用現有的棧結構 設計乙個具有getmin 功能的棧 1.pop,push,getmin 時間複雜度為o 1 2.設計的棧可以使用現有的棧結構 author nemo public class...

設計乙個帶有getMin功能的棧

題目 實現乙個特殊的棧,在實現棧的基本功能的基礎上,再實現返回棧中最小元素的操作。要求 1,pop,push,getmin操作的時間複雜度都是o 1 注 1,設計的棧型別可以使用現有的棧結構。思路 可以考慮使用兩個棧來進行設計,乙個棧用來儲存當前棧中的元素,其功能和乙個正常的棧沒有區別,這個棧記為s...

如何高效的設計乙個新功能?

我從事過多年的概念設計,原型設計,測試到最終構建和部署應用程式的功能和api編寫的工作。根據我的經歷。很多次,我開發完乙個新的功能後,準備紀錄下來這個功能如何用。我會先介紹總結特徵的有用性,我會思考許多。有時寫作會很容易和流暢。有時我會寫到一半,不知道後面該如何寫了。連我自己都不知道,為什麼會發生這...