MongoDB分布式原理以及read-preference和readConcern解决读写一致性问题
MongoDB詞匯表:
https://docs.mongodb.com/manual/reference/glossary/#term-replica-set
?
MongoDB分布式原理
primary
In a?replica set, the primary is the member that receives all write operations. See?Primary.
在副本集中,主庫是接收所有寫操作的節點。
secondary
A?replica set?member that replicates the contents of the master database. Secondary members may handle read requests, but only the?primary?members can handle write operations. See?Secondaries.
一個副本集,其復制所述主數據庫中的內容。次節點:讀請求。主庫:寫操作。
復制
允許多個數據庫服務器共享相同數據的功能,從而確保冗余并促進負載平衡。請參見復制。
https://docs.mongodb.com/manual/replication/#replication-auto-failover
復制提供冗余并提高?數據可用性。使用不同數據庫服務器上的多個數據副本,復制可提供一定程度的容錯能力,以防止丟失單個數據庫服務器。
在某些情況下,復制可以提供更大的讀取容量,因為客戶端可以將讀取操作發送到不同的服務器。在不同數據中心中維護數據副本可以提高數據本地性和分布式應用程序的可用性。您還可以維護其他副本以用于專用目的,例如災難恢復,報告或備份。
異步復制
輔助節點復制主節點的操作日志,并將操作異步應用于其數據集。通過使次要節點的數據集反映主要節點的數據集,即使一個或多個成員失敗,副本集也可以繼續運行。
故障轉移
在發生故障時允許副本集的輔助成員成為主庫成的過程。請參閱自動故障轉移。
如果主要節點不可用,則符合條件的次要節點將進行選舉以自行選舉新的主要節點。
自動故障轉移
時機:當主節點與集合中的其他成員的通信electionTimeoutMillis時間超過配置的時間段(默認為10秒)時。
由于突發的網絡延遲等因素,群集可能會頻繁選舉,即使該主節點處于健康狀態也是如此。
?
方式:合格的輔助節點將要求選舉以提名自己為新的主節點。群集嘗試完成新主數據庫的選擇并恢復正常操作。
?
副本集無法處理寫入操作,直到選舉成功完成。
如果將副本集配置為在主副本處于脫機狀態時在次副本上運行,則副本集可以繼續提供讀取查詢?。
應用程序連接邏輯應包括對自動故障轉移和后續選舉的容忍度。
從MongoDB 3.6開始,MongoDB驅動程序客戶端可以檢測到主數據庫的丟失,并一次自動 重試某些寫入操作,從而提供了自動故障轉移和選擇的其他內置處理。
https://docs.mongodb.com/manual/core/retryable-writes/#retryable-writes
?
選舉
副本集的成員在啟動時和發生故障時選擇主庫的過程。請參閱?副本集選擇。
https://docs.mongodb.com/manual/core/replica-set-elections/#replica-set-elections
?
最終一致性
分布式系統的屬性,允許對系統的更改逐漸傳播。在數據庫系統中,這意味著不需要可讀成員始終反映最新的寫入。
====================
readPreference和readConcern配合使用
-
readPreference?主要控制客戶端 Driver 從復制集的哪個節點讀取數據,這個特性可方便的實現讀寫分離、就近讀取等策略。
primary?只從 primary 節點讀數據,這個是默認設置primaryPreferred?優先從 primary 讀取,primary 不可服務,從 secondary 讀secondary?只從 scondary 節點讀數據secondaryPreferred?優先從 secondary 讀取,沒有 secondary 成員時,從 primary 讀取nearest?根據網絡距離就近讀取
-
readConcern?決定到某個讀取數據時,能讀到什么樣的數據。
local?能讀取任意數據,這個是默認設置majority?只能讀取到『成功寫入到大多數節點的數據』
========================
read-preference
官網地址:https://docs.mongodb.com/manual/core/read-preference/
讀取首選項描述了MongoDB客戶端如何將讀取操作路由到副本集的成員。
默認情況下,應用程序將其讀取操作定向到副本集中的 主要成員(即讀取首選項模式“主要”)。但是,客戶端可以指定讀取首選項,以將讀取操作發送到輔助對象。
| 讀取首選項模式 | 描述 |
|---|---|
primary | 默認模式。所有操作均從當前副本集primary讀取?。 包含讀取操作的多文檔事務必須使用讀取首選項 |
primaryPreferred | 在大多數情況下,操作從主服務器讀取,但如果不可用,則從輔助?成員讀取操作。 |
secondary | 所有操作均從副本集的輔助成員讀取。 |
secondaryPreferred | 在大多數情況下,操作會從輔助?成員讀取,但如果沒有輔助成員可用,則操作會從primary讀取。 |
nearest | 從副本集的成員讀取的操作具有最小的網絡延遲,而與成員的類型無關。 |
?
==================
readConcern
官網地址:https://docs.mongodb.com/manual/reference/read-concern/
該readConcern選項使您可以控制從副本集和副本集分片讀取的數據的一致性和隔離性。
通過有效使用寫入關注點和讀取關注點,您可以適當地調整一致性和可用性保證的級別,例如等待更強的一致性保證,或者放寬一致性要求以提供更高的可用性。
為MongoDB 3.2或更高版本更新的MongoDB驅動程序支持指定讀取關注。
?
readConcern 的是為了在于解決臟讀問題,用戶從 MongoDB 的 primary 上讀的數據并沒有同步到大多數節點,然后 primary 宕機恢復, primary節點會將未同步到大多數節點的數據回滾,導致用戶讀到了臟數據。
當指定 readConcern 級別為majority ,能保證用戶讀到的數據已經寫入到大多數節點,而這樣的數據肯定不會發生回滾,避免了臟讀的問題。
需要注意的是,readConcern 只是保證讀到的數據不會發生回滾,但并不能保證讀到的數據最新。
參考官網:
誤區:?majority并非從多節點讀取,依然是單節點讀取。
readConcern 原理
snapshot 0,1,2,3......N的狀態是committed/uncommitted
同步到大多數節點時,對應的snapshot會標記為commmited。
用戶讀取:讀最新的 commited 狀態的 snapshot,這樣就保證了讀到的數據是已經同步到大多數節點。
secondary節點在自身oplog發生變化會同步信息到primary。
primary節點統計超過半數的節點的同步信息就修改該snapshot為uncommitted->commited。
同時secondary拉取oplog的同時從primary節點得到最新一條已經同步到大多數節點的oplog,更新自身的 snapshot 狀態。
?
參考:
https://yq.aliyun.com/articles/60553
https://yq.aliyun.com/articles/663931
readConcern 主要用于跟 mongos 與 config server 的交互上
當寫入新文檔時,mongos 從config server 上獲取集合的路由表本地,如寫入shardX的文檔,則請求被路由到shardX上寫入。
mongos 從 config server 上獲取到路由表后,會緩存在本地內存,避免每次寫入/查詢都去 config server 上取表。
mongos 在寫入時,會帶上自身緩存的路由表版本,當請求到達 shard后,shard 發現 mongos 的路由表版本比自己的低,則說明路由表已經發生過更新,這時 mongos 會重新到 config server 上取最新的路由表,然后按新的路由表來寫入。
https://yq.aliyun.com/articles/58689
Mongos本身并不持久化數據,Sharded cluster所有的元數據都會存儲到Config Server,而用戶的數據則會分散存儲到各個shard。Mongos啟動后,會從config server加載元數據,開始提供服務,將用戶的請求正確路由到對應的Shard。
https://yq.aliyun.com/articles/32434
================
Read Concern?"majority"
https://docs.mongodb.com/manual/reference/read-concern-majority/index.html
考慮以下寫入三個成員副本集的操作Write0的時間軸:
注意 為了簡化,該示例假定:
Write0之前的所有寫操作已成功復制到所有成員。
Writeprev是Write0之前的上一次寫入。
Write0之后未發生其他寫操作。
然后,下表總結了在時間T具有“多數”讀取關注的讀取操作將看到的數據狀態。
?
最新數據不在大部分機器:?
?
?
臟數據:
總結
以上是生活随笔為你收集整理的MongoDB分布式原理以及read-preference和readConcern解决读写一致性问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 女人的泪是什么歌呢?
- 下一篇: Apache Hudi的写时复制和读时合