問題
其實分布式系統接口的調用順序,也是個問題,一般來說是不用保證順序的。但是有時候可能确實是需要嚴格的順序保證。給大家舉個例子,你服務 A 調用服務 B,先插入再删除。好,結果倆請求過去了,落在不同機器上,可能插入請求因為某些原因執行慢了一些,導緻删除請求先執行了,此時因為沒資料是以啥效果也沒有;結果這個時候插入請求過來了,好,資料插入進去了,那就尴尬了。
本來應該是 “先插入 -> 再删除”,這條資料應該沒了,結果現在 “先删除 -> 再插入”,資料還存在,最後你死都想不明白是怎麼回事。
是以這都是分布式系統一些很常見的問題。
剖析
首先,一般來說,個人建議是,你們從業務邏輯上設計的這個系統最好是不需要這種順序性的保證,因為一旦引入順序性保障,比如使用分布式鎖,會導緻系統複雜度上升,而且會帶來效率低下,熱點資料壓力過大等問題。
下面我給個我們用過的方案吧,簡單來說,首先你得用 dubbo 的一緻性 hash 負載均衡政策,将比如某一個訂單 id 對應的請求都給分發到某個機器上去(及需要保證順序性的操作請求放到一個機器去處理),接着就是在那個機器上因為可能還是多線程并發執行的,你可能得立即将某個訂單 id 對應的請求扔一個記憶體隊列裡去,強制排隊,這樣來確定他們的順序性。
但是這樣引發的後續問題就很多,比如說要是某個訂單對應的請求特别多,造成某台機器成熱點怎麼辦?解決這些問題又要開啟後續一連串的複雜技術方案......曾經這類問題弄的我們頭疼不已,是以,還是建議什麼呢?
最好是比如說剛才那種,一個訂單的插入和删除操作,能不能合并成一個操作,就是一個删除,或者是什麼,避免這種問題的産生。
出處:https://github.com/doocs/advanced-java/blob/master/docs/distributed-system/distributed-system-request-sequence.md