1. 程式人生 > 其它 >MongoDB入門實戰教程(11)

MongoDB入門實戰教程(11)

前面我們學習了在MongoDB中的寫操作事務管理,本篇我們開始進入讀操作事務。本文簡單介紹了MongoDB的讀操作事務,它有兩個重要的引數 readPreference 和 readConcern,分別解決從哪裡讀取資料 和 什麼樣的資料可以被讀取 的問題。

前面我們學習了在MongoDB中的寫操作事務管理,本篇我們開始進入讀操作事務。

1 讀資料關注的兩個問題

在通過mongodb讀取資料時,我們一般需要關注兩個問題:

(1)從哪裡讀取?

(2)什麼樣的資料可以被讀取?

第一個問題,mongodb交給了 readPreference 來解決。

第二個問題,mongodb交給了 readConcern 來解決。

2 readPreference詳解

關於readPreference

readPreference 選項決定了mongodb會使用哪一個節點(primary or secondary)來滿足正在發起的讀請求。

readPreference的可選值:

(1)primary:只選擇主節點

(2)primaryPreferred:優先選擇主節點,如果主節點不可用則選擇從節點

(3)secondary:只選擇從節點

(4)secondaryPreferred:優先選擇從節點,如果從節點不可用則選擇主節點;

(5)nearest:選擇最近的節點,無論是primary 還是 secondary 角色。

readPreference適用場景

比如,在電商場景中,使用者下單後會立即跳轉到訂單詳情頁,這時候可以配置為 primary/primaryPreferred,因為這時候從節點可能還沒有獲得同步的新訂單資料。

又如,使用者查詢自己的歷史訂單記錄,這時候可以配置為 secondary/secondaryPreferred,因為這時候使用者對歷史訂單的時效性沒有太高的要求;

再如,在Report場景中,由於報表對時效性的要求並不是太高,但資源需求較大,因此可以配置為secondary,在從節點單獨處理,避免對線上使用者造成影響。

最後,在內容管理場景中,將使用者上傳的圖片分發到全世界(比如多資料中心的場景),可以配置為nearest,讓各地使用者能夠就近讀取資料。

readPreference應用實踐

在MongoShell中:

// 在讀取students集合時採用secondary策略
db.teams.find().readPref("secondary");

在.NET應用程式中:

// 通過連線字串設定全域性預設readPreference策略
mongodb://
mongo-master:27017,mongo-slave1:27017,mongo-slave2:27017/?replicaSet=testRs&readPreference=secondary // 在.NET程式碼中通過Driver設定readPreference策略 _contacts.WithReadPreference(ReadPreference.Secondary).Find(doc => true);

擴充套件:Tag

在mongodb中,readPreference只能控制某一類節點,而tag則可以將節點選擇控制到一個或多個節點。在Kubernetes中,也有tag這個概念,可以將容器部署到指定tag的一個或多個node上。

比如,一個5節點的複製,3個節點硬體較好專供服務線上客戶實時操作,2個節點硬體較低專供服務報表生成。這時,就可以給3個硬體較好的節點打tag:{purpose: "online"},給2個硬體較低的節點打tag:{purpose: "reporting"}。最後,線上應用在讀取資料時就可以指定tag是{purpose: "online"}的節點讀取,而報表應用則指定tag是{purpose: "reporting"}的節點讀取。

3 readConcern詳解

關於readConcern

readPreference 解決了從哪裡讀資料的問題,而readConcern 則用來解決什麼樣的資料可以被讀取。

readConcern 類似於傳統關係型資料庫的隔離級別,它的可選項包括:

(1)available:讀取所有可用的資料

(2)local:讀取所有可用且屬於當前分片的資料

(3)majority:讀取在大多數節點上提交完成的資料

(4)linearizable:可線性化讀取文件

(5)snapshot:讀取最近快照中的資料

可以看到,上面的可選項基本上也是遵循了關係型資料的事務隔離級別,越往下安全性越高,但是併發效能越低。

在實際應用中,和 writeConcern 一樣,我們往往會折中考慮做權衡,因此我們在readConcern的一般性場景下選擇 majority,即讀取在大多數節點上提交完成的資料。如果跟事務隔離級別對比,那majority就類似於Read Commited即提交讀。

readConcern應用實踐

在MongoShell中:

db.teams.find().readConcern("majority");

在.NET應用程式中:

// 連線字串全域性設定
mongodb://mongo-master:27017,mongo-slave1:27017,mongo-slave2:27017/?replicaSet=testRs&readConcern=majority

// 在.NET程式碼中操作Driver時設定
_contacts.WithReadConcern(ReadConcern.Majority).Find(doc => true);

writeConcern + readConcern

在某些場景中,向主節點寫入了一條資料,立即從從節點讀取這條資料,如何才能在不改變方式的前提下保證使用者能夠讀取到剛剛寫入的資料?

對於這類問題,我們也可以稱其為如何實現一個安全的讀寫分離。

這裡,我們可以使用 writeConcern + readConcern 的組合拳來實現:

db.orders.insert({ oid: 101, sku: "kiteboar", q: 1}, {writeConcern:{w: "majority”}});
db.orders.find({oid:101}).readPref("secondary").readConcern("majority");

4 總結

本文簡單介紹了MongoDB的讀操作事務,它有兩個重要的引數 readPreference 和 readConcern,分別解決從哪裡讀取資料 和 什麼樣的資料可以被讀取 的問題。

下一篇,我們會學習MongoDB的多文件事務,這是MongoDB 4.x版本的最大改進。

參考資料

唐建法,《MongoDB高手課》(極客時間)

郭遠威,《MongoDB實戰指南》(圖書)

△推薦訂閱學習

作者:周旭龍

出處:https://edisonchou.cnblogs.com

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。