MongoDB readConcern 原理解析
摘要: MongoDB 可以通過 writeConcern 來定製寫策略,3.2版本後又引入了 readConcern 來靈活的定製讀策略。 readConcern vs readPreference MongoDB 控制讀策略,還有一個 readPreference 的設定,為了避免混淆,先簡單說明下
MongoDB 可以通過 writeConcern 來定製寫策略,3.2版本後又引入了 readConcern
來靈活的定製讀策略。
readConcern vs readPreference
MongoDB 控制讀策略,還有一個 readPreference
的設定,為了避免混淆,先簡單說明下二者的區別。
-
readPreference 主要控制客戶端 Driver 從複製集的哪個節點讀取資料,這個特性可方便的實現讀寫分離、就近讀取等策略。
primary
只從 primary 節點讀資料,這個是預設設定primaryPreferred
優先從 primary 讀取,primary 不可服務,從 secondary 讀secondary
只從 scondary 節點讀資料secondaryPreferred
優先從 secondary 讀取,沒有 secondary 成員時,從 primary 讀取nearest
根據網路距離就近讀取
-
local
能讀取任意資料,這個是預設設定majority
只能讀取到『成功寫入到大多數節點的資料』
readPreference
和 readConcern
可以配合使用。
readConcern 解決什麼問題?
readConcern
的初衷在於解決『髒讀』的問題,比如使用者從 MongoDB 的 primary 上讀取了某一條資料,但這條資料並沒有同步到大多數節點,然後 primary 就故障了,重新恢復後 這個primary 節點會將未同步到大多數節點的資料回滾掉,導致使用者讀到了『髒資料』。
當指定 readConcern 級別為 majority 時,能保證使用者讀到的資料『已經寫入到大多數節點』,而這樣的資料肯定不會發生回滾,避免了髒讀的問題。
需要注意的是,readConcern
能保證讀到的資料『不會發生回滾』,但並不能保證讀到的資料是最新的,這個官網上也有說明。
Regardless of the read concern level, the most recent data on a node may not reflect the most recent version of the data in the system.
有使用者誤以為,readConcern
指定為 majority 時,客戶端會從大多數的節點讀取資料,然後返回最新的資料。
實際上並不是這樣,無論何種級別的 readConcern
,客戶端都只會從『某一個確定的節點』(具體是哪個節點由 readPreference 決定)讀取資料,該節點根據自己看到的同步狀態檢視,只會返回已經同步到大多數節點的資料。
readConcern 實現原理
MongoDB 要支援 majority 的 readConcern 級別,必須設定replication.enableMajorityReadConcern
引數,加上這個引數後,MongoDB 會起一個單獨的snapshot 執行緒,會週期性的對當前的資料集進行 snapshot,並記錄 snapshot 時最新 oplog的時間戳,得到一個對映表。
最新 oplog 時間戳 | snapshot | 狀態 |
---|---|---|
t0 | snapshot0 | committed |
t1 | snapshot1 | uncommitted |
t2 | snapshot2 | uncommitted |
t3 | snapshot3 | uncommitted |
只有確保 oplog 已經同步到大多數節點時,對應的 snapshot 才會標記為 commmited,使用者讀取時,從最新的 commited 狀態的 snapshot 讀取資料,就能保證讀到的資料一定已經同步到的大多數節點。
關鍵的問題就是如何確定『oplog 已經同步到大多數節點』?
primary 節點
secondary 節點在 自身oplog發生變化時,會通過 replSetUpdatePosition 命令來將 oplog 進度立即通知給 primary,另外心跳的訊息裡也會包含最新 oplog 的資訊;通過上述方式,primary 節點能很快知道 oplog 同步情況,知道『最新一條已經同步到大多數節點的 oplog』,並更新 snapshot 的狀態。比如當t2已經寫入到大多資料節點時,snapshot1、snapshot2都可以更新為 commited 狀態。(不必要的 snapshot也會定期被清理掉)
secondary 節點
secondary 節點拉取 oplog 時,primary 節點會將『最新一條已經同步到大多數節點的 oplog』的資訊返回給 secondary 節點,secondary 節點通過這個oplog時間戳來更新自身的 snapshot 狀態。
注意事項
- 目前
readConcern
主要用於跟 mongos 與 config server 的互動上,參考MongoDB Sharded Cluster 路由策略 - 使用
readConcern
需要配置replication.enableMajorityReadConcern
選項 - 只有支援 readCommited 隔離級別的儲存引擎才能支援
readConcern
,比如 wiredtiger 引擎,而 mmapv1引擎則不能支援。
本文為雲棲社群原創內容,未經允許不得轉載,如需轉載請傳送郵件至[email protected];如果您發現本社群中有涉嫌抄襲的內容,歡迎傳送郵件至:[email protected] 進行舉報,並提供相關證據,一經查實,本社群將立刻刪除涉嫌侵權內容。
【雲棲快訊】誠邀您免費學習【阿里雲總監課】!首次集齊12位阿里雲技術高管,從理論到實踐傾囊相授,還有30元代金券,戳鏈