最終一致性,從其名字看,已經放棄了強一致性,如果出現異常情況,很有可能會產生主業務已提交,邊緣業務最終也沒能一致的情況。如網絡持續不通,一段時間重試后,任務不得不放棄
因此最終一致性還有一層隱含信息->做好最終不一致的備案,否則可能造成不可預期的問題。
目前做法
和事務型數據庫一同提交
想要做到原子性,強一致性,需要將邊緣業務的信息和主業務一同提交到事務型數據庫中,通過已有的事務特性來保證一致性。
具體的做法是在數據庫,如mysql中,建一個邊緣任務表,和主業務流程的更改一同入庫。
將邊緣的任務方法,通過aop增強的方式,改造成往數據庫中存入一條記錄,和主業務一同提交到mysql,然后再通過異步、重試、告警等方式履行邊緣任務的代碼。
如果邊緣任務重試次數超過閾值仍沒有成功,就需要告警或者監聽器的方式,告知備案程序,如單獨記錄一個失敗任務信息,通過人工來處理這些失敗的任務。
邊緣任務獲取
京東有一款分布式事務中間件,通過一致性hash算法來獲取任務,讓每個應用節點獲取到不同的任務,避免多個任務同時被多台機器請求到,這樣做需要引入一個額外的分布式系統,來監控各個應用節點的心跳,如果某個機器離線了,其他機器就可以接手它的任務。
冪等性
冪等是最重要的問題,在分布式系統中可能出現各種意料之外的問題,比如一個任務開始之后,向數據提交任務完成事件前掛掉了,其他節點會把當前任務進行重試,避免任務漏做。還有很多這種情況,解決的辦法都是冪等,多次執行結果和執行一次的效果相同,如發送郵件,如果要做到冪等,需要根據邊緣任務做了一個鎖或者信號,其他任務發現這個鎖或者信號,就知道任務正在被執行或已完成,這樣就可以避免發送兩次郵件
封裝
代碼的微入侵,可以通過aspectj在編譯時增強代碼,也可以通過javaagent在啟動時增強,還可以在運行時利用spring aop增強,方法很多,各有優劣,其中spring aop存在“自調用”問題:原始類內部方法調用無法觸及增強代碼。
關於遠程邊緣任務數據中心
如果邊緣業務表在本地數據庫,則需要每個應用都在自己的庫中建表,這種體驗不太好,因此,又有了中心化存儲邊緣任務的模式,這種模式效率相較於本地庫會低一些,且存在風險