1. 程式人生 > >秒級實現PostgreSQL版本升級方案

秒級實現PostgreSQL版本升級方案

PostgreSQL

 一、為什麼要升級PostgreSQL資料庫

看到這個題目,很多使用 PostgreSQL 的同學可能會這樣問,我當前使用的 PostgreSQL DB Instance 的 Major Version 雖然低一些,但是它一直很穩定,並且暫時也能滿足當前業務對效能的需求,那我為什麼還要去花費時間,消耗經歷去做資料庫升級呢?

1、對 PostgreSQL 熟悉的人或者經常看官方文件的同學會發現,基本上每年 PostgreSQL 都會有一個大版本釋出,而隨之釋出的還有一些新特性,比如說

9.3版本的新增物化檢視、支援事件觸發

9.4版本新增的 jsonb 欄位型別、可以通過 sql 命令 altersystem 來直接修改資料庫引數命令以及新增的 logicaldecoding 特性

9.5版本新增的支援 upsert 特性、新增的 BRIN 索引

9.6版本新增的對順序掃描的並行執行、為了提高資料庫的可靠性,允許多臺 standby資料庫同時處於 sync 狀態

10.0版本新增的支援表級的邏輯複製,允許對其進行釋出和訂閱、定義表分割槽及提高並行查詢的效率

這裡簡單的列一下每個版本的新特性,如果想了解個多的新特性或者每個特性的詳細資訊,請參考https://www.postgresql.org/docs/current/static/release.html

每一個新特性在其特定的使用場景下,都會對資料庫和應用程式的效能有質的飛躍,都會極大的節省開發及運維人員的時間成本、人力成本,所以我們為什麼不站在巨人的肩膀上前行呢?

2、PostgreSQL 社群成員每年只會同時維護5個主機板本的 PostgreSQL 資料庫,也就是說每個資料庫版本都是有生命週期的,從今年九月份(2017-09)開始,對於9.3以前的版本資料庫不再進行維護,當然你依然可以在官網上下載9.3以前的版本使用,但是如果在使用過程中出現了小 bug,那麼社群成員只會在維護的版本中修復,9.3以前的版本不會進行任何修改,所以為了避免低版本的 bug 引發應用程式故障崩潰,升級資料庫還是很有必要的。

資料庫

二、傳統升級方案剖析 

資料庫升級分為兩種,一種是小版本迭代升級,另一種是主機板本升級。小版本升級很簡單,只需要重啟一下資料庫即可,我們這裡主要說一下主機板本升級。做過資料庫升級方案的同學或者熟讀官方文件的同學可能知道,官方提供兩種大版本升級方案,分別是 pg_upgrade 和 pg_dumpall,這裡對這兩種方式的優缺點做一下整理:

資料庫

在我們生產環境中,尤其是核心的生產環境中,資料庫都是以叢集的方式存在的,因為資料是一個公司的核心命脈,所以如果要以傳統的方式來升級資料庫,絕大部分同學會選擇使用 pg_dumpall 的方式來實現,但是因為 pg_dumpall 的升級時間是與整個資料庫叢集的資料量成正比的,所以升級過程中需要長時間停止程式的寫服務,這對核心的業務程式(特別是有99.999保證的程式)來說是不可接受的,那麼既要升級資料庫主機板本,又要保證核心程式的99.999,就需要藉助其他方式,而 PGQ 就可以實現秒級升級資料庫。

三、PGO原理及特徵       

首先我們先來了解一下什麼是 pgq,其實 pgq 是 skytools 的一個模組,而 skytools 是 skype 公司的一個複製和容錯的工具包。skytools裡面有三個模組,分別是 pgq、londiste 和 walmgr。

pgq 是一個用 PL/pgSQL、Python 和 C 編寫的一個佇列系統,它分為3個部分,分別是 producers、ticker 和 consumers,其中 producers 負責呼叫資料庫的儲存程式將資料轉換成 event,ticker 則負責將 event 進行批次劃分,而 consumers 則負責將 event 轉換成 sql 語句;londiste 是一個用 Python 寫的複製工具,它利用 pgq 做為事件傳輸;walmgr 則是一個指令碼,主要用來對 wal 做歸檔,對資料庫做初始化備份以及恢復。

在 pgq 整個叢集中還有 node 的概念,分別是 root node、branch node、leaf node。Root 節點是整個叢集的資料唯一入口,同時負責向下遊推送 event,root 節點的下游可以為 branch 節點、leaf 節點以及通過呼叫 pgq 的 api 介面自定義程式將資料同步到其他平臺,比如 greenplum、elasticsearch、kafka、sqlserver 等等;branch 節點是轉換節點,負責接受上游推送下來的資料寫入到自己對應的 db 中,同時將 event 推送到下游(如果有下游的情況下),branch 可以掛載在 root 節點下,也可以掛載在其他 branch 節點;leaf 節點負責接受上游推送的 event 寫入到自己對應的資料庫中,它的掛載方式與 branch 節點一樣。

個人一直將 pgq 做為一個增量資料同步工具來使用,現在對 pgq 的特點進行一下總結:

1、資料從一個節點到下游節點可以在毫秒級完成,資料同步的快慢由自定義時間和自定義批次量的大小來根據業務需求靈活控制;

2、pgq 對 root 節點和 branch 節點的下游掛載節點個數沒有限制,如果一個 branch 節點出現故障,那麼可以將此節點的下游節點通過 change-provider 命令掛載到其他節點,在切換的過程中由 ticker 值來控制保證資料不會丟失,而故障節點會一直重試,直到故障恢復或在叢集中摘除次節點;

3、root 節點可以根據業務需要通過 takeover 命令來和 branch 節點進行切換,同樣可以保證資料不會丟失;

4、pgq 的同步物件是 tables 和 sequences,可以一次新增多張表進行同步,pgq 會對錶先做 copy 全量同步,然後在進行增量同步,同步過程中不會影響其他表;

5、pgq 需要同步表必須還有主鍵或者非空的唯一索引,不滿足此條件的表無法加入到同步叢集中;

6、pgq 是一個開源工具,可以呼叫其 api 介面將資料同步到其他平臺,如 greenplum、elasticsearch、kafka、sqlserver……

7、pgq 是單程序程式,所以不適合一次性操作上百萬上千萬的資料,建議分批次多次執行;

8、官方釋出的 release 版本目前只支援到 pg9.5,需要修改原始碼中 keywrods 的路徑才可以支援 pg9.6 以及 pg10 版本;

原 PGQ 同步叢集架構

架構

branch 節點切換後的同步叢集架構

四、PostgreSQL主機板本升級過程

1、先要確定 pgq 的版本與 PostgreSQL 的版本是否匹配,如果不匹配需要手工修改一下 pgq 的原始碼

      vi sql/pgq/triggers/stringutil.c

          – * src/include/parser/keywords.h

+ * src/include/common/keywords.h

2、安裝 pgq 同步叢集,需在低版本資料庫配置 root 節點環境,高版本資料庫配置 branch 節點環境

兩個節點都需要配置 pgqd.ini 檔案,同時 root 節點配合 pgq_root95.ini 檔案,branch 節點配置 pgq_branch96.ini 檔案,配置檔案的名字自己定義即可

         vi .pgqd.ini

[pgqd]
logfile = pgqd.log
pidfile = pgqd.pid
base_connstr = host=l-pgtest1.dev user=pgq password=pgq port=5432
database_list = postgres
ticker_period = 1

—————————

vi pgq_root.ini

[londiste3]
job_name = pgq_root
db = host=l-pgtest1.dev port=5432 dbname=postgres user=pgq password=pgq
pgq_queue_name = pgq
logfile = pgq_root.log
pidfile = pgq_root.pid
—————————-
vi pgq_branch.ini

[londiste3]
job_name = pgq_branch96
db = host=l-pgtest1.dev port=8432 dbname=postgres user=pgq password=pgq
pgq_queue_name = pgq
logfile = pgq_branch96.log
pidfile = pgq_branch96.pid

pgq_queue_name 在整個 pgq 叢集中要保持一致,而 job_name 在整個叢集中要唯一,同時這個叢集中所有的資料庫都要建立一個具有 superuser 許可權的使用者,比如此例中的 pgq

建立 root 節點:londiste3 pgq_root.ini create-root pgq_root ‘host=l-pgtest1.dev port=5432 dbname=postgres user=pgq password=pgq’

建立 branch 節點:londiste3 pgq_branch.ini create-branch pgq_branch96 ‘host=l-pgtest1.dev port=8432 dbname=postgres user=pgq password=pgq’ –provider=’host=l-pgtest1.dev port=5432 dbname=postgres user=pgq password=pgq’

3、新增同步物件(表)

先要對資料庫的結構進行同步,因為 pgq 只關心資料,所以各個節點的資料結構要保持一致,然後確定要新增的同步表具有主鍵或者唯一索引,否則新增同步表報錯

londiste3 pgq_root.ini add-table tablename1 tablename2   — 以此命令為模板來新增同步表

4、所有的同步表都新增完後,確定一下同步叢集是否正常,可以通過各個節點的日誌來看,也可以同步命令來看

londiste3 pgq_root.ini status

5、通過切換 root 節點的方式來實現資料庫升級,在 branch 節點上執行 takeover 命令來實現

londiste3 pgq_branch.ini takeover pgq_root   –其中 pgq_branch.ini 是 branch 節點的配置檔案,pgq_root 是 root 節點名

6、如果是在本伺服器上進行操作,還需要重啟一下高版本資料庫例項,因為要改一下 db instance 的埠號;如果是升級到其他伺服器則不用進行此操作

五、PostgreSQL主機板本升級總結

1、資料庫升級秒級實現,應用停服時間短;

2、升級回滾方式靈活,同樣是以切換 pgq root 節點的方式來實現;

3、可以保證升級前後 PostgreSQL 的相容性,尤其是一些 Extension 的相容性 ;

原文來自微信公眾號:Qunar技術沙龍