小米開源數據庫簡介

更好的樣式前往 個人Github筆記 查看

<md文檔排版很差>html

數據模型

組合鍵:Table + HashKey + SortKeymysql

  1. Table實現業務數據的隔離git

  2. HashKey決定數據在那個分片github

  3. SortKey決定數據在分片內的排序redis

一致性協議

使用PacificA協議,保證多副本數據的一致性。sql

<!-- addition -->數據庫

機器

Pegasus分佈式集羣至少須要準備這些機器:緩存

  • MetaServer安全

    • link:Meta Server 的設計服務器

    • 要求:2~3臺機器,無需SSD盤。

    • 做用:用來保存表和表的分片信息。

  • ReplicaServer:

    • link:Replica Server 的設計

    • 要求至少3臺機器,建議掛SSD盤。譬如一臺服務器掛着8塊或者12塊SSD盤。這些機器要求是同構的,即具備相同的配置。

    • 做用:至少三臺ReplicaServer。每個ReplicaServer都是由多個Replica組成的。每個Replica表示的是一個數據分片的Primary或Secondary。

  • Collector:可選角色,1臺機器,無需SSD盤。該進程主要用於收集和彙總集羣的統計信息,負載很小,建議放在MetaServer的其中一臺機器上。

Replica

  • 一個數據分片對應3個Replica。

  • Replica有兩個種類:Primary和Secondary。

  • 在一個數據分片對應的 3 個或以上的Replica中,只有1個Primary,其他的均是Secondary。

  • 不少個Replica組成一個ReplicaServer,同一個ReplicaServer中的Replica種類不相同。

    • 同一個ReplicaServer中的Replica不必定全是Primary,也不必定全是Secondary。

  • 一個最基本的Pegasus集羣,最少須要 3 個ReplicaServer。

在Pegasus中,一個Replica有以下幾種狀態:

  • Primary

  • Secondary

  • PotentialSecondary(learner):

    • 當group中新添加一個成員時,在它補全完數據成爲Secondary以前的狀態

  • Inactive:

    • 和MetaServer斷開鏈接時候的狀態,或者在向MetaServer請求修改group的PartitionConfiguration時的狀態

  • Error:

    • 當Replica發生IO或者邏輯錯誤時候的狀態

寫流程

寫流程相似於兩段提交:

  1. 客戶端根據Key首先查詢MetaServer,查詢到這個Key對應的分片的對應的ReplicaServer。具體來講,客戶端須要的實際上是分片Primary所在的ReplicaServer。

  2. 客戶端向Primary ReplicaServer發起寫請求。

  3. Primary ReplicaServer向其對應的兩臺或以上的Secondary ReplicaServer複製數據。

  4. Secondary ReplicaServer將數據寫入成功後,Primary ReplicaServer向客戶端返回成功的響應。

可能致使ReplicaServer不能響應寫請求的緣由有:

  1. ReplicaServer沒法向MetaServer持續彙報心跳,自動下線。

  2. Replica在IO上發生了一些沒法恢復的異常故障,自動下線。

  3. MetaServer將Replica的Primary進行了遷移。

  4. Primary在和MetaServer進行group成員變動的操做,拒絕寫。

  5. 當前Secondary個數太少,Replica出於安全性考慮拒絕寫。

  6. 出於流控考慮而拒絕寫。

讀流程

只從Primary讀。

宕機恢復

  • MetaServer和全部的ReplicaServer維持心跳。

  • 經過心跳來實現失敗檢測。

  • 宕機恢復的幾種狀況:

    • Primary Failover:若是某個分區的Primary所在的ReplicaServer宕機了,那麼MetaServer 就會選擇一個Secondary成爲Primary。事後再添加Secondary。

    • Secondary Failover:若是某個分區的Secondary所在的ReplicaServer宕機了,那麼暫時使用一主一副的機構繼續提供服務。事後再添加Secondary。

    • MetaServer Failover:主MetaServer宕機了,備用的MetaServer經過zookeeper搶主成爲新的主MetaServer。從zookeeper恢復狀態,而後從新和全部ReplicaServer創建心跳。

  • 宕機恢復過程當中,儘可能避免數據的跨節點複製。

zookeeper搶主

<!-- zookeeper搶主 -->

link:zookeeper搶主

單機存儲

一個ReplicaServer包括多個Replica,Replica使用RocksDB做爲存儲引擎:

  • 關閉掉了rocksdb的WAL。

  • PacificA對每條寫請求都編了SequenceID,RocksDB對寫請求也有內部的SequenceID。Pegasus對兩者作了融合,來支持自定義的checkpoint的生成。

  • Pegasus給RocksDB添加了一些compaction filter以支持Pegasus的語義:例如某個value的TTL。

和不少一致性協議的實現同樣,Pegasus中PacificA的實現也是和存儲引擎解耦的。

RocksDB

<!-- RocksDB -->

link:RocksDB

數據安全

  • Table軟刪除

    • Table刪除後,數據會保留一段時間,防止誤刪除

  • 元數據恢復

    • Zookeeper損壞時,從各ReplicaServer收集並重建元數據

  • 遠程冷備份

    • 數據按期備份到異地,譬如HDFS或者金山雲 • 在須要的時候可快速恢復

  • 跨機房同步

    • 在多個機房部署集羣

    • 採用異步複製的方式同步數據

冷備份

Pegasus的冷備份功能用來將Pegasus中的數據按期生成快照文件,並備份到其餘存儲介質上,從而爲數據容災多提供一層保障。但因爲備份的是某個時間點的數據快照文件,因此冷備份並不保證能夠保留全部最新的數據,也就是說,恢復的時候可能會丟失最近一段時間的數據。

具體來看,冷備份過程要涉及到以下一些參數:

  • 存儲介質(backup_provider):

    • 指其餘的文件存儲系統或服務,如本地文件系統或者HDFS。

  • 數據冷備份的週期(backup_interval):

    • 週期的長短決定了備份數據的覆蓋範圍。若是週期是1個月,那麼恢復數據時,就可能只恢復一個月以前的數據。但若是週期設的過短,備份就會太頻繁,從而使得備份開銷很大。在小米內部,冷備份的週期一般是1天。

  • 保留的冷備份個數(backup_history_count):

    • 保留的備份個數越多,存儲的空間開銷就越大。在小米內部,通常保留最近的3個冷備份。

  • 進行冷備份的表的集合(backup_app_ids):

    • 並非全部的表都值得進行冷備份。在小米內部,對於常常重灌全量數據的表,咱們是不進行冷備份的。

在Pegasus中,以上這幾個參數的組合稱爲一個冷備份策略(backup_policy)。數據的冷備份就行按照policy爲單位進行的。

跨機房同步

link:跨機房同步文檔

小米內部有些業務對服務可用性有較高要求,但又不堪每一年數次機房故障的煩惱,因而向 pegasus 團隊尋求幫助,但願在機房故障時,服務可以切換流量至備用機房而數據不致丟失。由於成本所限,在小米內部以雙機房爲主。

一般解決該問題有幾種思路:

  1. 由 client 將數據同步寫至兩機房。這種方法較爲低效,容易受跨機房專線帶寬影響,而且延時高,同機房 1ms 內的寫延時在跨機房下一般會放大到幾十毫秒,優勢是一致性強,但須要 client 實現。服務端的複雜度小,客戶端的複雜度大。

  2. 使用 raft/paxos 協議進行 quorum write 實現機房間同步。這種作法須要至少 3 副本分別在 3 機房部署,延時較高但提供強一致性,由於要考慮跨集羣的元信息管理,這是實現難度最大的一種方案。

  3. 在兩機房下分別部署兩個 pegasus 集羣,集羣間進行異步複製。機房 A 的數據可能會在 1 分鐘後複製到機房 B,但 client 對此無感知,只感知機房 A。在機房 A 故障時,用戶能夠選擇寫機房 B。這種方案適合 最終一致性/弱一致性 要求的場景。後面會講解咱們如何實現 「最終一致性」。

基於實際業務需求考慮,咱們選擇方案3。

即便一樣是作方案 3 的集羣間異步同步,業內的作法也有不一樣:

  1. 各集羣單副本:這種方案考慮到多集羣已存在冗餘的狀況下,能夠減小單集羣內的副本數,同時既然一致性已沒有保證,大能夠索性脫離一致性協議,徹底依賴於穩定的集羣間網絡,保證即便單機房宕機,損失的數據量也是僅僅幾十毫秒內的請求量級。考慮機房數爲 5 的時候,若是每一個機房都是 3 副本,那麼全量數據就是 3*5=15 副本,這時候簡化爲各集羣單副本的方案就是幾乎最天然的選擇。

  2. 同步工具做爲外部依賴使用:跨機房同步天然是儘量不影響服務是最好,因此同步工具能夠做爲外部依賴部署,單純訪問節點磁盤的日誌(WAL)並轉發日誌。這個方案對日誌 GC 有前提條件,即日誌不能夠在同步完成前被刪除,不然就丟數據了,但存儲服務日誌的 GC 是外部工具難以控制的。因此能夠把日誌強行保留一週以上,但缺點是磁盤空間的成本較大。同步工具做爲外部依賴的優勢在於穩定性強,不影響服務,缺點在於對服務的控制能力差,很難處理一些瑣碎的一致性問題(後面會講到),難以實現最終一致性

  3. 同步工具嵌入到服務內部:這種作法在工具穩定前會有一段陣痛期,即工具的穩定性影響服務的穩定性。但實現的靈活性確定是最強的。

最初 Pegasus 的熱備份方案借鑑於 HBase Replication,基本只考慮了第三種方案。而事實證實這種方案更容易保證 Pegasus 存儲數據不丟的屬性。

每一個 replica (這裏特指每一個分片的 primary,注意 secondary 不負責熱備份複製)獨自複製本身的 private log 到遠端,replica 之間互不影響。複製直接經過 pegasus client 來完成。每一條寫入 A 的記錄(如 set / multiset)都會經過 pegasus client 複製到 B。爲了將熱備份的寫與常規寫區別開,咱們這裏定義 duplicate_rpc 表示熱備寫。

A->B 的熱備寫,B 也一樣會經由三副本的 PacificA 協議提交,而且寫入 private log 中。這裏有一個問題是,在 A,B 互相同步的場景,一份寫操做將造成循環:A->B->A,一樣的寫會無數次地被重放。爲了不循環寫,咱們引入 cluster id 的概念,每條 duplicate_rpc 都會標記發送者的 cluster id。

[duplication-group]
A=1
B=2
void set(String tableName, byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds)

直接使用pegasus優化,直接對pegasus讀、寫。能夠替代redis緩存的架構。

  1. 讀寫邏輯複雜

  2. 要特地維護數據一致性

  3. 服務可用性不高

  4. 機器成本高

問題:

讀取:先讀取緩存,若是緩存中不存在,那麼再讀取數據庫中的數據。

寫入:雙寫,既寫入緩存、也要寫入數據庫。

原先:Redis 做爲緩存 + HBase/mysql/MongoDB 做爲數據庫。

業務應用

  HashKey SortKey Value
map MapId key value
set SetId key null
list ListId index value

Pegasus自己不支持容器類型,可是其HashKey + SortKey的數據模型能夠模擬容器。

容器支持

對HashKey或者SortKey進行字符串匹配, 只有符合條件的結果纔會返回。對HashKey或者SortKey進行字符串匹配,只有符合條件的

條件過濾

同一個HashKey的數據寫入同一個Replica,同一個Replica的操做,在同一個線程中串行執行。這樣就避免了同步的問題。

對同一個HashKey的寫操做,保證老是原子的,包括set、multiSet、del、multiDel、incr、 checkAndSet。

單行事務

支持對數據指定過時時間, 數據過時後就沒法讀取到。

TTL過時策略
  1. 線程安全

    • 全部的接口都是線程安全的,不用擔憂多線程的問題。

  2. 併發性能

    • 客戶端底層使用異步的方式實現,能夠支持大的併發,不用擔憂性能的問題。

  3. Client單例

    • 經過 getSingletonClient() 得到的Client是單例, 能夠重複使用。

  4. 翻頁功能

    • 經過客戶端提供的接口,可以輕鬆實現數據翻頁功能 。

Java客戶端

集羣使用falcon進行監控。

集羣監控

使用

熱備份同時也須要容忍在 replica 主備切換下複製的進度不會丟失,例如當前 replica1 複製到日誌 decree=5001,此時發生主備切換,咱們不想看到 replica1 從 0 開始,因此爲了可以支持 斷點續傳,咱們引入 confirmed_decree。replica 按期向 meta 彙報當前進度(如 confirmed_decree = 5001),一旦meta將該進度持久化至 zookeeper,當replica故障恢復時便可安全地從 5001從新開始熱備份。

因此當 B 重放某條 duplicate_rpc 時,發現其 cluster_id = 1,識別到這是一條發自 A 的熱備寫,則不會將它再發往 A。

原文出處:https://www.cnblogs.com/zjxu97/p/12078390.html

相關文章
相關標籤/搜索