天天看點

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

邏輯訂閱是postgresql 10.0的新特性。

具體的原理,使用方法可以參考如下文章。

<a href="https://github.com/digoal/blog/blob/master/201702/20170227_01.md">《postgresql 10.0 preview 邏輯訂閱 - 原理與最佳實踐》</a>

<a href="https://github.com/digoal/blog/blob/master/201704/20170405_02.md">《postgresql 10.0 preview 邏輯訂閱 - pg_hba.conf變化,不再使用replication條目》</a>

<a href="https://github.com/digoal/blog/blob/master/201703/20170330_01.md">《postgresql 10.0 preview 邏輯訂閱 - 備庫支援邏輯訂閱,訂閱支援主備漂移了》</a>

<a href="https://github.com/digoal/blog/blob/master/201703/20170328_01.md">《postgresql 10.0 preview 邏輯訂閱 - 支援并行copy初始化資料》</a>

postgresql 早在2010年就支援了實體流式複制,可以用來支援容災、讀寫分離、ha等業務場景。為什麼還需要邏輯訂閱的功能呢?

1. 差别1,實體複制目前隻能做到整個叢集的複制。邏輯訂閱可以做到表級。

實體流式複制是基于redo的塊級别複制,複制出來的資料庫與上遊資料庫一模一樣,每個塊都是一樣的,就好像克隆的一樣。

實體流式複制,目前隻能做到整個叢集的複制,雖然技術上來講也可以做到按表空間、按資料庫級别的複制,目前pg社群還沒有這麼做。

ps:外圍的公司有這樣的插件,walbouncer,支援實體的partial replication。

http://www.cybertec.at/en/products/walbouncer-enterprise-grade-partial-replication/

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

2. 差别2,實體複制的備庫隻讀,不能寫入。邏輯訂閱讀寫都可以。

3. 差别3,實體複制不需要等待事務送出,即可将redo發往備庫,備庫也可以直接apply它。邏輯訂閱,目前需要等待事務送出後,釋出端才會使用wal_sender程序将decode後的資料發送給訂閱端,訂閱端流式接收與流式apply。

将來邏輯訂閱也可能不需要等事務結束就apply,因為在clog中是有2個bit記錄事務狀态的。

4. 差别4,實體複制,需要複制所有的redo(包括復原的)。邏輯訂閱,不需要複制所有的redo,僅僅需要複制”訂閱表産生的redo解析後的資料”(并且復原的事務不會被複制)。

5. 差别5,如果要支援邏輯訂閱,需要配置wal_level=logical,如果僅僅需要實體複制,則配置wal_level=replica即可。

邏輯訂閱需要産生額外的redo資訊(通過alter或create table指定pk, 或 full row)。而實體複制,不需要在redo中記錄這些資訊。

邏輯訂閱對主庫的性能影響比實體複制更較大的。

6. 差别6,對于大事務,實體複制的延遲比邏輯訂閱更低。因為差别3。

7. 差别7,邏輯訂閱需要用到釋出端的catalog,将redo翻譯為可供訂閱者使用的row格式,如果在訂閱端與釋出端沒有同步前,釋出端的table定義發生了變化或者被删除了,翻譯redo的工作将無法進行下去。postgresql使用多版本來解決這樣的問題,允許catalog的變更,但是版本被保留到訂閱端不需要它為止(pg内部通過lsn來實作)。如果你發現釋出端的catalog膨脹了,可以從這方面找一下原因(是不是訂閱太慢或者訂閱者停止訂閱了,同時期間釋出端産生了大量的ddl操作)。

實體複制不存在這樣的問題。

8. 差别8,實體複制的備庫,如果要被用來隻讀的話,為了避免備庫long query與vacuum redo發生沖突,有兩種解決方案,都有一定的損傷。1,主庫延遲vacuum,一定程度上導緻主庫膨脹。2,備庫apply禮讓query,一定程度上導緻備庫apply延遲。

邏輯訂閱不存在以上情形的沖突。

邏輯訂閱,适合于釋出端與訂閱端都有讀寫的情況。

邏輯訂閱,更适合于小事務,或者低密度寫(輕度寫)的同步。如果有大事務、高密度寫,邏輯訂閱的延遲相比實體複制更高。

邏輯訂閱,适合于雙向,多向同步。

實體複制,适合于單向同步。

實體複制,适合于任意事務,任意密度寫(重度寫)的同步。

實體複制,适合于ha、容災、讀寫分離。

實體複制,适合于備庫沒有寫,隻有讀的場景。

1. 多個業務之間,有少量的資料需要同步時,邏輯訂閱可以解決這樣的問題。

例如a業務和b業務,分别使用兩個資料庫,但是他們有少量的資料是共用的。而且都要對這部分共享資料進行讀寫。

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

2. 資料彙總,例如多個業務庫的feed資料,要彙總到一個分析庫。以往可能要建構龐大的etl和排程系統,并且很難做到實時的同步。現在有了邏輯訂閱,可以友善的應對這樣的場景。

(postgresql 的多個特性表名,它正在朝着htap的方向發展,既能高效的處理oltp線上業務,也能處理分析業務。(llvm、向量計算、列存儲、多核并行、算子複用等一系列的特性支援olap))

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

3. 資料拆分,與資料彙總剛好相反,比如在垂直拆分時,使用邏輯訂閱,可以将一個集中式的資料庫拆分成多個資料庫。由于邏輯訂閱是增量的,可以節約拆分過程的停機時間。

另外還有些業務場景,在端上可能不會部署那麼多的小資料庫,統統往一個庫裡寫。下遊接一些小的資料庫,是要邏輯訂閱,也能很好的滿足此類需求。

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

4. 多活架構中,最痛苦的實際上是資料庫,為什麼呢?

比如一個遊戲業務,可能在全國都有idc,而認證或者賬務系統可能還是集中式的,如果要拆分成多個庫,就會涉及到資料一緻性和完整性的問題。

比如按使用者的首次注冊地,将資料庫分為多個區域。根據使用者的登陸來源ip,路由到相應的idc(通路這個idc中的資料庫),這個使用者如果是固定使用者還好,因為注冊地和使用地基本是不變的。對于手機遊戲就扯淡了,因為登陸地不斷的變化,比如出差,原來在杭州登陸的,跑北京登陸了。而北京機房并沒有該使用者的資訊。業務層面就需要解決這樣的問題。

使用邏輯訂閱,可以很好的解決這個場景的問題,每個idc中的資料都是完整的,當使用者在杭州時,讀寫杭州的資料庫,通過訂閱資料複制到北京的機房。當使用者漫遊到北京時,讀寫北京的資料庫,通過訂閱複制到杭州的機房。

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

5. 有些企業,在雲上有資料庫,線上下也有資料庫,甚至在多個雲廠商都有資料庫。應了一句話,不要将雞蛋放在同一個籃子裡。

那麼這些資料庫的資料如何在多個域之間同步呢?使用實體複制是很難做到的,存在一些不可避免的問題:1,雲廠商的資料庫核心可能修改過,實體複制不一定相容。2,不同廠商的版本可能不相容。3,資料庫編譯時的資料塊大小可能不一樣導緻不相容。4,背後使用的插件可能不一樣,導緻不相容。5,雲廠商不一定會開放實體複制的接口。

邏輯訂閱規避了以上問題:1,邏輯訂閱可以跨版本。2,邏輯訂閱不管資料塊的大小是否一樣,都沒有問題。

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

6. 從雲上将資料遷移到線下,或者從線下将資料遷移到雲上。

使用邏輯訂閱,可以實作增量的遷移。減少遷移的業務停機時間。

7. 跨版本、跨平台更新。

跨版本更新,使用邏輯訂閱,增量遷移,可以減少更新版本的業務停機時間。

8. 資料分享給其他的産品,例如緩存、搜尋引擎、流計算平台。

使用邏輯訂閱,可以實時将資料分享給其他的業務平台,bottledwater-pg就是一個很好的例子。

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

9. 資料庫的熱插拔。類似oracle 12c的cdb架構。postgresql cluster 對應oracle 12c的cdb,cluster中的database對應oracle 12c的pdb。

當需要将一個cluster的database拔出時,通過訂閱方式複制到其他的cluster。

PgSQL · 應用案例 · 邏輯訂閱給業務架構帶來了什麼?

例子

邏輯訂閱隻需簡單兩步即可完成。

1. 建表、釋出

2. 建表、訂閱

詳情請參考

邏輯訂閱,本質上是事務層級的複制,需要在訂閱端執行sql。

如果訂閱端執行sql失敗(或者說引發了任何錯誤,包括限制等),都會導緻該訂閱暫停。

注意,update, delete沒有比對的記錄時,不會報錯,也不會導緻訂閱暫停。

使用者可以在訂閱端資料庫日志中檢視錯誤原因。

1. 通過修改訂閱端的資料,解決沖突。例如insert違反了唯一限制時,可以删除訂閱端造成唯一限制沖突的記錄先delete掉。然後使用alter subscription name enable讓訂閱繼續。

2. 在訂閱端調用pg_replication_origin_advance(node_name text, pos pg_lsn)函數,node_name就是subscription name,pos指重新開始的lsn,進而跳過有沖突的事務。

目前的lsn通過pg_replication_origin_status.remote_lsn檢視。

https://www.postgresql.org/docs/devel/static/view-pg-replication-origin-status.html