PostgreSQL邏輯復(fù)制解密原理解析
在數(shù)字化時(shí)代的今天,我們都認(rèn)同數(shù)據(jù)會(huì)創(chuàng)造價(jià)值。為了最大化數(shù)據(jù)的價(jià)值,我們不停的建立著數(shù)據(jù)遷移的管道,從同構(gòu)到異構(gòu),從關(guān)系型到非關(guān)系型,從云下到云上,從數(shù)倉到數(shù)據(jù)湖,試圖在各種場景挖掘數(shù)據(jù)的價(jià)值。而在這縱橫交錯(cuò)的數(shù)據(jù)網(wǎng)絡(luò)中,邏輯復(fù)制扮演著及其重要的角色。讓我們將視角從復(fù)雜的網(wǎng)絡(luò)拉回其中的一個(gè)端點(diǎn),從PostgreSQL出發(fā),對其邏輯復(fù)制的原理進(jìn)行解密。
在數(shù)字化時(shí)代的今天,我們都認(rèn)同數(shù)據(jù)會(huì)創(chuàng)造價(jià)值。為了最大化數(shù)據(jù)的價(jià)值,我們不停的建立著數(shù)據(jù)遷移的管道,從同構(gòu)到異構(gòu),從關(guān)系型到非關(guān)系型,從云下到云上,從數(shù)倉到數(shù)據(jù)湖,試圖在各種場景挖掘數(shù)據(jù)的價(jià)值。而在這縱橫交錯(cuò)的數(shù)據(jù)網(wǎng)絡(luò)中,邏輯復(fù)制扮演著及其重要的角色。
讓我們將視角從復(fù)雜的網(wǎng)絡(luò)拉回其中的一個(gè)端點(diǎn),從PostgreSQL出發(fā),對其邏輯復(fù)制的原理進(jìn)行解密。
1 概念與原理
邏輯復(fù)制,是基于復(fù)制標(biāo)識復(fù)制數(shù)據(jù)及其變化的一種方法。區(qū)別于物理復(fù)制對頁面操作的描述,邏輯復(fù)制是對事務(wù)及數(shù)據(jù)元組的一種描述。
圖-WAL數(shù)據(jù)流示例
如圖所示,物理復(fù)制的數(shù)據(jù)流是對tablespace/database/filenode文件的塊進(jìn)行操作,而邏輯復(fù)制的內(nèi)容是對元組進(jìn)行描述。
接下來我們來看邏輯復(fù)制中的幾個(gè)概念:
復(fù)制槽
復(fù)制槽是記錄復(fù)制狀態(tài)的一組信息。由于WAL(預(yù)寫式日志)文件在數(shù)據(jù)真正落盤后會(huì)刪除,復(fù)制槽會(huì)防止過早清理邏輯復(fù)制解析所需的WAL日志。在邏輯復(fù)制中,每個(gè)插槽從單個(gè)數(shù)據(jù)庫流式傳輸一系列更改,創(chuàng)建復(fù)制槽需要指定其使用的輸出插件,同時(shí)創(chuàng)建復(fù)制槽時(shí)會(huì)提供一個(gè)快照。
輸出插件
輸出插件負(fù)責(zé)將WAL日志解碼為可讀的格式,常用的插件用test_decoding(多用來測試),pgoutput(默認(rèn)使用),wal2json(輸出為json)。PostgreSQL定義了一系列回調(diào)函數(shù),我們除了使用上述插件,可以通過回調(diào)函數(shù)編寫自己的輸出插件。
圖-復(fù)制槽數(shù)據(jù)流
復(fù)制協(xié)議與消息
通過復(fù)制協(xié)議,我們可以從源端獲取WAL數(shù)據(jù)流。例如通過PSQL工具建議復(fù)制連接
psql "dbname=postgres replication=database"
開啟流式傳輸WAL
START_REPLICATION[ SLOT slot_name] [ PHYSICAL] XXX/XXX[ TIMELINE tli]
無論是物理復(fù)制,還是邏輯復(fù)制,使用PostgreSQL的發(fā)布訂閱或者pg_basebackup搭建流復(fù)制,都是通過復(fù)制協(xié)議與定義的消息進(jìn)行交互(物理復(fù)制和邏輯復(fù)制數(shù)據(jù)流內(nèi)容不同)
圖- WAL數(shù)據(jù)流消息類型
圖-邏輯復(fù)制中的XLogData消息
工作流程
當(dāng)我們了解了概念之后,來看一下整個(gè)解析的工作流程。由于WAL文件里一個(gè)事務(wù)的內(nèi)容并不一定是連續(xù)的,所以需要通過Reorder后放在buffer中,根據(jù)事務(wù)ID組織成一條消息,COMMIT后發(fā)送給輸出插件,輸出插件解析后將消息流發(fā)送給目標(biāo)端。
圖-邏輯解析工作流程
2 問題與演進(jìn)
當(dāng)我們掌握了邏輯復(fù)制的原理,計(jì)劃使用其構(gòu)建我們的數(shù)據(jù)遷移應(yīng)用之前,我們還有一些問題并沒有解決。讓我們來一起看看是什么亟待解決的問題,以及我們?nèi)绾芜M(jìn)行處理。
問題一:Failover slot
為了高可用性,數(shù)據(jù)庫至少會(huì)存在一主一備的架構(gòu),當(dāng)主庫故障進(jìn)行高可用切換時(shí),備庫卻沒有相應(yīng)的復(fù)制槽信息,也就是缺少failover slot。這是由于保存slot信息的物理文件,未同步至備庫。那么我們?nèi)绾问謩?dòng)創(chuàng)建一個(gè)faliover slot呢?
1. 主庫創(chuàng)建復(fù)制槽,檢查備庫wal文件是否連續(xù)
2. 復(fù)制包含slot信息的物理文件至備庫,在pg_repslot目錄下
3. 備庫重啟,重啟后才可以看到復(fù)制槽信息,原因是讀取slot物理文件的函數(shù)StartupReplicationSlots只會(huì)在postmaster進(jìn)程啟動(dòng)時(shí)調(diào)用。
4. 定期查詢主庫slot狀態(tài),使用pg_replication_slot_advance函數(shù)推進(jìn)備庫復(fù)制槽
自此,我們在備庫上也有了相應(yīng)的信息,手動(dòng)實(shí)現(xiàn)了failover slot。PostgreSQL生態(tài)中著名的高可用軟件Patroni也是以這種方式進(jìn)行了實(shí)現(xiàn),區(qū)別只是在Patroni查詢主庫slot狀態(tài)時(shí)將信息寫入了DCS中,備庫拿到DCS中的位點(diǎn)信息進(jìn)行推進(jìn)。
問題二:DDL同步
原生的邏輯復(fù)制不支持解析DDL語句,我們可以使用事件觸發(fā)器來進(jìn)行處理。
1. 使用事件觸發(fā)器感知表結(jié)構(gòu)變更,記錄到DDL_RECORD表中,并將該表通過邏輯復(fù)制進(jìn)行發(fā)布。
2. 接收端獲取到該表的數(shù)據(jù)變更,即可處理為相應(yīng)DDL語句進(jìn)行執(zhí)行。
圖-事件觸發(fā)器實(shí)現(xiàn)DDL同步
問題三: 雙向同步
當(dāng)數(shù)據(jù)遷移涉及雙向同步的管道時(shí),例如想實(shí)現(xiàn)雙主雙寫,對數(shù)據(jù)庫同一對象進(jìn)行操作,就會(huì)出現(xiàn)WAL循環(huán)。
圖-相同表雙向同步導(dǎo)致數(shù)據(jù)循環(huán)
部分DTS應(yīng)用為了解決這個(gè)問題會(huì)創(chuàng)建輔助表,在事務(wù)中先對輔助表進(jìn)行操作,通過解析到對輔助表的操作而得知該記錄是又DTS應(yīng)用插入,從而過濾該事務(wù),不再循環(huán)解析。PostgreSQL對事務(wù)提供了Origin記錄,無須輔助表,通過pg_replication_origin_session_setup函數(shù)或者發(fā)布訂閱中的replorigin_create即可指定Origin ID。
指定Origin ID后,我們除了可以解析后通過DTS應(yīng)用進(jìn)行過濾,還也可以通過解析插件中的FilterByOriginCB回調(diào)函數(shù)在解析過程中過濾,這種方式減少了數(shù)據(jù)傳輸,效率更高。
圖-test_decoding中OriginFilter函數(shù)DEMO
其他問題:
除了以上三個(gè)問題,還有一些使用的問題或限制。這里列出了一些,不再展開,僅簡要說明。
Toast處理:對于toast值(消息格式中可以判斷),我們在處理時(shí)一般使用占位符進(jìn)行處理,接收端接收到占位符就不對這一列進(jìn)行處理,雖然有些麻煩,但這也是在和傳輸toast值的方案中權(quán)衡的結(jié)果。
心跳表:由于復(fù)制槽記錄的XMIN是全局的,當(dāng)我們發(fā)布的表一直沒有更新時(shí),XMIN沒有推進(jìn)導(dǎo)致WAL積壓,我們可以創(chuàng)建一張心跳表,周期性寫入數(shù)據(jù)并發(fā)布,使XMIN進(jìn)行推進(jìn)。
大事務(wù)延遲: 根據(jù)前文提到的工作流程我們可以知道默認(rèn)事務(wù)在COMMIT后才會(huì)進(jìn)行解析,這對于大事務(wù)來說勢必會(huì)導(dǎo)致延遲,PG14版本提供了streamin模式進(jìn)行解析,即事務(wù)進(jìn)行中進(jìn)行解析并發(fā)送至接收端。
3 應(yīng)用與實(shí)踐
前兩節(jié)我們從原理及問題的角度對PostgreSQL進(jìn)行了解密,接下來我們看如何通過我們掌握的邏輯復(fù)制原理,進(jìn)行數(shù)據(jù)遷移的應(yīng)用與實(shí)踐。
全量與增量同步
在真實(shí)的數(shù)據(jù)遷移場景中,大部分都是全量和增量都要同步的場景,并且我們打通了數(shù)據(jù)傳輸?shù)耐ǖ篮螅矊@條通道的安全,效率,以及功能的擴(kuò)展,例如清洗,脫敏等ETL能力提出了新的要求。我們先來看一下如果實(shí)現(xiàn)全量與增量的同步。
圖-數(shù)據(jù)流向示意圖
主要流程包括:
1. 創(chuàng)建復(fù)制槽并導(dǎo)出快照
2. 根據(jù)快照進(jìn)行全量數(shù)據(jù)遷移
3. 根據(jù)復(fù)制槽進(jìn)行增量數(shù)據(jù)的遷移
我們使用了PG數(shù)據(jù)庫或者消息隊(duì)列MQ作為數(shù)據(jù)代理,全量與增量解析可以同時(shí)進(jìn)行,當(dāng)全量數(shù)據(jù)處理完畢后,狀態(tài)機(jī)通知增量處理程序進(jìn)行增量發(fā)布。而對于代理中的數(shù)據(jù),可以在解析后進(jìn)行預(yù)處理。
自建實(shí)例遷移上云實(shí)踐
最后和大家分享一個(gè)自建實(shí)例遷移上云的實(shí)踐,該案例是將自建的PG10版本實(shí)例遷移至京東云上的RDS PG 11版本,通過對增量數(shù)據(jù)的回流以及數(shù)據(jù)校驗(yàn)保證了數(shù)據(jù)安全與業(yè)務(wù)平穩(wěn)切換。
圖-數(shù)據(jù)遷移上云
DTS應(yīng)用主要分為如下幾個(gè)階段:
1. 數(shù)據(jù)檢查階段: 檢查主鍵,權(quán)限,配置
2. 數(shù)據(jù)遷移階段: 結(jié)構(gòu),存量,增量數(shù)據(jù)遷移,監(jiān)控遷移狀態(tài)
3. 應(yīng)用遷移階段: 切換域名,引入流量
4. 回滾階段: 增量數(shù)據(jù)回流,若出現(xiàn)問題可快速回滾。
到此這篇關(guān)于PostgreSQL邏輯復(fù)制解密原理解析的文章就介紹到這了,更多相關(guān)PostgreSQL邏輯復(fù)制解密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- PostgreSQL數(shù)據(jù)庫遷移部署實(shí)戰(zhàn)教程
- 關(guān)于Docker部署postgresql數(shù)據(jù)庫的問題
- postgresql 12版本搭建及主備部署操作
- postgresql數(shù)據(jù)庫安裝部署搭建主從節(jié)點(diǎn)的詳細(xì)過程(業(yè)務(wù)庫)
- PostgreSQL中Slony-I同步復(fù)制部署教程
- Windows?環(huán)境搭建?PostgreSQL?邏輯復(fù)制高可用架構(gòu)數(shù)據(jù)庫服務(wù)
- PostgreSQL 邏輯復(fù)制 配置操作
- postgresql流復(fù)制原理以及流復(fù)制和邏輯復(fù)制的區(qū)別說明
- PostgreSQL部署邏輯復(fù)制過程詳解
相關(guān)文章
postgresql數(shù)據(jù)庫 timescaledb 時(shí)序庫 把大數(shù)據(jù)量表轉(zhuǎn)換為超表的問題
這篇文章主要介紹了postgresql數(shù)據(jù)庫 timescaledb 時(shí)序庫 把大數(shù)據(jù)量表轉(zhuǎn)換為超表,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Postgresql 賦予用戶權(quán)限和撤銷權(quán)限的實(shí)例
這篇文章主要介紹了Postgresql 賦予用戶權(quán)限和撤銷權(quán)限的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01postgresql兼容MySQL on update current_timestamp
這篇文章主要介紹了postgresql兼容MySQL on update current_timestamp問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03常用?PostgreSQL?數(shù)據(jù)恢復(fù)方案及使用示例
這篇文章主要介紹了常用?PostgreSQL?數(shù)據(jù)恢復(fù)方案概覽,數(shù)據(jù)丟失通常是由?DDL?與?DML?兩種操作引起,由于在操作系統(tǒng)中表文件已經(jīng)不存在,所以只能采用恢復(fù)磁盤的方法進(jìn)行數(shù)據(jù)恢復(fù),需要的朋友可以參考下2022-01-01PostgreSQL連接數(shù)過多報(bào)錯(cuò):too many clients already的解決
在使用 Navicat 連接 PostgreSQL 數(shù)據(jù)庫時(shí),突然遭遇到了一個(gè)報(bào)錯(cuò):“FATAL: sorry, too many clients already”,這一錯(cuò)誤提示表明數(shù)據(jù)庫連接數(shù)已經(jīng)達(dá)到上限,無法再創(chuàng)建新連接,所以本文給大家介紹了相關(guān)的解決辦法,需要的朋友可以參考下2024-03-03在windows下手動(dòng)初始化PostgreSQL數(shù)據(jù)庫教程
在windows下手動(dòng)初始化PG,是一件比較麻煩的事,下面我具體寫一下過程,大家做一下參考。2014-09-09PostgreSQL數(shù)據(jù)庫中DISTINCT關(guān)鍵字的四種用法詳解
PostgreSQL 不但高度兼容 SQL 標(biāo)準(zhǔn),同時(shí)還對很多語法進(jìn)行了擴(kuò)展,可以用于實(shí)現(xiàn)一些特殊的功能,今天我們就來介紹一下 PostgreSQL 數(shù)據(jù)庫中 DISTINCT 關(guān)鍵字的 4 種不同用法,需要的朋友可以參考下2024-04-04

PostgreSQL TIMESTAMP類型 時(shí)間戳操作