深度剖析分散式事務效能

葉東富發表於2021-10-11

隨著微服務的大規模應用,跨微服務的分散式事務也越來越多,那麼分散式事務的效能究竟怎麼樣?效能會下降多少?能否滿足業務需求?這些指標關係到分散式事務能否順利的引入到生產應用,是大家非常關心的問題。

本文嘗試深入分析分散式事務帶來的額外開銷,應用中的哪些因素會影響最終的效能,瓶頸點在哪裡,如何提升效能。本文以支援多語言的分散式事務管理器https://github.com/yedf/dtm的saga事務作為效能測試的樣本,對效能測試的結果,進行深度剖析。

測試環境

機型CPU/記憶體儲存系統Mysql
阿里雲ecs.c7.xlarge4核8G500G ESSD IOPS 26800Ubuntu 20.04Docker mysql:5.7

測試過程

# 在dtm目錄下
docker-compose -f helper/compose.mysql.yml up -d # 啟動Mysql

# 執行sysbench對mysql進行測試
sysbench oltp_write_only.lua --time=60 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password= --mysql-db=sbtest --table-size=1000000 --tables=10 --threads=10 --events=999999999 --report-interval=10 prepare
sysbench oltp_write_only.lua --time=60 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=root --mysql-password= --mysql-db=sbtest --table-size=1000000 --tables=10 --threads=10 --events=999999999 --report-interval=10 run

go run app/main.go bench > /dev/nul # 啟動dtm的bench服務,日誌較多,重定向到nul裝置
bench/run-dtm.sh # 新啟動命令列,執行dtm相關的各項測試

PS:如果您需要動手進行測試,建議您購買香港或國外的主機,這樣相關的github、docker訪問會快很多,能夠快速搭建好環境。我在國內購買的主機,訪問github和docker,非常慢,有時連線不上,無法順暢進行測試。

測試指標

我們會對以下幾個指標進行對比:

  • Global-TPS:使用者視角下,完成了多少個全域性事務。
  • DB-TPS:各項測試中,在DB層面完成的事務數量
  • OPS:各項測試中,完成了多少個SQL語句

結果對比

Mysql無DTM-2SQLDTM-2SQLDTM-2SQL-Barrier無DTM-10SQLDTM-10SQLDTM-10SQL-Barrier
Global-TPS-1232575531551357341
DB-TPS2006246423002124110214281364
OPS120394928575063721062092829548

Mysql效能

我們首先用測試了Mysql自身的效能。在DTM的這次效能測試中,寫操作較多,因此我們這次主要對Mysql的寫進行了效能測試。

我們採用了sysbench中的oltp_write_only基準,在這個基準中,每個事務包含6個寫SQL(有insert/update/delete)。

在這個基準下,每秒完成的事務數量大約為2006,完成SQL數量大約為為12039。這兩項結果,會在後續的DTM相關測試中引用。

DTM測試

分散式事務中涉及的事務模式有多種,我們選取一個有代表性的簡單Saga模式作為代表,分析分散式事務DTM的效能。

我們選取的Saga事務,包含兩個子事務,一個是TransOut轉出餘額,一個是TransIn轉入餘額。轉入轉出各包含兩個Sql,分別是更新餘額和記錄流水。

無DTM-2SQL

我們首先測試不採用DTM的情況,也就是直接呼叫TransOut和TransIn,測試結果是每秒完成了1232個全域性事務。每個全域性事務包含轉出和轉入兩個子事務,因此DB-TPS為2464,然後每個子事務又包含兩個SQL,因此總的SQL操作為4928。

這個結果對比MYSQL,DB-TPS更高,而DB-SQL只有一半,主要原因為每個事務都需要將資料同步到磁碟,需要額外消耗效能,此時瓶頸主要在系統資料庫的事務能力

DTM-2SQL

我們接著測試採用DTM的情況,採用了DTM之後,一個SAGA事務的時序圖如下:

image.png

全域性事務會包括4個事務:TransIn、TransOut、儲存全域性事務+事務分支、修改全域性事務為已完成。將每個子事務分支修改為已完成也各需要一個事務,但DTM採用非同步寫進行了合併,減少了事務。

每個全域性事務包括的SQL數量為:1個儲存全域性事務、1個儲存分支、1個讀所有分支、2個修改分支為完成、1個修改全域性事務為完成,一共6個額外的SQL,加上原本子事務的4個SQL是10個。

測試結果中,每秒完成全域性事務數為575,那麼DB-TPS為2300,OPS為5750,對比前面不採用DTM的方案,DB-TPS略有下降,OPS有一定的上升,瓶頸還是在系統資料庫

DTM-2SQL-Barrier

加入了子事務屏障後,每個子事務分支會多一個insert語句,每個全域性事務對應的SQL數量為12.

測試結果中,每秒完成全域性事務數為531,那麼DB-TPS為2124,OPS為6372,對比前面DTM的方案,DB-TPS略有下降,OPS略有上升,符合預期

無DTM-10SQL

我們對壓測的資料做調整,將每個子事務裡的SQL數量,從2調整為10,將子事務中的SQL迴圈執行5次。

無DTM的壓測結果中,每秒完成的全域性事務數為551,DB-TPS為1102,OPS為10620。這個結果中,OPS與MYSQL的接近,瓶頸主要在資料庫的OPS。

DTM-10SQL

這個壓測結果中,每秒完成的全域性事務數為357,DB-TPS為1428,OPS為9282,其中OPS比無DTM的情況下降了百分之十幾,主要原因為DTM的表,有較多的欄位及索引,每個SQL的執行開銷會大一些,因此總OPS會更低。

DTM-10SQL-Barrier

測試結果中,每秒完成全域性事務數為341,那麼DB-TPS為1364,OPS為9548,對比前面DTM的方案,DB-TPS略有下降,OPS略有上升,符合預期

小結

由於分散式事務需要儲存全域性事務和分支事務的狀態,會產生額外的寫,大約是每個全域性事務產生額外4+n(子事務數量)個SQL操作,2個資料庫事務。當業務很簡單,SQL少,使用分散式事務會導致事務吞吐量下降50%;如果業務較複雜,SQL多,效能大約下降35%。下降的原因主要為全域性/分支事務狀態的儲存,產生了額外的SQL操作。

從DTM的壓測結果與MYSQL的壓測資料對比來看,DTM產生的額外開銷很小,已經最大化的利用了資料庫的能力。

一臺ecs.c7.xlarge+500G磁碟的阿里雲伺服器,安裝mysql後,大約能夠提供300~600的Global-TPS,每月費用為900元(2021年10月價格),這個成本對比提供的業務能力來說,已經很低了。

如果您需要更強勁的效能,可以購買更高配的配置,也可以在應用層部署多組DTM,兩種方案的代價並不大,足以滿足絕大部分公司的需求。

歡迎大家訪問https://github.com/yedf/dtm專案,給顆星星支援我們的工作!

相關文章