1. 程式人生 > >介紹下用訊息佇列實現分散式事務

介紹下用訊息佇列實現分散式事務

    在OIE的時代, 上層應用開發人員總是認為資料庫足夠強大, 所以很多業務可以做的非常簡單。 比如A轉賬50元給B這個過程, 只要寫一個簡單sql語句塊就ok了。
   
    開始事務;
    A賬戶減去50
    B賬戶增加50
    提交事務。
    
    這個實現簡單明瞭, A賬戶錢減少的同時B賬戶的錢得到增加。但是當系統規模逐步擴大的時候, 只能不斷要求使用更好的硬體以及買更貴的資料庫lincence。 這種系統在超過一定規模後所需要的成本是指數增長的。為了獲得近乎線性的擴充套件能力, 好的解決方案當然是分庫分表。在分庫後, 這個事務就變成了一個分散式事務。不要看到多庫事務就想到XA, 如果資料庫是架構在廉價伺服器上, XA會帶來高昂的運維成本。 這裡介紹一下eBay的方法,就是用訊息佇列實現這種分散式事務。
    首先是業務分析, 系統是否必須在A賬戶減少的同時增加B賬戶。比如延遲50ms,在極端情況下,延遲秒級, 是否是可接受的。
    其實這個延遲基本都是可接受的。 相當於資金有了一個在途的過程。支付寶就是這麼幹的!
    接受這個延遲後, 我們在A賬戶所在的資料庫建立一個日誌表, 在B賬戶所在資料庫再建立一個日誌表。把事務分成兩個部分。
        A庫:
      1  開始事務
          A賬戶減去50
          A日誌表記錄要給B賬戶增加50, 同時生成全域性唯一交易id
          提交事務。
        
        B庫:
     2   開始事務
          B賬戶上應用A日誌表的要求(也就是給B賬戶增加50)。
          B日誌表記錄操作完成的交易id
          提交事務。
     3   更新A日誌表, 標記這個交易完成。

        這裡, 兩個日誌表其實相當於一個訊息機制。 有些中介軟體可以完全代替這兩個日誌表功能。比如阿里內部使用的notify。

    我們來分析上面這個過程。因為每個事務內涉及的賬戶表和日誌表都在同一個資料庫中, 所以上述兩個事務都是本地事務。
    假設步驟1完成, 2完成前中斷, 那麼修復程式只要掃描A日誌表, 然後重新從步驟2開始做就ok。
    假設步驟2完成, 步驟3完成前中斷。 那麼按照上面提到的方式修復程式可能會給B賬戶多加了50. 所以修復程式在修復時要先在B的日誌表裡查詢該交易id是否執行過, 如果已經執行過, 則跳過步驟2直接步驟3。

    在應用層上想辦法解決規模問題, 降低對資料庫的要求, 甚至能用kv系統實現的可以完全用kv系統解決; 降低對伺服器可靠性的要求, 應用自動處理錯誤恢復,這些實質上把伺服器和資料庫的價值轉移到了應用層。 所以每次看到一個系統大部分價值被伺服器廠商和資料庫廠商賺走而心存不甘的應用開發者們, 多想想辦法把價值留在自己手中吧。
    
    隨著雲端計算的發展, 更多的雲服務不斷推出, 大家徹底摒棄價格昂貴的小機和oracle的時代應該不遠了吧。



<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script> 閱讀(34) | 評論(0) | 轉發(0) | 給主人留下些什麼吧!~~ 評論熱議