問題背景:近期在重構公司內部一個重要的任務系統,由于原來的任務系統使用了MongoDB來保存任務,客戶端從MongoDB來取,至于為什么用MongoDB,是一個歷史問題,也是因為如果使用到MongoDB的數組查詢可以減少任務數量很多次,假設這樣的情況,一個md5需要針對N種情況做任務處理,如果用到MongoDB的數組,只需要將一個md5作為一條任務,其中包含一個長度為N的待處理任務列表(只有N個子任務都處理完后整個任務才算處理完畢),這樣整個任務系統的數量級就變為原來的1/N。細節描述:1.當MongoDB的任務數量增多的時候,數組查詢相當的慢,任務數達到5K就已經不能容忍了。2.任務處理每個md5對應的N個子任務必須要全部完成才從MongoDB中刪除3.任務在超時后可以重置改進方案如下:由于原有代碼的耦合,不能完全拋棄MongoDB,所以決定加一個Redis緩存。一個md5對應的N個子任務分發到N個Redis隊列中(拆分子任務)。一個單獨的進程從MongoDB中向Redis中將任務同步,客戶端不再從MongoDB取任務。這樣做的好處是拋棄了原有的MongoDB的數組查詢,同步進程從MongoDB中取任務是按照任務的優先級偏移(已做索引)來取,所以速度比數組查詢要快。這樣客戶端向Redis的N個隊列中取子任務,把任務結果返回原來的MongoDB任務記錄中(根據md5返回子任務)。改進過程遇到的問題:由于客戶端向MongoDB返回時候會有一個update操作,如果N個子任務都完成,就將任務從MongoDB中刪除。這樣的一個問題就是,經過測試后發現MongoDB在高并發寫的情況下性能很低下,整個任務系統任務處理速度最大為200/s(16核,16G,CentOS,內核2.6.32-358.6.3.el6.x86_64),原因大致為在頻繁寫情況下,MongoDB的性能會由于鎖表操作急劇下降。具體問題:(ThinkoutoftheBox)能否提出一個好的解決方案,能夠保存任務狀態(子任務狀態),速度至少超過MongoDB的?
MongoDB + Redis 任務隊列性能瓶頸
千萬里不及你
2019-04-08 11:16:51