微服务Apache ServiceComb 数据一致性Saga演进介绍
2019獨角獸企業重金招聘Python工程師標準>>>
ServiceComb數據一致性解決方案Saga演進介紹
?
本文轉自 微服務 開源項目 Apache ServiceComb (incubating) 的官方博客:
http://servicecomb.incubator.apache.org/cn/docs/saga_pack_design/
?
傳統的單體應用的微服務化改造過程中大多會面臨數據庫拆分,故而原來由數據庫保證的數據一致性也一定面臨重新設計和實現,此時需要引入分布式數據一致性方案來解決。常見的解決方案主要有2PC,TCC,事件驅動等,而在微服務開源項目 ServiceComb中提出并實現了使用Saga[1]來解決微服務的數據一致性難題,不同方案的對比可參考《ServiceComb中的數據最終一致性方案》[2]一文。Saga是一個數據最終一致性的解決方案,它允許我們成功地執行所有事務,或在任何事務失敗的情況下,補償已成功的事務,并提供了ACID[3]中ACD的保證(由于事務是交錯執行的,可能會看到其他事務的部分結果,因此不能滿足隔離性要求)。因此,Saga適用于以下跨服務的事務場景:
- 嵌套調用。如網上購物時,會依次經過下單、支付服務和第三方支付這幾個子事務,其中,下單依賴于支付服務的返回狀態,而支付服務也包含了多種可選的支付方式,并依賴于具體支付方式返回的結果。通過Saga,可以清晰地看到一個完整事務中各個服務之間的關系,在異常時也能快速定位出現問題的子事務。
- 高并發。如秒殺場景下,在成功扣除庫存和完成支付后方可認為秒殺成功,若成功扣除庫存但支付失敗則自動進行補償(即恢復庫存)。鑒于Saga只有提交和補償兩種狀態,成功場景下只需對每個子事務進行一次調用即可,因此可以在高并發下保持高性能。
- 調用時間長。如線上購買電影票,選好座位后一般會有15分鐘的支付時間。Saga僅在子事務的提交階段對資源進行短暫的鎖定,且通過超時機制確保事務超時后能自動補償,即在規定時間內沒有支付成功的話就自動釋放鎖定的座位,極大地簡化了業務出現異常時的處理邏輯。
Saga新版本演進
新年新氣象,Apache ServiceComb(incubating) Saga[4](以下簡稱Saga)進行了演進。相對于上一版[2],新演進的設計主要有以下優勢:
- 極大提升易用性。開發者只需使用2-3個注解(即啟用事務服務:EnableOmega、全局事務標記:SagaStart和子事務標記:Compensable)。
- 更方便擴展。對微服務框架的支持更友好。
- 數據一致性與業務邏輯解耦。在演進后的設計中,通過服務側omega的引入,saga協調器的職責更為單一(只需負責協調事務的完整性),與具體業務無關,因此,開發人員可以聚焦在具體業務的開發。
Saga演進后的架構,如下圖所示,主要包含兩個組件,即alpha和omega,其中:
- alpha充當協調者的角色,主要負責對事務的事件進行持久化存儲以及協調子事務的狀態,使其最終得以與全局事務的狀態保持一致,即保證事務中的子事務要么全執行,要么全不執行。
- omega是微服務中內嵌的一個agent,負責對網絡請求進行攔截并向alpha上報事務事件,并在異常情況下根據alpha下發的指令執行相應的補償或重試操作。
omega內部運行機制
omega是微服務中內嵌的一個agent,負責向alpha上報事務狀態并與其它omega直接傳遞事務上下文信息。其中,每個服務的事務上下文包括:
- 全局事務id(Global Tx Id):用于唯一標識全局事務,一般在全局事務入口生成,并在整個事務過程中傳遞。
- 本地事務id(Local Tx Id):用于唯一標識本地事務,一般由本地事務生成。
- 父事務id(Parent Tx Id):用于構建子事務間的關系,可由請求上下文中構建。
如下圖所示,分布式事務與用于分布式調用鏈追蹤的zipkin[5]的處理流程很類似,在服務提供方,omega會將請求攔截并從中提取請求信息中的全局事務id作為其自身的全局事務id(即Saga事件id),并將請求中的本地事務id作為其父事務id,且使用新生成的id作為本地事務id;在服務消費方,omega會將請求攔截并往其中添加當前的全局事務id和本地事務id。通過服務提供方和服務消費方的這種協作處理,子事務能連接起來形成一個完整的全局事務。
omega在預處理階段會先向alpha發送事務開始的事件,在后處理階段會再向alpha發送事務結束的事件。alpha在收到事件后會進行持久化的存儲。因此,每個成功的子事務都有一一對應的開始及結束事件。
在omega啟動時會向alpha注冊,使得異常或者超時場景下,alpha能通過回調向omega發送重試或補償的命令和相應的調用參數,從而確保全局事務的一致性。
具體處理流程
成功場景
全局事務開始前omega會先向alpha發送全局事務開始的事件,并在所有子事務完成時向alpha發送全局事務結束的事件。而每個子事務在執行前也會向alpha發送事務開始的事件,在成功執行后,會向alpha發送事務結束的事件。子事務間通過全局事務id連接在一起,但也因本地事務id而有所區分。因此,在成功場景下,每個開始的事件都會有對應的結束事件。
異常場景
在子事務執行期間拋出異常時,omega會向alpha上報aborted事件,然后alpha會向該全局事務的其它已完成的子事務發送補償指令,確保最終同一全局事務下的所有子事務要么都成功,要么都回滾。由于事務中沒有明確指定全局事務中的參與者,因此,alpha的掃描器會定期查詢事件表并找出已完成所有補償子事務的全局事務,然后對這些全局事務添加全局事務結束事件以保證事務的完整性。
超時場景
alpha的掃描器會定期掃描正在處理的事件狀態,若發現事件超時,則會記錄相應的aborted事件,然后alpha會向該全局事務的其它已完成的子事務發送補償指令來恢復至事務開始前的狀態。
如何使用?
Saga的使用主要涵蓋兩方面,alpha的啟動及omega的使用。
alpha的啟動
alpha啟動前需要先運行數據庫PostgreSQL:
docker run -d -e "POSTGRES_DB=saga" -e "POSTGRES_USER=saga" -e "POSTGRES_PASSWORD=password" -p 5432:5432 postgres?
在確保數據庫正常啟動后,即可運行alpha:
docker run -d -p 8090:8090 \-e "JAVA_OPTS=-Dspring.profiles.active=prd" \-e "spring.datasource.url=jdbc:postgresql://{docker.host.address}:5432/saga?useSSL=false" \alpha-server:0.1.0?
omega的使用
omega的使用很簡單,以一個簡化的轉賬業務為例,同一筆轉賬要么轉入和轉出都成功,要么都失敗。在這樣一個業務中引入Saga,只需簡單幾步即可:
?
Copy
2.2 在全局事務的起點添加?@SagaStart?的注解。
@SagaStart(timeout=10)public boolean transferMoney(String from, String to, int amount) {transferOut(from, amount);transferIn(to, amount);}?
2.3 在子事務處添加?@Compensable?的注解并指明其對應的補償方法。其中,補償方法的形參列表需與子事務方法的形參列表保持一致。
@Compensable(timeout=5, compensationMethod="cancel")public boolean transferOut(String from, int amount) {repo.reduceBalanceByUsername(from, amount);}public boolean cancel(String from, int amount) {repo.addBalanceByUsername(from, amount);}?
2.4 對轉入服務重復第2.3步即可。
2.5 在每個服務的application.yaml中添加配置項,指明服務信息和alpha的地址信息:
spring:application:name: {application.name}alpha:cluster:address: {alpha.cluster.addresses}?
目前Saga的實現還存在著很多有意思且有挑戰性的課題,如alpha的協調調度實現、冪等的實現及自動補償的實現等,歡迎有志之士與我們攜手一起解決數據一致性的難題,共同為完善微服務生態貢獻自己的力量。
如何加入Apache ServiceComb 社區:
http://servicecomb.incubator.apache.org/cn/docs/join_the_community/
?
參考文獻
[1] Apache ServiceComb 官網,
http://servicecomb.incubator.apache.org/cn/
[2] 代碼參考項目地址? Apache ServiceComb(incubating) Saga,
https://github.com/apache/incubator-servicecomb-saga
[3] ServiceComb中的數據最終一致性方案,
http://servicecomb.incubator.apache.org/cn/docs/distributed_saga_1/
http://servicecomb.incubator.apache.org/cn/docs/distributed_saga_2/
http://servicecomb.incubator.apache.org/cn/docs/distributed_saga_3/
[4] Sagas, Hector Garcia-Molina & Kenneth Salem,?
https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf
[5] ACID, Wikipedia,?
https://en.wikipedia.org/wiki/ACID
[6] zipkin, zipkin,?
https://github.com/openzipkin/zipkin
[7] 碼云地址,
https://gitee.com/servicecomb
https://www.oschina.net/p/servicecomb
轉載于:https://my.oschina.net/u/3823482/blog/1798723
總結
以上是生活随笔為你收集整理的微服务Apache ServiceComb 数据一致性Saga演进介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue安装jquery插件
- 下一篇: UWP 剪贴板 Clipboard