MongoDB writeConcern原理解析

MongoDB支持客戶端靈活配置寫入策略(writeConcern),以滿足不同場景的需求。

db.collection.insert({x: 1}, {writeConcern: {w: 1}})

1. writeConcern選項

MongoDB支持的WriteConcern選項如下

  1. w: <number>,數據寫入到number個節點才向客戶端確認

    • {w: 0} 對客戶端的寫入不需要發送任何確認,適用於性能要求高,但不關注正確性的場景
    • {w: 1} 默認的writeConcern,數據寫入到Primary就向客戶端發送確認
    • {w: "majority"} 數據寫入到副本集大多數成員後向客戶端發送確認,適用於對數據安全性要求比較高的場景,該選項會降低寫入性能
  2. j: <boolean> ,寫入操作的journal持久化後才向客戶端確認

    默認爲"{j: false},如果要求Primary寫入持久化了才向客戶端確認,則指定該選項爲true
  3. wtimeout: <millseconds>,寫入超時時間,僅w的值大於1時有效。

    當指定{w: }時,數據需要成功寫入number個節點纔算成功,如果寫入過程中有節點故障,可能導致這個條件一直不能滿足,從而一直不能向客戶端發送確認結果,針對這種情況,客戶端可設置wtimeout選項來指定超時時間,當寫入過程持續超過該時間仍未結束,則認爲寫入失敗。

2. {w: "majority"}解析

{w: 1}、{j: true}等writeConcern選項很好理解,Primary等待條件滿足發送確認;但{w: "majority"}則相對複雜些,需要確認數據成功寫入到大多數節點纔算成功,而MongoDB的複製是通過Secondary不斷拉取oplog並重放來實現的,並不是Primary主動將寫入同步給Secondary,那麼Primary是如何確認數據已成功寫入到大多數節點的?

  1. Client向Primary發起請求,指定writeConcern爲{w: "majority"},Primary收到請求,本地寫入並記錄寫請求到oplog,然後等待大多數節點都同步了這條/批oplog(Secondary應用完oplog會向主報告最新進度)。
  2. Secondary拉取到Primary上新寫入的oplog,本地重放並記錄oplog。爲了讓Secondary能在第一時間內拉取到主上的oplog,find命令支持一個awaitData的選項,當find沒有任何符合條件的文檔時,並不立即返回,而是等待最多maxTimeMS(默認爲2s)時間看是否有新的符合條件的數據,如果有就返回;所以當新寫入oplog時,備立馬能獲取到新的oplog。
  3. Secondary上有單獨的線程,當oplog的最新時間戳發生更新時,就會向Primary發送replSetUpdatePosition命令更新自己的oplog時間戳。
  4. 當Primary發現有足夠多的節點oplog時間戳已經滿足條件了,向客戶端發送確認。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章