在數位化時代的今天,我們都認同資料會創造價值。為了最大化資料的價值,我們不停的建立著資料遷移的管道,從同構到異構,從關係型到非關係型,從雲下到雲上,從數倉到資料湖,試圖在各種場景挖掘資料的價值。而在這縱橫交錯的資料網路中,邏輯複製扮演著及其重要的角色。
讓我們將視角從複雜的網路拉回其中的一個端點,從PostgreSQL出發,對其邏輯複製的原理進行解密。
邏輯複製,是基於複製標識複製資料及其變化的一種方法。區別於物理複製對頁面操作的描述,邏輯複製是對事務及資料元組的一種描述。
如圖所示,物理複製的資料流是對tablespace/database/filenode檔案的塊進行操作,而邏輯複製的內容是對元組進行描述。
接下來我們來看邏輯複製中的幾個概念:
複製槽
複製槽是記錄複製狀態的一組資訊。由於WAL(預寫式紀錄檔)檔案在資料真正落盤後會刪除,複製槽會防止過早清理邏輯複製解析所需的WAL紀錄檔。在邏輯複製中,每個插槽從單個資料庫流式傳輸一系列更改,建立複製槽需要指定其使用的輸出外掛,同時建立複製槽時會提供一個快照。
輸出外掛
輸出外掛負責將WAL紀錄檔解碼為可讀的格式,常用的外掛用test_decoding(多用來測試),pgoutput(預設使用),wal2json(輸出為json)。PostgreSQL定義了一系列回撥函數,我們除了使用上述外掛,可以通過回撥函數編寫自己的輸出外掛。
複製協定與訊息
通過複製協定,我們可以從源端獲取WAL資料流。例如通過PSQL工具建議複製連線
psql "dbname=postgres replication=database"
開啟流式傳輸WAL
START_REPLICATION[ SLOT slot_name] [ PHYSICAL] XXX/XXX[ TIMELINE tli]
無論是物理複製,還是邏輯複製,使用PostgreSQL的釋出訂閱或者pg_basebackup搭建流複製,都是通過複製協定與定義的訊息進行互動(物理複製和邏輯複製資料流內容不同)
工作流程
當我們瞭解了概念之後,來看一下整個解析的工作流程。由於WAL檔案裡一個事務的內容並不一定是連續的,所以需要通過Reorder後放在buffer中,根據事務ID組織成一條訊息,COMMIT後傳送給輸出外掛,輸出外掛解析後將訊息流傳送給目標端。
當我們掌握了邏輯複製的原理,計劃使用其構建我們的資料遷移應用之前,我們還有一些問題並沒有解決。讓我們來一起看看是什麼亟待解決的問題,以及我們如何進行處理。
問題一:Failover slot
為了高可用性,資料庫至少會存在一主一備的架構,當主庫故障進行高可用切換時,備庫卻沒有相應的複製槽資訊,也就是缺少failover slot。這是由於儲存slot資訊的物理檔案,未同步至備庫。那麼我們如何手動建立一個faliover slot呢?
1. 主庫建立複製槽,檢查備庫wal檔案是否連續
2. 複製包含slot資訊的物理檔案至備庫,在pg_repslot目錄下
3. 備庫重啟,重啟後才可以看到複製槽資訊,原因是讀取slot物理檔案的函數StartupReplicationSlots只會在postmaster程序啟動時呼叫。
4. 定期查詢主庫slot狀態,使用pg_replication_slot_advance函數推進備庫複製槽
自此,我們在備庫上也有了相應的資訊,手動實現了failover slot。PostgreSQL生態中著名的高可用軟體Patroni也是以這種方式進行了實現,區別只是在Patroni查詢主庫slot狀態時將資訊寫入了DCS中,備庫拿到DCS中的位點資訊進行推進。
問題二:DDL同步
原生的邏輯複製不支援解析DDL語句,我們可以使用事件觸發器來進行處理。
1. 使用事件觸發器感知表結構變更,記錄到DDL_RECORD表中,並將該表通過邏輯複製進行釋出。
2. 接收端獲取到該表的資料變更,即可處理為相應DDL語句進行執行。
問題三: 雙向同步
當資料遷移涉及雙向同步的管道時,例如想實現雙主雙寫,對資料庫同一物件進行操作,就會出現WAL迴圈。
部分DTS應用為了解決這個問題會建立輔助表,在事務中先對輔助表進行操作,通過解析到對輔助表的操作而得知該記錄是又DTS應用插入,從而過濾該事務,不再回圈解析。PostgreSQL對事務提供了Origin記錄,無須輔助表,通過pg_replication_origin_session_setup函數或者釋出訂閱中的replorigin_create即可指定Origin ID。
指定Origin ID後,我們除了可以解析後通過DTS應用進行過濾,還也可以通過解析外掛中的FilterByOriginCB回撥函數在解析過程中過濾,這種方式減少了資料傳輸,效率更高。
其他問題:
除了以上三個問題,還有一些使用的問題或限制。這裡列出了一些,不再展開,僅簡要說明。
Toast處理:對於toast值(訊息格式中可以判斷),我們在處理時一般使用預留位置進行處理,接收端接收到預留位置就不對這一列進行處理,雖然有些麻煩,但這也是在和傳輸toast值的方案中權衡的結果。
心跳錶:由於複製槽記錄的XMIN是全域性的,當我們釋出的表一直沒有更新時,XMIN沒有推進導致WAL積壓,我們可以建立一張心跳錶,週期性寫入資料並行布,使XMIN進行推進。
大事務延遲: 根據前文提到的工作流程我們可以知道預設事務在COMMIT後才會進行解析,這對於大事務來說勢必會導致延遲,PG14版本提供了streamin模式進行解析,即事務進行中進行解析並行送至接收端。
前兩節我們從原理及問題的角度對PostgreSQL進行了解密,接下來我們看如何通過我們掌握的邏輯複製原理,進行資料遷移的應用與實踐。
全量與增量同步
在真實的資料遷移場景中,大部分都是全量和增量都要同步的場景,並且我們打通了資料傳輸的通道後,也對這條通道的安全,效率,以及功能的擴充套件,例如清洗,脫敏等ETL能力提出了新的要求。我們先來看一下如果實現全量與增量的同步。
主要流程包括:
1. 建立複製槽並匯出快照
2. 根據快照進行全量資料遷移
3. 根據複製槽進行增量資料的遷移
我們使用了PG資料庫或者訊息佇列MQ作為資料代理,全量與增量解析可以同時進行,當全量資料處理完畢後,狀態機通知增量處理程式進行增量釋出。而對於代理中的資料,可以在解析後進行預處理。
自建範例遷移上雲實踐
最後和大家分享一個自建範例遷移上雲的實踐,該案例是將自建的PG10版本範例遷移至京東雲上的RDS PG 11版本,通過對增量資料的迴流以及資料校驗保證了資料安全與業務平穩切換。
DTS應用主要分為如下幾個階段:
1. 資料檢查階段: 檢查主鍵,許可權,設定
2. 資料遷移階段: 結構,存量,增量資料遷移,監控遷移狀態
3. 應用遷移階段: 切換域名,引入流量
4. 回滾階段: 增量資料迴流,若出現問題可快速回滾。
作者:蔣帥