李躍森,騰訊云PostgreSQL首席架構(gòu)師,騰訊數(shù)據(jù)庫團(tuán)隊架構(gòu)師,負(fù)責(zé)微信支付商戶系統(tǒng)核心數(shù)據(jù)庫的架構(gòu)設(shè)計和研發(fā),PostgreSQL-x2社區(qū)核心成員,獲多項國家發(fā)明專利。從事PG內(nèi)核開發(fā)和架構(gòu)設(shè)計超過10年。
2015年之前,微信支付業(yè)務(wù)快速發(fā)展,需要一款數(shù)據(jù)庫能夠安全高效的支撐微信支付商戶系統(tǒng)核心業(yè)務(wù),這個重任落在了騰訊數(shù)據(jù)庫團(tuán)隊自研PostgreSQL上。
2016年7月,騰訊云對外發(fā)布云數(shù)據(jù)庫PostgreSQL,提供騰訊自研的內(nèi)核優(yōu)化版和社區(qū)版兩個版本,以及提供分布式集群架構(gòu)(分布式集群內(nèi)部代號PostgreSQL-XZ)兩種方案。目前云數(shù)據(jù)庫PostgreSQL在騰訊大數(shù)據(jù)平臺、廣點通、騰訊視頻等騰訊多個核心業(yè)務(wù)中穩(wěn)定運行。
騰訊自研PostgreSQL分布式集群 PostgreSQL-XZ
騰訊PostgreSQL-XZ是由PostgreSQL-XC社區(qū)版本地化而來,能支撐水平擴(kuò)展數(shù)據(jù)庫集群。雖然PostgreSQL-XC很強(qiáng)大,但在性能、擴(kuò)展性、安全、運維方面還是有明顯的瓶頸,而騰訊PostgreSQL經(jīng)過多年的積累,在這些方面都有較大提升和強(qiáng)化。由于是用于微信支付的核心數(shù)據(jù)庫,騰訊PostgreSQL被定位為安全、高效,穩(wěn)定,可靠的數(shù)據(jù)庫集群。下面將以騰訊PostgreSQL-XZ為代表介紹騰訊自研PostgreSQL所做的優(yōu)化和改進(jìn)。
一.事務(wù)管理系統(tǒng)的優(yōu)化
PostgreSQL-XC在事務(wù)管理系統(tǒng)方案本身有一個明顯的缺點,那就是事務(wù)管理機(jī)制會成為系統(tǒng)的瓶頸,GTM(Global Transaction Manager全局事務(wù)管理器)會限制系統(tǒng)的擴(kuò)展規(guī)模。如圖1所示,是每個請求過來CN(Coordinator 協(xié)調(diào)節(jié)點)都會向GTM申請必需的gxid(全局事務(wù)ID)和gsnapshot(全局快照)信息,并把這些信息隨著SQL語句本身一起發(fā)往DN(Datanode數(shù)據(jù)庫節(jié)點)進(jìn)行執(zhí)行。另外,PostgreSQL-XC的管理機(jī)制,只有主DN才會獲取的gxid,而備DN沒有自己的gxid,因此無法提供只讀服務(wù),對系統(tǒng)也是不小的浪費。

圖1
而騰訊PostgreSQL-XZ改進(jìn)了事務(wù)管理機(jī)制,改進(jìn)后,CN不再從GTM獲取gxid和gsnapshot,每個節(jié)點使用自己的本地xid(事務(wù)ID)和gsnapshot(快照),如此GTM便不會成為系統(tǒng)的瓶頸;并且,DN備機(jī)就還可以提供只讀服務(wù),充分利用系統(tǒng)閑置資源。如圖2,優(yōu)化后的事務(wù)管理系統(tǒng)架構(gòu)如下:

圖2
二.備機(jī)只讀實現(xiàn)與優(yōu)化
當(dāng)然,事務(wù)管理系統(tǒng)的優(yōu)化為進(jìn)行備DN只讀提供了基礎(chǔ),然而原始集群并沒有負(fù)載、調(diào)度等能力。在這方面,我們也做了大量的創(chuàng)新,總結(jié)起來包括:
正常CN和只讀CN進(jìn)行分離。
正常CN存儲主用DN的元數(shù)據(jù)信息
只讀CN存儲備用DN的元數(shù)據(jù)信息
DN之間使用hot standby(熱備份保護(hù))模式進(jìn)行日志同步
通過這些方式,集群可以提供帶有智能負(fù)載能力的備DN只讀功能,充分利用系統(tǒng)資源。

圖3
三.業(yè)務(wù)最小中斷的擴(kuò)容方案
業(yè)務(wù)的快速增長不可避免的需要對資源進(jìn)行擴(kuò)容,社區(qū)版本的實現(xiàn)使得擴(kuò)容成本高昂,需要對業(yè)務(wù)進(jìn)行長時間的中斷。因為,在社區(qū)版本PostgreSQL-XC中,通過 DN=Hash(row) % nofdn 的方式?jīng)Q定一條記錄的存儲節(jié)點:
也就是說,先對分布列計算hash值,然后使用這個值對集群中的節(jié)點個數(shù)取模來決定記錄去哪個節(jié)點(如圖4)。
這種方案簡單,但實際應(yīng)用中需要長時間停機(jī)擴(kuò)容。這是因為,擴(kuò)容后節(jié)點數(shù)會變多,數(shù)據(jù)無法按照原有的分布邏輯進(jìn)行讀寫,需要重新分布節(jié)點數(shù)據(jù)。而再均衡數(shù)據(jù)需要停機(jī)并手工遷移再均衡到各個節(jié)點。對于規(guī)模較大的交易系統(tǒng)來說,由于原有節(jié)點存儲的是海量數(shù)據(jù),再均衡過程可能會持續(xù)好幾天。相信這是業(yè)務(wù)完全無法忍受的。

圖4
因此我們引入了一種新的分表方法 —sharded table。Shardedtable 的數(shù)據(jù)分布采用如下(圖5)的方式:
引入一個抽象的中間層--shard map。Shard map中每一項存儲shardid和DN的映射關(guān)系。