目標自主安全可控 中國銀聯分散式資料庫實踐

劉美利發表於2018-08-20

導語: 本文根據周家晶老師在2018年5月12日【第九屆中國資料庫技術大會(DTCC)】現場演講內容整理而成。

周家晶

中國銀聯股份有限公司 高階工程師

中國銀聯分散式中介軟體UPSQL Proxy負責人,從事開源資料庫MySQL的研發工作,主要關注分散式事務、SQL最佳化等。

摘要: 介紹銀聯為滿足自主安全可控這一目標,透過較長時間的積累,所形成的MySQL產品體系與架構。具體介紹分散式資料庫中介軟體的分散式事務實現機制、SQL最佳化和分散式儲存引擎實踐。

正文:

分散式資料庫

分散式資料庫簡單來說就是海量資料和高效能要素可以水平擴充套件的資料庫。中國銀聯在2014年開始投入MySQL開源資料庫,主要為了自主可控以及去IOE。

產品的建設分為UPSQL和UPSQL Proxy。

回顧整個研發歷程,可以分為三個階段,初期、中期和當前。初期主要關注高可用、讀寫分離和分庫分表;中期階段開始考慮一些更加複雜議題,比如說分散式事務如何支援和實現、資料庫連線池以及SQL解析執行最佳化;當前是一些新的議題,比如複雜查詢。

初始架構

銀聯的初始架構,從下往上看,最下層是UPSQL data node資料節點,主要負責資料庫層的高可用,是一個邏輯節點。中間層叫做UPSQL Proxy,在生產實踐中我們一般錄入兩個或兩個以上UPSQL Proxy。最上面一層是客戶端,應用上要求負載均衡連線兩個UPSQL或Proxy,同時我們有一個adm-server的元件,這個元件跟UPSQL和Proxy協同完成資料庫檢測和高可用決策、切戶以及Proxy隔離,實現了從資料節點到UPSQL Proxy節點的高可用切換。

在整個研發工程中,我們一直在思考一個問題:Spanner方案和Proxy方案現在是業界的兩種方案,那麼Spanner方案和Proxy方案在功能上有哪些區別,是否Spanner就是最終解決方案?

分散式資料庫

無論是Spanner方案還是Proxy方案,在分散式事務實現上只有一條途徑,那就是2PC。銀聯的實現方案主要有兩點:一是用後端的資料庫儲存XA日誌,避免對其他分散式元件依賴,另一點則是使用最後參與者策略去最佳化效能。

方案對比

左側是一個通用方案,右側是我們的方案。

左側方案,在一個全域性事務裡,寫入兩個資料分片節點,在commit 階段兩個本地事務都會做XA,然後選擇一個節點進行分散式日誌記錄,完成之後,整個事務分散式就可以保證提交了,最後再進行xa commit。

2PC方案最大的問題就是參與者和協調者處理網路異常資料比較困難,透過分散式日誌就可以保證對異常的處理。

我們方案的區別是,選擇某一個本地事務,比如選擇資料分片1作為最後參與者,最終參與者不需要使用XA事務,過程中不需要做xa commit,並由最後參與者進行分散式日誌記錄。

主要優勢

a)     不需要使用單獨會話進行xa日誌記錄(友商方案中向xa日誌表的寫入是自動提交的另一個會話)

b)     減少一個兩階段事務

主要缺點

a)     涉及分散式事務的後端使用者,都需要配置xa日誌表許可權,因而存在運維風險。

所以左側方案更適合雲上公共產品的使用,右側方案依賴嚴格的運維管理性策略。

分散式死鎖

但是我們發現一個分散式死鎖的問題。比如說,全域性事務的a&b開啟分散式事務,那麼在time 1: a write db1.resource1 、time 2: b write db2.resource2緊接著time 3: a write db2.resource2、 time 4: b write db1.resource1,交叉反向的操作導致db1和db2上都出現了ab的所有等待,從全域性的角度上看,就出現了死鎖的問題,那麼怎麼去解決這個問題呢?

死鎖檢測

一個方案就是衝突圖的檢測。我們需要修改innodb-trx表,增加XAID資訊,將XAID作為全域性事務的一個標誌,以XAID的角度去看這個鎖的關聯關係。這樣只要我們拿到所有參與這張表的資訊,就可以實現對死鎖衝突的檢測。

死鎖預防

分散式死鎖的預防策略是時間戳策略(Timestamp ordering, TO),保證單一時序的鎖等待,來避免死鎖的發生。

具體做法是,在XAID的生成規則裡進行邏輯時間拼接,事務開始時間+ TM(proxy)事務序號+ TM編號+ datanode + ...就可以保證業務上的需求。然後在DeadlockChecker::search() 中獲取xaid,根據死鎖預防策略進行處理,進行一個簡單的時序保證。

進一步最佳化

 雖然我們使用了最後參與者,但是最後參與者在整個事務提交過程中事務管理上是有相互的。我們正常的事務是begin、commit就結束了,要想盡可能的讓操作一樣多,就需要把xa end拿掉。拿掉的做法也很簡單,以前在進入xa commit之前,會要求所處的事務狀態必須先是xa end然後才能跳轉到提交執行,現在把這個約束給修改掉,這樣就會減少一個網路互動。

架構演變

從初期的上線結構推進到中期階段,整個邏輯上沒有太大的變化,但是UPSQL Proxy和UPSQL之間的內在聯絡變的更為緊密。

SQL解析最佳化

為什麼要做SQL解析最佳化?

關於Proxy,首先要做SQL解析,然後是路由計算、分散式執行計劃計算、網路IO。這樣,很明顯可以發現Proxy主要資源開銷和效能最佳化點為: SQL解析和網路IO。

為避免硬解析,業界提供了兩種方法:一種是Prepare,做一次語句解析後,使用語句編號與變數值進行互動。我們在最開始做的時候,Proxy已經支援了Prepare,Prepare協議的優點是不需要對它做SQL解析。

另外一種方法是軟解析,即如果是相互的語句,就可以複用之前的語法樹,這樣的話都能夠避免SQL解析重複提高效能。

相似性最佳化

Prepare避開了語句輸入這一層,軟解析避開了詞法解析這一層,那麼我們就考慮能不能只做詞法解析不做語法解析。於是我們提出了相似性最佳化,即輸進去的語句透過詞法解析之後,如果發現語法樹相似就直接複用之前的語法樹。

相似性分析

詞法分析的結果是一組單詞序列,單詞序列的每個單詞由單詞型別和值組成。

MySQL的SQL解析過程中,詞法和語法解析耦合在一起,即語法解析的移進規約動作觸發詞法解析,而不是先完成詞法解析,再開始語法解析。我們將流程修改為先完成詞法解析獲取單詞序列,然後進行語法解析。

另外是我們定義的相似性規則。什麼是相似呢?就是對比兩個SQL的單詞序列,滿足單詞型別相同,如果是型別非引數,則要求單詞的值相等(忽略大小寫)。我們根據這個相似性規則制定了一個相似性hash演算法,用於提升相似性查詢效能。

相似性複用

需要實現該功能點,需要修改LEX_STRING。LEX_STRING是詞法分析和語法解析的最基礎資料。這裡增加兩個欄位,一個是index,即其在詞法解析中的位置。另一個是next_lex_string(MySQL的SQL語法中,它可以把連續的兩個字串拼接到一起,next_lex_string表示的是字串後續的下一個字串)。

複雜查詢

 

如何解決複雜查詢(例如典型的跨庫Join)?

基於MySQL有兩條路,一條是強化Proxy層構建支援複雜查詢的執行計劃,但是這樣做代價很高,並且無法保證SQL解析知識的完備性以及分散式計劃的症狀性,風險性很高。

另一條路是使用分散式儲存引擎,MariaDB Spider和MySQL NDB。但是MariaDB Spider同步呼叫較多、效能不佳,而MySQL NDB缺乏實踐經驗。MariaDB Spider是一個比較完善的解決方案,但其水平擴充套件主要是擴充套件儲存容量,效能上的提升不明顯。

因此我們就考慮做一個類似於MariaDB Spider的方案。

設計思路(Federated+Proxy)

設計思路:Federated+Proxy

核心思路是,由Federated引擎外掛UPSQL Proxy,由UPSQL Proxy實現資料拆分和事務管理。這樣UPSQL Proxy把拆表的過程隱藏起來,Federated連上去的時候只看到一個單表,就可以輕鬆實現複雜查詢了。

這樣的改動邏輯簡單,功能可控。但是缺點也很明顯:Federated是使用同步請求訪問UPSQL Proxy,且UPSQL Proxy被遮蔽在Federated之後,導致整體效能低下。

設計思路(語句分類路由)

設計思路:語句分類路由

核心思路是,OLAP和OLTP的融合技術。一條應用語句過來了之後,我們做一個語句分類,把複雜語句交給OLAP,簡單語句交給OLTP,然後最終都訪問同一個事務管理模組和執行模組,這樣可以保證無論什麼樣的語句都居於統一的事務之中。

設計思路:(協處理器:XProxy)

在我們的方案中,我們研發了一個XProxy協處理器。

核心思路是,UPSQL 和Proxy拿到語句後,做一個解析和分類執行,如果是一個複雜語句,就丟給MySQL Server,它會把複雜語句拆解成簡單語句,然後反向的丟回給UPSQL 和Proxy。這個路徑很長,但是優點是簡單語句可以透過Proxy直接到資料庫上,同時也可以支援複雜語句。但是缺點是互動次數變多,效能較差。

夥伴部署

在實際部署中我們會考慮兩種部署方案,一種叫做夥伴部署。

 把UPSQL 、Proxy和MYSQL一一對應部署在一起,但是缺點是需要額外增加一個資源。

叢集部署

 第二種方案叫叢集部署,也就是在夥伴部署的基礎上做了一些改動。將XProxy引擎下沉到資料儲存節點,實現資源複用。這樣可以實現UPSQL 、Proxy和資料節點之間是叢集和叢集的關係。一般情況下我們會把它的複雜查詢入到下面的一個備庫,這樣可以保證效能和資源。但是這種叢集關係必須要保證Proxy轉發請求到回來的這種雙方的關聯關係。

 複雜查詢總結

•      XProxy實現要點:

a)    使用STMT協議訪問UPSQL Proxy

b)   會話關聯(UPSQL Proxy與XProxy雙向話關聯),事務管理器關聯

c)    線上DDL

•      進一步最佳化(生產實踐優先順序低):

a)    ICP(Index Condition Pushdown)

b)   ECP(Engine Condition Pushdown)

•      該方案在如下場景下效能極差,複雜查詢下:

a)    不帶過濾條件的分頁– 需要增加儲存引擎介面

b)     統計運算- 可以借鑑MariaDB Spider的MapReduce方案

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31542119/viewspace-2212406/,如需轉載,請註明出處,否則將追究法律責任。

相關文章