來自:
最近在做乙個專案,其中乙個方案涉及到跨庫事務一致性問題,是乙個簡單的場景。這個專案是對老的業務進行效能提公升,業務邏輯基本上保持不變。主要是在於新專案採用了分庫分表的設計,從而提公升了效能。考慮到專案發布之後可能存在風險,採取了新老系統的並行方案。這個系統的業務比較簡單:接收來自外部的資料,然後對資料進行核對處理。為了保證新老系統能夠並行,在接收資料的時候必須實現雙寫方案,從而導致了跨庫事務的一致性問題。
下面一幅圖展示這一簡單的場景
這裡面會存在乙個小問題,就是可能存在寫入老庫成功,但是寫入新庫失敗的場景。
我們假設出現這種概率的情況是百萬分之一,在系統發布的情況下,這種概率可能更高。從目前我們的資料量來看,一天大概5000w,那麼出現不一致的資料量在500條。考慮到這個是資料核算系統,不能有一條丟失的情況,否則兩邊比對結果可能會不一致。所以需要保證一致性。
這種問題,有以下幾種解決方案
1 考慮使用jta等支援分布式事務的事務管理器
這種方案的優勢就是直接有現成的解決方案,一般的j2ee伺服器都提供了jta的相關的實現。比較明顯的問題就是解決方案太重量級。一般jta除了伺服器要支援,對應的資料庫服務廠商一般也要提供相應的商業支援,主要是提供基於 xaresource jdbc驅動,這一些商業上的支援,部分是需要付費的。而且使用xa 資料庫驅動,本身可能導致一些潛在的問題,尤其是基於不同的資料庫廠商的時候。而xa是基於兩階段提交協議,事務管理器為了完成乙個事務,需要多次和資料庫通訊,效率上比較低。
tenfy:這種方案比較重,需要具備更多的條件,但也說明jta本身已經有許多不錯的分布式解決方案了。
2 考慮使用資料庫自身的資料同步機制
如果新老庫的結構基本一樣,這種方案還是比較靠譜的。也是比較簡單的方案。這種方案的侷限性也再次。在本專案中,新庫不是乙個物理庫,而是多個物理庫,而老庫是乙個物理庫。如果要用資料庫自身的同步機制,涉及到多個庫和乙個庫之間的資料複製。同時由於分表的方案也不一樣,導致兩邊做乙個對映的配置,而這個需要在資料庫層面進行,邏輯相當的複雜,解決方案成本也比較高。相當於把重要的分庫分表的邏輯在資料庫這一層重新實現了乙份。
其實這個也帶來乙個維護問題,一旦我們覺得新系統已經足夠穩定。應用程式可以之間在寫入庫進行切換,把老庫的邏輯切掉,從而實現了只寫新庫的需求。整個過程也不需要進行再次發布。而資料庫的方案則需要停掉指令碼,在多個地方進行配置。
tenfy: 如果是同樣的結構,則可以直接用db自身的binlog機制或者半同步,ap只寫一次舊的庫即可,待db切換完成作一次比對後進行ap的切換。
3 在old庫存放相同的兩張模型表,一張表用於old庫的持久化表,另外一張作為臨時表,主要是作為需要同步到到新庫的資料。如果已經同步到新庫,就刪除。如果沒有同步到新庫就同步到新庫。這個過程採用定時機制,每分鐘定時提取臨時表一定資料量的資料,批量匯入到新庫。通過努力重試,來保證一致性。而新庫則需要保證冪等性,保證資料只會同步過一次。一般情況下,則是通過資料特徵識別符號來識別,這個一般都是資料的唯一性主鍵。
下面是簡單的實現:
這三種方案的主要思想就是 採取重試機制,這個只是分布式事務裡面的一種模型,相應的還有兩階段提交,異常恢復補償等機制。
tenfy: 其實臨時表的存在不一定是必須的,反而多乙個事務的操作,一旦要切掉舊的庫,這裡涉及到ap邏輯的修改,可以把臨時表去掉,ap只需操作舊的乙個庫即可,自己開發乙個拆分程式,及時分析舊庫的binlog後生成對新庫的操作指令,執行新庫的操作,這種方式還支援update,delete等操作,且該指令碼可以作為乙個通用程式服務後續類似的問題。
乙個簡單的事務
從這篇開始要總結事務了,我們就從乙個簡單的事務示例開始吧。下面這個示例首先定義了乙個事務,然後把關於乙個新訂單的資料記錄到資料庫中。示例 如下 use tsqlfundamentals2008 go 事務 乙個簡單的事務 begin tran 宣告乙個變數,儲存新的orderid declare n...
解決乙個跨域問題
因為我用flask框架 構建了乙個web 服務端,所以我建立乙個請求介面,這個介面 作用就是請求對方的 m3u8 鏈結,然後將響應內容返回給使用者 並且在這個函式中可以實現很多突破防盜煉的功能,例如 檢測請求頭中的referer字段。可以這樣寫 瀏覽器中支援很多協議,我相信都見到過這種 二進位制經過...
使用MySQL事務的乙個問題
mysql事務的預設隔離級別是repeatable read,也就是說在事務中每次讀到的資料都會是一樣的,不管其他人是否做過寫操作。乙個事務開始是剛建立連線,或上次提交或滾回。那麼如果在這種情況下使用mod perl,並保持db連線,那麼就可能出現資料不一致。比如乙個程序中有一段時間都沒有commi...