海量數據存儲實踐分享:NoSQL - 集羣流批 - PG 集羣 - 內存緩存

**【導讀】**某機構原採用的 Oracle 的 RAC 作爲數據存儲,隨着業務量和數據量的增大,對於系統的穩定性和擴展性造成了極大的問題。現在採用 Postgres 集羣 + Redis 內存數據庫 + Druid 實時分析數據庫 + Hbase 列式數據庫 + HDFS+Kafka 消息隊列;輔以 Minio 分佈式文件存儲實現的,目前使用效果良好。本文介紹了整合建設的初期存在的技術痛點和建設實踐經驗,希望可以爲大家提供參考借鑑。

**【作者】董生,**擁有 13 年 IT 工作經驗,有豐富的互聯網金融從業經歷和金融機構工作履歷,從事過交易系統、數據治理及數據架構設計和基於產品設計,擅長互金產品、客戶管理、資金清算及風控領域,曾在多家金融機構任職 CIO 和高級產品經理。目前就職於中國郵政儲蓄銀行。

一、項目建設背景

隨着大數據、雲計算、移動互聯迅速發展,快速交付與靈活擴展的強烈需求增長,傳統豎井式的 IT 基礎架構設施面臨着新的挑戰。一方面快速增長的互聯網業務需要靈活的、可自由伸縮、不限於規格容量的存儲的 IT 軟硬件資源提供堅實基礎保障,另一方面高效的業務響應同傳統的 IT 基礎設施發展矛盾也日益突出。例不可預估的互聯網業務客戶量、持續增長的日交易量、重要時期的高峯的運行壓力、大量併發 IO 讀寫,系統響應緩慢,關鍵指標時效性不足,而這些性能痛點最先反映在數據存儲 IO 上。

因此如何全面規劃和整合當前 IT 基礎架構中的數據存儲體系,構建靈活、高效、先進的高可用存儲架構,實現可滿足生產系統的高併發、低延時的性能需求,是金融機構 IDCIT 信息化建設的迫切要求。

二、高性能高併發的數據存儲建設痛點

隨着信息大數據時代的來臨,對信息收集的需求越來越高,在原來客戶交易信息留存的基礎上,增加了客戶的行爲及客戶的屬性等信息。對於一個大型的應用系統,海量數據的存儲和訪問成爲了系統設計的瓶頸問題。

我機構原先系統採用的是 Oracle 的 RAC 作爲數據存儲,隨着業務量和數據量的增大,對於系統的穩定性和擴展性造成了極大的問題。現在採用 Postgres 集羣 + Redis 內存數據庫 + Druid 實時分析數據庫 + Hbase 列式數據庫 + HDFS+Kafka 消息隊列;輔以 Minio 分佈式文件存儲實現的,目前使用效果良好,但在整合建設的初期,是存在許多技術痛點的。

1、是否堅持所有數據一致性原則

傳統的項目,幾乎清一色的使用傳統的關係型數據庫 (RDBMS)。從早期的 MySQL、SQL Server 到後期的 Informix、Db2、Oracle 再到 Oracle RAC。關係型數據庫是強事物一致性 (ACID),使用比較早,技術相對成熟。

ACID 它的核心是 “約束”,而這個“約束” 由數據庫的使用者告訴數據庫,使用者要求數據一定是符合這樣或者那樣的約束條件。當數據發生修改時,數據庫會檢查數據是否還符合約束條件,如果約束條件不再被滿足,那麼修改操作不會發生。關係數據庫最常見的兩類約束是 “唯一性約束” 和“完整性約束”,表格中定義的主鍵和唯一鍵都保證了指定的數據項絕不會出現重複,表格之間定義的參照完整性也保證了同一個屬性在不同表格中的一致性。

當數據庫系統從批量處理進化到在線實時系統後,事務就可以併發地在數據庫上進行操作,在給使用者帶來便利的同時也給數據庫系統開發人員帶來了諸多困難。嚴肅的數據庫系統都會有一套複雜的併發控制機制來保證事務並行執行時數據的正確性。而事務隔離性最大的煩惱來自併發控制對性能的影響,最嚴格的隔離性保證了所有的事務雖然是併發執行,但是最終執行的結果跟事務一個個串行着做是一樣的,可串行化保證了一定不會因爲併發進行的事務導致數據出錯,但是這也會導致事務有更多等待或者失敗。

在進入大數據時代後,超高的併發訪問量以及海量的數據,註定使用 ACID 的原則將使得系統需要一個性能極高的計算器進行運算。無疑這給系統帶來了巨大開銷浪費。

原本單位使用的是 Oracle 的 RAC,但是在越來越多的數據存儲和更多的訪問併發,單點 IO 吞吐量的制約效果,越來越明顯。

當關系型數據庫越來越成爲瓶頸時,爲解決單點瓶頸,適當採取犧牲 CAP 屬性中的 C,也不失爲一個可選的策略。

早期的系統調研中,有的場景對於實時性一致性要求高,但是每次操作的數據量不大。而在其他的常見中,每次操作的數據量較大,但是對於數據的實時一致性沒有過高的要求。

基於此,對於數據存儲的選型,要區別對待。對於前後數據需要一致性的,依舊採用關係型數據庫,用數據庫事務來保證數據的 ACID 一致性要求。對於併發訪問量高,但是數據的時效性和對比關聯性不是很強的場景,我們採用分佈式數據存儲來應對。

經過多次選型調研,最終選擇了 Postgres 數據庫作爲關係型數據庫的載體,用於 ACID 的場景。使用 NoSQL 的數據存儲作爲高併發訪問的場景的數據存儲。

2、非關係型數據庫選型

市面常見的 NoSQL 包括 Redis、Durid、Hbase、MongoDB、Hive 等。對於不同應用場景的選擇是不同的。

MongoDB 表結構靈活可變,字段類型可以隨時修改。記錄以 Json 格式後存儲,不需要定義表結構。但是多表查詢、複雜事務等高級操作效率低下。所以其適合於寫少讀多的場景。

HBase 列式存儲特性帶來了海量數據規模的支持和極強的擴展能力,但是由於查詢都必須要依賴 rowKey,這就使得很多複雜查詢難以進行。例如,如果你的查詢條件涉及多個列項,或者你無法獲取要查詢數據的 key,那麼查詢效率將會非常低下。

Druid 是基於 MPP 架構的 OLAP,其預聚合算是 Druid 的一個非常大的亮點,通過預聚合可以減少數據的存儲以及避免查詢時很多不必要的計算。適用於大量數據的下的實時聚合查詢場景。

Redis 犧牲了常規數據庫中的數據表、複雜查詢等功能,特別適合那些對讀寫性能要求極高,查詢條件也同樣簡單的應用場景。

HIVE 數據倉庫,基於 HDFS 的結構,支持主流的 SQL 但是查詢的速度較慢,適合於大批量場景的數據加工,存儲的場景。

下面有個對比的表格:

4ZsIvm

3、數據災備方式的選擇

數據是科技公司最大的資產,每個公司都在數據災備上面作爲了大量的應用防止出現意外時候,數據丟失及訪問異常。爲最大程度的降低風險。早期考慮 dump 每天的數據快照,在異地數據庫進行恢復,但是這樣存在 dump 期間的數據丟失情況。一旦出現數據服務器 down 機的情況,備庫是無法承接使用的。

現在 Postgres 集羣本地採用一主兩從的流複製方式,保證主從節點之間數據一致性。同時在一臺從節點上使用級聯複製爲異步 IDC 提供數據同步服務。

HDFS 採用跨 IDC 機架的方式,Redis、Durid、MongoDB 採用集羣模式、保證數據災備時候,能夠快速切換到備機使用,且數據不會丟失。

三、建設實踐

1、關係型數據庫應用

 關係型中數據庫切分存儲

由於去 IOM 的要求及未來國產化、開源化的大趨勢。我們最終選擇了 Postgres 作爲關係型數據庫的載體。

單庫 Postgres 性能無法滿足高併發訪問的要求,採用了分庫分表的數據邏輯切分。由於是強職能管理型的系統特性。客戶關聯的數據信息使用基於所在轄區水平分庫切分,而管理公共信息、統計報表信息、數據概覽信息、以垂直切分的方式切分。對於常用的表,在各個數據庫中冗餘存儲。以此減少 OLAP 操作時網絡傳輸的耗時,同時便於利用數據庫本身的特性。

這樣切分,雖然不同的數據庫中數據相較於一致性 hash 分庫原則會不一致,不同轄區對應的數據庫中數據量可能不一樣多,犧牲了一部分的存儲。但是較系統的性能,還是值得的。

同時對於數據庫當日產生的操作信息及交易流水,按照一致性 Hbase 的原理,將流水信息存儲在以流水號切分的數據庫節點中存儲。

在衆多的 PostgreSQL HA 方案中,流複製 HA 方案是性能,可靠性,部署成本等方面都比較好的,也是目前被普遍採用的方案。而用於管理流複製集羣的工具中,Pacemaker+Corosync 又是比較成熟可靠的。同時爲了兼顧異地災備,以一個從節點進行級聯複製,將數據異地災備到其他 IDC 機房節點。

系統基於 Pacemaker+Corosync 實現 PG 集羣的 Master-Slave 模式,如圖所示:

讀寫分離、高可用

使用 pacemaker 實現集羣資源的管理,業務層通過 write-vip 實現數據向 Master 節點的寫入,通過 read-vip 實現 Slave 節點數據的讀取;主節點故障時,vip 會自動漂移,從節點升爲主庫,實現 PG 的高可用。

數據、狀態同步

Master 與 Slave 節點基於流複製(Steaming Replication)通過 1.X(eth1)網段實現數據的同步;通過 2.X(eth2)網段,corosync 實現 Master 與 Slave 節點狀態同步。

主從切換策略

  1. 初始狀態下,master 數據庫和 write-vip 在節點 1 上運行,slave 數據庫和 read-vip 在節點 2 上運行。

  2. 當 master 數據庫或 master 數據庫所在節點宕機時,節點 2 上的 slave 數據庫提升爲 master 數據庫,同時 write-vip 飄移到節點 2 上。

  3. 當 slave 數據庫所在節點 2 宕機時,slave 數據庫停止運行,read-vip 飄移到 node1。

2、Redis 內存數據庫存放熱點數據以及公共參數和映射參數

由於客戶信息進行了切分。爲了快速的找到一個客戶所在的信息。我們將客戶及客戶所在數據庫的映射關係、客戶交易流水的 hash 鍵值的映射關係作爲熱點數據存放於 Redis 中。

同時系統中需要承載的公共參數也放入了 Redis 中。

同時將客戶交易信息中,交易金額超過 1 萬元的大額數據交易信息以及每天日終提取出最近一季度活躍的客戶信息,將這部分活躍的客戶關鍵標誌信息和大額交易標誌信息,也存放在 Redis 中,用於檢索時候,直接在內存中進行檢索,而非直接訪問數據庫,當 Redis 中沒有的時候再訪問對應的數據庫。

映射關係、公共參數採用集羣模式部署 HA。熱點數據由於數據量較大,集羣模式寫入慢,採用了哨兵的模式部署 HA。

其中哨兵 3 臺節點 集羣 6 臺節點。

3、Durid 檢索聚合重點信息


有時候存在在全單位維度的數據 OLAP 的數據加工和抽樣。如果在每個數據庫中抽樣結果聚合後,在通過程序二次篩選,一方面架構複雜,另外一方面開發成本較高。爲此我們引入了 Druid,在其中存儲了全機構的所有客戶和客戶的重點屬性信息。

每次需要聚合查詢的時候,從 Druid 中根據客戶重點信息檢索出目標集合。如果目標集合的展示信息不夠,在根據目標集合到對應的 PG 分庫或者 Hbase 中查詢出應的數據信息。

4、HBase 應用歷史交易明細信息

明細信息存放於 HBase 中注意基於以下幾個情況:

PG 分庫分表存放:

(1)數據量較大,PG 數據庫壓力過大,數據庫內存數據的頻繁交換

(2)分庫分表,數據庫維護成本的增加,例如數據庫表清理維護,數據同步策略,路由策略。

採用 Druid 存儲:

大量數據存入 Druid,Druid 集羣壓力大。

由於 HBase 適合於讀少寫多的情況,而歷史明細一般查詢較少。所以放入 HBase 進行保存。

於是採用了將索引與數據存儲隔離的原則,只把可能參與條件檢索的字段索引到 Druid 中,這樣整個 Druid 集羣壓力減少到原來的 1/N,全量的客戶歷史交易明細根據檢索出的主鍵,作爲 ROWKEY 在 HBase 內查詢。

實際應用中,用客戶號 + 日期 + 交易流水號作爲 ROWKEY。當發生交易時候,首先在交易數據庫節點寫入當天的流水信息。同時寫入的操做通過 Kafka 消息隊列傳到後線服務。後線服務實時寫入 HBase 中存放歷史交易明細的表中

5、MongoDB 應用用戶的屬性行爲偏好信息

因爲系統的定位原因,系統主要用戶客戶信息的檢索,並對客戶進行產品推薦以及其他金融服務。所以客戶的屬性信息是訪問量最大的。但是其修改又很少。這種正適合於 MongoDB 的應用場景。

每天晚上通過 hive 數據倉庫,加工出客戶的屬性信息。將其導入 MongoDB 用於白天的高併發訪問的查詢。

MongoDB 有三種集羣部署模式,分別爲主從複製(Master-Slaver)、副本集(Replica Set)和分片(Sharding)模式。

Master-Slaver 因爲不提供自動 HA 功能,所以建設中沒有考慮使用。

Replica Set 將數據複製多份保存,不同服務器保存同一份數據,在出現故障時自動切換,實現故障轉移。但遇到需要存儲海量數據的情況時,副本集機制就束手無策了。副本集中的一臺機器可能不足以存儲數據,或者說集羣不足以提供可接受的讀寫吞吐量。

所以最終選擇了 Sharding 模式,它將數據分開存儲,不同服務器保存不同的數據,所有服務器數據的總和即爲整個數據集。

Mongodb(R) 表示路由節點, 點 Mongodb(C) 表示配置節點,Mongodb(M) 表示主節點,Mongodb(S) 表示備節點,Mongodb(A) 表示仲裁節點。

Mongodb(M),Mongodb(S),Mongodb(A) 組成一個分片服務器,整個的數據分佈存儲在不同的分片服務器中。其中 Mongodb(M),Mongodb(S) 用於實際數據存儲。Mongodb(A) 負責仲裁選主,不存儲數據。

Mongodb(R) 在集羣中可作爲路由使用,客戶端由此接入,讓整個集羣看起來像是一個單一的數據庫,提供客戶端應用程序和分片集羣之間的接口。

Mongodb(C) 是獨立的一個 Mongodb 進程,保存集羣和分片的元數據,在集羣啓動最開始時建立,保存各個分片包含數據的信息。

6、HIVE 數據倉庫

在 HDFS 構建 Hive 數據倉庫,用於上面 5 部分的數據加工源。

Hive 的數據源來源於本系統的數據和外系統的數據。本系統數據通過 Kafka 寫入 Hive,外系統數據通過文件的方式採集。

Hive 的高可用分爲 Hive Metastore 的高可用和 HiveServer2 的高可用。

Hive Metastore HA 解決方案旨在處理 Metastore 服務失敗。每當部署的 Metastore 服務關閉時,Metastore 服務在相當長的時間內都會保持不可用狀態,直到恢復服務爲止。爲避免此類停機,在 HA 模式下必須部署 Metastore 高可用,而不是隻有 HiveServer2 的高可用。

四、實踐應用架構

五、建設後小感

其實數據建設不是一蹴而就的,很多時候都是在實踐中邊摸索邊前進。本單位的數據應用建設也是經過了多個階段,很有幸,自己都全程參與了。最早的時候 RAC。到 RAC + 集羣離線,到集羣離線 + PG 集羣,最後發展到 NoSQL + 集羣流批 + PG 集羣 + 內存緩存的模式。

建設到本期之後,數據的支持能達到在 10000+TPS 的時候訪問 60 億以上記錄達到秒級響應。最長耗時不超過 2.5S。在數據容量 300TB 以上,這樣的併發條件下,取得這個成績我個人還是蠻欣慰的。未來數據湖的出現,可能有一批新的技術等待我們應用。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Cw1ICqKvXVVKUiNIyQO7JQ