在資料庫上實現TAC需要具備哪些底層能力?

qing_yun發表於2023-11-06

資料庫高可用是企業級使用者在關鍵業務系統中對資料庫的基本要求,在高可用方面,怎麼提高能力都不為過。也正是因為高可用的問題,很多金融企業在選擇核心系統資料庫的時候,都被迫選擇分散式資料庫。因為目前國產集中式資料庫在高可用切換方面與分散式資料庫相比還存在較大的差距。前段時間在一個會議上,有一家券商就對某個國產集中式資料庫廠商提出了高可用的需求,問他們有沒有能力在證券交易系統上實現對Oracle的替代。

實現自動切換,RPO為零,RTO越低越好是關鍵業務系統給國產資料庫廠商出的一道考題。在這方面Oracle用TAC給出了一個近乎完美的答案。在Oracle RAC叢集中,如果某個節點故障,應用系統的連線可以快速的以秒級的速度切換到存活的節點,SELECT查詢以及絕大多數DML/DDL也可以直接切過去繼續執行。這意味著一個建表操作或者一個數百萬資料寫入的事務可以在使用者無感知的情況下在一個例項故障時完成透明切換。頂多終端使用者會感覺某筆交易的延時長了一點點。在23C中,TAC不僅僅支援RAC,還支援ADG,當ADG SWITCHOVER的時候,或者是ADG是採用同步模式的時候,主庫故障或者切換的的時候,應用可以透過TAC切換到ADG備庫。

看起來好像這個功能也不算太難實現,不過為了這個功能,Oracle從98那年的TAF推出到實現TAC FOR JAVA整整花了20年時間,而推出比較全面的TAC功能,要到明年了。Oracle花了25年完成的革命性的功能提升,其背後到底有什麼秘密呢?

一個外行來看資料庫產品的時候,往往覺得某些功能似乎很簡單,似乎只要開發人員程式碼寫得好一點,實現起來很容易。其實有些看似很簡單的功能的背後有著十分複雜的邏輯。就像大家一直吐槽的XID64,十多年過去了,在PG 16裡依然跳票了,雖然這個功能對於PG來說很必要,但是要想真正擁有這個功能沒那麼簡單。TAC可能不一定有XID 64複雜,但是已經足夠複雜了。當RAC某個節點故障的時候,應用的客戶端感知RAC節點故障,自動重連到備用例項,如果是隻讀事務,則根據PGA中的CURSOR資料以及SELECT發起時的SCN在新例項上繼續完成沒有完成的SQL PLAN餘下的操作。如果是寫操作事務,事務守護模組在新的連線中重放當前沒有完成的事務,實現無感知的自動切換。我們看上面的描述似乎實現起來並不難,實際上要想實現TAC功能,有很多基礎能力需要具備。

首先是資料庫產品必須擁有一個RPO為0的備機方案,這是確保TAC切換能順利完成繞不過去的技術點。業務系統高可用全自動快速切換中很重要的一點是資料0丟失。共享儲存多讀多寫,共享儲存強一致性讀寫分離、同步備機等都是可以實現RPO為0的備節點解決方案。如果是同步備機,一般而言可以選擇FAR-SYNC方案來避免備機對主庫產生的效能影響。

其次是高可用切換的備節點選擇問題,在多節點RAC上,如果某個節點故障時,無計劃,無策略的隨意切換會帶來很多不可知的問題,放大叢集自研動態REMASTER的開銷,嚴重時甚至會引發叢集效能問題。Oracle在這方面設計了SERVICE HA,需要做TAC的應用必須連線到某個設定好的SERVICE NAME,而每個需要TAC切換的SERVICE實現都已經配置好了HA切換策略。透過合理的SERVICE HA策略,可以確保切換的有序性。在這裡,就需要資料庫產品有SERVICE和SERVICE HA的能力。

資料庫核心具備了上述能力後,還需要客戶端能夠快速切換的能力。在TAF裡,是客戶端感知到伺服器端的異常後,主動採取的切換動作,因為網路超時、資料庫訪問超時等的判斷有一定的TIMEOUT限制,以及RETRY的需求,因此這樣的切換往往是分鐘級的,存在較大的 延時。為了更快的切換,必須採取其他的方案。Oracle為了實現快速切換,在服務端引入了一個服務—Oracle Notify Service(ONS),當某個資料庫例項故障時,ONS會很快發現,並透過Fast Application Notification(FAN)快速通知到每個連線到這個資料庫例項的會話。而每個BackEnd也都必須有接受FAN訊息,並且根據FAN訊息自動決策的能力。

當會話自動切換到新的資料庫例項上的時候,對於存在寫操作的會話,還需要能夠正在進行中的寫操作的能力。Oracle是透過Transaction Guard(TG)來實現的 ,TG透過當前會話正在進行的事務的完成情況自動完成未完成的事務。為了實現這個功能,Oracle引入了LTXID。LTXID的全稱是Logical Transaction ID,即邏輯事務ID。LTXID由以下四個部分組成:分支限定符(branch qualifier),用於標識事務的分支;全域性事務ID(global transaction ID),用於標識事務的全域性範圍;事務分支號(transaction branch number),用於標識事務的分支序號;事務序列號(transaction sequence number),用於標識事務的序列號。在TG中,把一個本地事務模擬成一個分散式事務,並將這個邏輯分散式事務的 ID與一個真實的本地事務做關聯。本地事務的變化也會同步到TG中的邏輯對映中,當發生故障切換時,TG可以根據當前操作的狀態(Prepared、committed、rolled back、complete、unknown等)採取不同的 自動化動作,完成寫操作的自動切換。如果事務的狀態是未知(unknown),事務協調器會重新查詢各個分支的狀態,並根據多數派原則(majority rule)決定事務的最終狀態,並選擇回滾還是提交。

似乎到這裡TAC所需要的功能基本上都羅列了,不過還沒完,還有很多很重要的小地方的改造。比如判斷當前資料庫切換時發生的哪些錯誤是可以恢復的,哪些錯誤是無法恢復的。比如當前事務中存在一個當前資料庫無法恢復的錯誤,那麼再去嘗試無損切換是不合理的,此時最好的辦法是向客戶端報個措,讓應用程式去處理這個故障。Oracle的處理方式是對每個故障增加了一個OracleException.IsRecoverable屬性,來標誌故障是否可恢復,對於可恢復的故障才採取TAC無損切換,否則立馬向客戶端報錯。

前幾天我寫了一篇關於Oracle TAC的文章,當時就有好幾個國產資料庫廠商的朋友和我溝通,說他們想在自己的資料庫產品中實現TAC,從而更好的改善使用者體驗。我當時就和他們說,TAC對使用者來說是個十分棒的功能,但是要實現TAC其實並不容易。當時我承諾有空了再寫篇詳細一點的文章來介紹一些TAC的實現細節,這個週末正好想起了了,於是開始構思,今早約好了10點去拜訪一家國產資料庫廠家,因此早上的時間比較充裕,就寫了上面的內容。

實際上對於實現TAC來說,還有最後一個難關,那就是Oracle在TAC上的專利壁壘。作為參與全球化競爭的中國資料庫企業,遵守國際規則,尊重智慧財產權是必須要做的事情。在TAC實現路徑上,Oracle已經擁有了大量的專利,因此我們的國產廠商直接照著Oracle一頓猛抄肯定是不行的。首先我們要去研究明白在這方面哪些是Oracle的專利,必須在實現中對這些進行規避。

來自 “ 白鱔的洞穴 ”, 原文作者:白鱔;原文連結:https://mp.weixin.qq.com/s/NBZ7ZUeCMqig9AECJmeDMA,如有侵權,請聯絡管理員刪除。

相關文章