“PostgreSQL+金融”的架構演進

ShaDuby 8年前發布 | 12K 次閱讀 PostgreSQL

PostgreSQL 是一個自由的對象-關系數據庫服務器(數據庫管理系統),功能很強大。包括了可以說是目前世界上最豐富的數據類型的支持,比如 IP 類型和幾何類型等等。

發現很多讀者都問過這樣一個問題:如果打算為項目選擇一款免費、開源的數據庫,那么你可能會在MySQL與PostgreSQL之間猶豫不定。針對這個問題,我們采訪到了即將在 Postgres中國用戶2016大會 上作分享的平安科技數據庫技術部總監 汪洋,請他從實踐者的角度給出一些經驗分享和建議。

InfoQ:對于金融領域的應用來說,使用 PostgreSQL 與使用 MySQL 相比,優勢有哪些?

汪洋:這個問題的本質回歸到為什么平安科技會選擇 PostgreSQL 來做為 Oracle 的替代品。

我們并不是沒有使用過 MySQL,事實上,從2013年底我們就開始引入和使用 MySQL 數據庫,比 PostgreSQL 還早了一年多。但最后,經過評估和實踐的檢驗,發現 PostgreSQL 對于大部分的金融應用場景更加適合,因此還是選擇了 PostgreSQL 數據庫做為科技的主流開源數據庫。

這里面包含有多方面的因素。支付場景是金融領域里較為受關注的部分。平安集團是一家綜合性金融服務企業,業務覆蓋了包括保險、基金、投資、證券等。保險業務就是最明顯的例子,業務邏輯極其復雜,即使是 OLTP 系統,也涉及對大量數據的訪問和計算。因此,很多業務邏輯都是在數據庫內部通過 package 或者 stored procedure 來實現的,這種處理方式對于 PostgreSQL 來說游刃有余。

我認為 MySQL 屬于 Thin Database,而 Oracle 和 PostgreSQL 屬于 Thick Database。Thin Database 的概念在于輕數據庫重應用。換句話說,就是數據庫只做為數據的存儲,只提供簡單的查詢訪問。而復雜的業務邏輯前移到應用服務器端來完成。MySQL 數據庫自身的特性并不十分豐富,例如 innoDB 存儲引擎只提供索引組織表形式的數據存儲格式,某種程度上限制了它的使用場景。對于觸發器和存儲過程的支持較弱,并不建議使用。應用的 CRUD 操作盡量通過主鍵進行,雖然支持二級索引,但通過二級索引操作會有性能損失。在進行關系型數據庫中必不可少的表關聯操作時,只支持 Nested Loops 關聯方法,缺少對  sort merge join 和 hash join 的支持。當關聯表超過2張時,MySQL 的優化器有時生成的執行計劃不優,造成性能下降。

也正因為如此,我們制定了針對 MySQL 的開發規范,例如表的大小不要超過多大,盡量書寫簡單查詢,通過主鍵來訪問數據,不要寫超過2張表相互關聯的 SQL 等。MySQL 更加適合業務邏輯簡單的 OLTP 應用。而對于 PostgreSQL 來說,無論業務邏輯簡單還是復雜,OLTP 還是 OLAP 負載,PostgreSQL 都可以支持,也都有很成熟的產品,很多著名的 OLAP 數據庫產品例如 Greenplum、AWS 的 Redshift 等都是基于 PostgreSQL 開發的。PostgreSQL 的查詢優化器非常強大,而且對于三種表關聯方法 Nested Loops,Sort-Merge Join 和 Hash Join 全部支持,對于復雜的 SQL 語句優化起來也不是問題,而這正是保險行業進行業務邏輯處理需要的特性。

PostgreSQL 還提供了強大的數據庫內部 function 支持,而且可以用多種語言編寫,對于復雜業務邏輯計算以及大數據量訪問完全可以在數據庫本地化實現,大大減少了網絡交互成本,從而整體提升應用性能。

因此,也有人說 PostgreSQL 不止是一個數據庫,更是一個強大的開發平臺,足見其功能之豐富。

我認為,PostgreSQL 的進程體系結構與 MySQL 的線程體系結構的不同點在于更加適合于垂直擴展。現在大家都在談分布式架構,橫向擴展,share nothing,我們不妨微觀上來看一下進程和線程架構的不同。以進程為主的體系結構,在操作系統內部來看,就是一個分布式架構,每個進程有自己的地址空間,share nothing,只在需要交互的時候通過 IPC 機制 shared memory 和 semaphore 來進行通訊,大多數情況下都是在處理自己的事務,互不干涉;而以線程為主的體系結構,共享地址空間,相當于 share everything,需要處理好線程間的關系以及對資源的訪問控制。因此,創建進程的成本雖然相比創建線程高,但卻容易擴展。對于平安如此體量的企業,系統負載非常大,雖然橫向擴展非常重要,但垂直擴展能力也是不容置疑需要考慮的因素。而且 PostgreSQL 和 MySQL 的橫向擴展能力都需要中間層或者代理層來實現,并不是依靠數據庫內核完成,在這一點上兩者并沒有區別,至少現在如此。這樣數據庫內核的垂直擴展能力更加重要。如果說到橫向擴展技術,MySQL 有 Fabric 和 TDDL,PostgreSQL 近年在分布式上發展也非常之快,有 Postgres-XL,pg_shard,Postgres-XZ 等產品。

還有重要的一點。在談到 TCO(Total Cost of Ownership)的時候,大家會覺得 PostgreSQL 和 MySQL 兩者都是開源產品,并沒有差別。但實際上,TCO 除了可能的 License 成本之外,還包括學習成本和運維成本。對于金融領域來講,過去使用的都是 Oracle、DB2 等商業數據庫。之前 Oracle 和 DB2 這些商業化數據庫發展了幾十年,數據庫自身的特性非常豐富,和 PostgreSQL 都屬于 Thick Database,也難怪 PostgreSQL 被稱為開源領域的 Oracle。大家可以想一下,對于用慣了商業化數據庫的開發人員還是 DBA 來講,哪一種數據庫對于他們來講更加熟悉一些?學習成本更低?多年的經驗更加容易轉化,復用?運維成本更低?我想答案是顯而易見的,這也是為什么平安選擇 PostgreSQL 的一個重要考量因素。

InfoQ:當數據量很龐大的時候,平安科技是怎么利用 PostgreSQL 實現異地備份的?

汪洋:平安對于系統的高可用和數據安全是極其重視的。我們結合了多年積累的數據庫運維經驗,為 PostgreSQL 建立了 MAA(Maximum Availability Architecture)架構。我理解這里的備份應該是廣義的備份概念,而不單指的是磁帶備份。我們對于 PostgreSQL 的磁帶備份是在本地的主庫上進行的。由于不支持直接上帶,所以先把備份寫入到 WOS(Web Object Scaler)分布式存儲上,然后再由 WOS 上帶。

由于在主庫備份會與應用爭搶 IO 資源,最初也評估過在本地從庫備份,但我們采用的 pg_rman 工具還是需要在主庫發起 begin backup 和 end backup 命令,考慮到網絡影響,加之當前 IO 資源也比較充足,所以備份暫時還是在主庫上進行,后續會考慮將備份操作遷移到從庫。異地的數據庫備份是通過搭建遠程容災庫實現的,使用 PostgreSQL 自身的 Streaming Replication 技術以異步方式傳輸并應用 WAL 日志來保持本地主庫和遠程從庫之間的數據同步。

這種情況下,主從之間的差異取決于日志量產生的速度,與數據庫大小關系不大。當前,平安科技最大的 PostgreSQL cluster 是 3TB,每分鐘產生的 WAL 在 80MB 左右,在這樣的負載下,本地主庫基本上和遠程從庫保持準同步的關系。

InfoQ:使用開源的 PostgreSQL 數據庫,平安科技在保證系統穩定、性能方面做了哪些優化措施?

汪洋:確實,PostgreSQL 是一個開源數據庫,我們在引入的時候對于系統的穩定性也尤其關注和重視。加之平安是一個綜合金融服務集團,業務范圍涵蓋金融行業的方方面面,各個業務線之間也有復雜的相互調用關系。如果一個系統出現問題,經常會有“牽一發而動全身”的影響。不僅可能會造成經濟損失,也會影響聲譽,所以在系統高可用、可靠性和穩定性上面我們做了大量工作。

最初我們采用的一主兩從的高可用架構。本地一主一從,遠程一從,大家都使用本地磁盤。這樣,當主數據庫發生問題,可以快速切換到本地從庫繼續提供服務。可很快我們發現,這樣在故障切換時有可能會發生數據丟失!對于某些金融應用來講,數據丟失是不能接受的。由于考慮到主從之間的網絡延遲會導致 OLTP 應用性能下降,主從之間并沒有采用同步復制(盡管PostgreSQL支持,這也是優于MySQL的地方)。

由于主從之間的強一致性沒有保證,所以切換時可能會發生數據庫丟失,影響 RPO。同時,使用本地盤使得計算和存儲強耦合。數據顯示,系統出現問題更多的是 CPU 和 RAM 而不是存儲。這樣,即使不是存儲問題,CPU 或者 RAM 的故障也會引發切換導致數據丟失。因此我們對架構進行了優化,一方面從使用本地盤切換為使用共享盤,另一方面為 PostgreSQL 建立了主備集群。這樣,在服務器發生故障時,集群可以快速將 Postgres 實例從主機切換到備機,并且因為使用的是共享盤,數據的一致性和完整性得到保障,不會有絲毫的數據丟失。

從性能上來看,共享盤也提供了比本地盤更好的 IO 性能,無論從 IOPS 上還是吞吐量上。在每一次的架構優化調整時,不止從理論上論證其可行性,也都是經過嚴格的測試驗證后才會實施。這點也體現在 Linux IO 調度器的選擇上。Linux 內核在 IO 調度上有四種策略,分別為 NOOP,CFQ(Complete Fairness Queueing),Deadline 和 Anticipatory。我們分別針對機械磁盤和 SSD 進行了 IO 的基準測試,在測試中模擬了數據庫讀寫負載 IO 的行為,包括隨機讀、隨機寫、順序讀、順序寫的不同組合,還包括對不同 IO 大小的測試,在各種組合下觀察監控不同 IO 調度策略下的性能數據。根據性能數據制定不同 IO 調度器設置規范。基于機械磁盤,CFQ 和 Deadline 表現優于其他兩種策略,但 CFQ 和 Deadline 之間差別不大,為了保持更大的適應性,選擇了 CFQ;而對于 SSD 閃存,經過測試 NOOP 和 Deadline 要由于 CFQ 和 Anticipatory,而且 Linux 7 內核已經缺省使用 Deadline,因此在 SSD 上我們采用 Deadline。

對于開源數據庫來講,監控自然也是必不可少的。我們所有的數據庫都采用統一的監控框架 Zabbix,極大降低了運維成本。根據 PostgreSQL 自己的特性,結合了多年 Oracle 運維的經驗,定制了很多監控指標。例如對慢查詢的監控,對于剩余事務年齡的監控用于判斷是否需要及早進行 vacuum,以及對 checkpoint 效率的監控等。為了對每一個 cluster 的性能有一個全面的了解,方便進行性能趨勢分析和定位問題發生的異常時段,我們借鑒了 Oracle 中非常優秀的 AWR(Automatic Workload Repository)概念,自己開發了 PGAWR 數據庫性能報告工具。里面不僅有 OS 的性能數據,也有 DB 整體的負載情況和性能數據,還有按照不同維度排序的 SQL 語句列表,可以對 DB 極其運行主機的情況一目了然,快速診斷問題和發現異常 SQL 語句。

種種,都是為了能夠讓 PostgreSQL 運行地更穩定,在問題發生時能夠快速定位、分析并加以解決,滿足金融行業對系統運行和恢復時效的需要。

InfoQ:能不能介紹一下平安科技 PostgreSQL 開源數據庫的架構設計,以及有哪些規范?

汪洋:從高可用架構上來看,對于 PostgreSQL 數據庫分為兩個層面,首先是主機故障,其次是存儲故障。之前提到,大部分的問題是由主機故障導致,存儲故障只占很少一部分。由于主機和故障發生機率的不對等性,我們進行了計算和存儲的解耦。為了防范主機故障,我們采用共享存儲,并且建立 Linux 服務器集群在主機發生問題時快速切換。由于計算和存儲解耦,也更加方便對主機進行主動維護,大大降低了數據丟失的可能性。雖然存儲故障發生機率小,但影響面卻很大,所以我們也沒有忽視對存儲故障的防護。在本地和遠程我們都建立了 PostgreSQL 的從庫,它們和主庫之間都采用異步復制策略。如果主庫存儲發生問題,短時間無法恢復,就會切到本地從庫繼續提供服務;如果發生地區性問題,則切換到遠程繼續提供服務。實現兩地三中心的防護。

除了高可用架構規范,在 PostgreSQL 架構規范中我們還定義了:

  1. 生產環境所采用的 PostgreSQL 版本號,以及 PostgreSQL 的 Patch 策略和升級策略;

  2. 服務器和操作系統用戶的命名規范;

  3. 數據庫應用使用的字符集設置;

  4. 每一個 cluster 的卷和目錄命名規則;

  5. PostgreSQL 數據庫的標準參數設置規范。

此外我們還制定了用戶架構規范,在規范中,定義了 PostgreSQL cluster 都應該有哪些標準的初始化用戶,例如 DBA 用戶,部署專用用戶,復制用戶,監控用戶等。對于每一個 Database,創建屬主用戶以及應用連接用戶,以最小化權限原則授予應用連接用戶必需的權限,規避進行危害性操作的風險。對于運營人員,在規范中也有明確的定義,按照職責劃分創建不同的專屬用戶。這樣,實現 DBA、運營和開發人員的權限分離,一方面最小化權限將對數據庫的可能危害降到最低,另一方面便于后續的審計和追蹤。

對于數據庫系統的健康、穩定運行,開發規范一樣重要。在給開發人員制定的開發規范中,我們分別從命名規范和設計規范兩大方面進行了描述。命名規范包括對表、字段、索引、視圖等數據庫對象的命名要求,而設計規范包括對表、索引、分區表在設計時的一些原則的描述。通過這些規范要求,讓開發人員可以相對簡單地進行應用系統的設計,降低系統運行時的性能風險。而且,我們還將這些規范集成到了數據庫自動化審計平臺中,例如在版本提交階段自動審核數據庫版本是否合規,SQL 語句是否包含全表掃描,隱式轉換等高風險操作等,進一步加強了質量控制,降低了系統上線后的風險,簡化了運維工作。

InfoQ:在后期運維過程中對架構、規范進行了怎樣的優化,引入了哪些新技術?目的是什么?

汪洋:PostgreSQL 畢竟在平安引入的時間不長,到今天也差不多1年半的時間。雖然,我們制定了 PostgreSQL 的推廣策略,按照系統復雜度、系統重要程度分層級逐步推廣,但在推廣使用的過程中,還是會遇到這樣那樣的一些問題。對此,我們要求每一個問題都要找到根本原因,只有這樣才能有的放矢地不斷調整和優化。

之前提到的從最初的使用主從架構和本地磁盤調整到使用 Linux 服務器集群加共享存儲就是一個明顯的例子。在這里,我想再分享一個例子。有一次,在運行的一個數據庫上,發現產生的 WAL 日志非常之快,數據庫本身并不大,只有 100GB,但每小時產生的 WAL 卻可達到 300GB 之多。這是一個典型的小庫高負載的案例,通過詳細分析發現,雖然庫本身負載很高,但也和未經優化的 checkpoint 相關參數配置相關。負載高和 checkpoint 的配置形成了惡性循環,導致 WAL 生成量巨大,造成系統磁盤空間告急此類可用性風險。雖然調整過一次參數,但因為未找到根本原因,并沒有從根本上解決問題。隨著越來越多高負載的重要數據庫使用 PostgreSQL,對于以后繼續推廣存在較大隱患,必須找到根本原因,徹底解決問題。經過對 WAL 生成原理進行研究,對日志進行分析,甚至對 PostgreSQL 源碼進行理解,終于對 WAL 生成機制有了較為清晰的了解。并針對性地制定了參數調整策略和未來使用新版本時的規范。問題主要和兩個參數相關,一個是 wal segment size,一個是 checkpoint_segments。缺省值設置較低,wal_segment_size 是 16MB,checkpoint_segments 是 32,不太適合運行金融系統的高負載應用。由于 wal segment size 只能在 PostgreSQL 軟件編譯時調整,所以對于現有系統,只能調整 checkpoint_segments。對于這個特定的數據庫,第一次在沒有找到根本原因的情況下將 checkpoint_segments 調整到了 128,但沒有從根本上解決問題。在分析后,調整到了 512,WAL 生成量大幅減少,達到了預期的效果。在未來使用新的 PostgreSQL 版本時,我們調整了規范,在編譯時將 wal segment size 調整為 64MB(缺省的4倍),并且根據系統的負載情況靈活調整從9.5開始引入的參數 max_wal_size,使得系統可以更加穩定地運行金融系統應用。

另外,隨著 PostgreSQL 對 JSON 的支持越來越豐富,越來越成熟,我們也開始在 PostgreSQL 上推薦使用 JSON 數據類型。特別要提到的是,在關系型數據庫領域,PostgreSQL 的 JSON 支持要比 MySQL 和 Oracle 都早,MySQL 從5.7開始支持 JSON,Oracle 是從 12cR1 將對 JSON 的支持 backport 到了 11.2.0.4,PostgreSQL 則走在了前面。和 Document DB 領域中原生支持 JSON 數據類型的佼佼者 MongoDB 比較,經過測試驗證,我們發現 PostgreSQL 的性能并不差。而 MongoDB 由于屬于 NoSQL,并不支持表(或者說 collection)之間的關聯,PostgreSQL 恰好填補這方面的空缺。對于一些有 JSON 文檔存儲需求,但又需要和關系型或者結構化數據關聯的應用場景 PostgreSQL 無疑是非常適合的一款數據庫。

當然,我們對于 PostgreSQL 還在不斷地學習,不斷地探索。但隨著對它的認識越來越深入,我們的信心也在不斷增強。特別是前不久 PostgreSQL 9.6 的發布,里面的很多新特性更是讓人期待,也讓大家看到了 PostgreSQL 的未來!

InfoQ:通過 PostgreSQL +金融的完美結合這一案例,你有哪些心得感想可以和 InfoQ 的讀者分享的?

汪洋:2015年可以稱之為平安的 PostgreSQL 元年,從2014年底開始接觸 PostgreSQL,到2015年初開始立項準備、調研、評估、測試、制定規范、制定推廣策略,到真正的使用推廣,到現在有超過1000個 PostgreSQL 的實例在運行,一路走來,既為取得的成績而高興,同時又感覺殊為不易。但今天我可以告訴大家,當初的選擇是正確的,我很慶幸選擇了 PostgreSQL 這樣一款優秀的數據庫產品,并且在團隊的努力下能夠讓 PostgreSQL 在平安扎根,發芽并且茁壯成長。過程中,不是沒有人質疑過,但我們相信自己的判斷和選擇,更重要的是我們相信 PostgreSQL 產品本身能夠幫助我們實現支撐金融系統應用的穩定運行,降低數據庫運營成本,擁抱開源技術,達到信息自主可控的目標。于是,我們耐心地說服,全力地配合,悉心地指導,以獲得大家的認同。漸漸地,事實和數據也證明了 PostgreSQL 是一款非常穩定的高性能數據庫產品,能夠運行金融級別的應用系統。

每一種數據庫產品都有它的應用場景,每一家公司也都有著不同的資源,在選擇一款數據庫產品時,不能隨大溜,跟潮流,一定要根據自身的情況,對包括未來數據庫技術的發展,業務的特性,金融監管的要求,公司人員具備的技能等做出全方位的分析,進而選擇一款最適合自己的數據庫。而且,在數據庫技術蓬勃發展的今天,企業可能也會根據不用的應用場景選擇多種數據庫產品,用以滿足存放和訪問不同數據類型的需要。這本身也是一個尋找最優化配置的過程,實現價值的最大化。

還有一點我覺得很重要,就是每一種數據庫,都要按照它原本的設計思想和設計目標去使用它,而不能把它當成黑盒子。首先要去了解它,然后再去適配它,只有這樣才能達到最好的磨合效果,才有可能將性能發揮到極致。反之,則會出現強扭的瓜不甜,導致性能問題。

雖然平安科技的 PostgreSQL 應用規模已經很大,取得了不小的成績,但平安在 PostgreSQL 數據庫上還有很長的路要走。例如如何使用分布式架構來提升 PostgreSQL 的橫向擴展能力,支撐 VLDB(Very Large Database),不僅可以運行 OLAP 負載,也可以運行 OLTP 負載;還有如何豐富 PostgreSQL 的性能數據和診斷數據,進一步提升在問題發生時的分析、定位以及解決時效,將對系統的影響程度降到最低。

這些都是我們接下來面臨的挑戰,對于象平安這樣的綜合金融服務集團挑戰尤其嚴峻。但可喜的是,我們看到 PostgreSQL 的發展越來越成熟,功能越來越豐富,很多我們希望的特性要么已經被實現,要么就是已經被納入規劃。PostgreSQL 的社區也在不斷壯大,日趨活躍,不斷有新的公司開始采用 PostgreSQL。在這樣的大好形勢下,相信 PostgreSQL 一定可以鞏固在開源數據庫領域的領導地位,不僅成為最先進的開源數據庫,而且成為金融服務行業最強大的開源數據庫!

 

來自:http://www.infoq.com/cn/news/2016/10/postgres-and-financial-arch

 

 本文由用戶 ShaDuby 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!