376
技術社區[雲棲]
保證數據一致性的常見做法
我們在做業務時,很多時候都用到了事務。最近業務涉及也蠻多的,這裏總結下。 單庫用事務就可以搞定,但是事務不是萬能的。就算隔離級別是可重複讀,並發情況下也會出現更新丟失的問題,所以事務並不能一定保證數據一致性。但在事務中使用悲觀鎖可以辦到。但是悲觀鎖用的不好可能導致死鎖,而且從底層上說使用的是排占鎖,性能肯定達不到很高。換個思維用樂觀鎖也可以解決,樂觀鎖提高了並發性能,但是樂觀鎖會導致很多修改失敗拋出異常,說不定反而會影響性能,這裏不多講這兩個東西。
多庫或者多服務時問題就稍顯複雜。我們怎麼保證這種場景下的數據的一致性呢?該場景下數據的一致性分強一致性和弱一致性。一般業務場景下,我們用的多的還是弱一致性,畢竟開發成本低的多。隻要允許一定時間窗口數據不一致,但是又能保證數據最終是一致的就可以選這個。弱一致性大多是通過補償機製來完成。這裏總結為三種方式:
- 推.A主動向B推送消息或者主動調B的接口,MQ消息或簡單HTTP調用,直到對方給你確認OK為止。
- 拉.B主動取A查詢消息結果,直到確認數據OK。
- 冥等性.多次重複操作,必須保證結果是一樣的。這裏可以為消息加一個唯一標識,並且要存這個消息的狀態。相同的消息隻處理一次,並做狀態判斷。
就拿我們調用第三方扣款,扣用戶賬戶的錢為例。
- 直接調用,同步返回結果,改狀態最簡單。但是這樣弊端明顯,用戶體驗不好,可能等半天才返回,最好做成異步。
- 調用過程中超時了。我不知道是請求超時,還是返回超時。怎麼辦?如果對方支持重複調用肯定很好,再次調用直到成功。如果對方調一次扣一次,那就隻有拿上次調用的數據去查結果,如果成功了則改狀態,如果對方說你這個數據沒收到過,那就再發起一次請求。這樣一直類推直到成功。
如果是操作特別敏感的數據,那麼就要求保證數據的強一致性。
常用的分布式場景強一致性協議有二階段提交協議。顧名思義事務的執行分為兩個階段,第一事務執行,第二事務提交。協調者詢問A,B庫是否可以開始執行事務,A.B都回答是,那麼A繼續執行事務,B繼續執行事務。當A,B都報告執行完畢時,這時第一階段算是完了。第二階段協調者告訴AB都去提交剛才的事務,當AB都提交後,各自釋放資源。其中執行事務的時候會記錄各自的undo和redo日誌,這個別忘了。裏麵存在的問題大家都注意到了吧。
- 第二階段通知A,B提交事務時,如果A成功通知了,B沒通知到,那豈不是數據都不一致了,而且B隻有等到超時才會釋放資源。
- 所有的過程都是同步阻塞的,這就意味著性能會大大降低。
- 協調者這個角色存在單點問題,如果它掛了其他事務都會一直占用資源直到超時。
雖然工作中我們很少會用到這種協議接口,但是根據這個思路,我們也不難開發自己的分布式事務接口。開發過程中,總是要在數據的正確定和係統的性能間去尋找那個平衡點。我們是單一的把代碼搞在一起,避免出現分布式事務,還是把係統拆分開發部署。這個問題沒有最好的答案,關鍵點還是要看你目前的業務量。
最後更新:2017-04-10 22:01:15