文章來源:Nodejs技術(shù)棧 / 原文鏈接 MongoDB 單文檔原生支持原子性,也具備事務(wù)的特性,但是我們說起事務(wù),通常是指在多文檔中的實(shí)現(xiàn),因此,MongoDB 在 4.0 版本支持了多文檔事務(wù),4.0 對(duì)應(yīng)于復(fù)制集的多表、多行,后續(xù)又在 4.2 版本支持了分片集的多表、多行事務(wù)操作。 事務(wù)四大特性
Read Concern/Write Concern/Read Preference在事務(wù)操作中會(huì)分別使用到 readConcern、writeConcern、readPreference 這幾個(gè)選項(xiàng),用于控制 Session 的行為,下面分別予以介紹。 事務(wù)和 Write Concern事務(wù)使用事務(wù)級(jí)別的 writeConcern 來提交寫操作,決定一個(gè)事務(wù)的寫入成功與否要看 writeConcern 選項(xiàng)設(shè)置了幾個(gè)節(jié)點(diǎn),默認(rèn)情況下為 1。 幾個(gè)選項(xiàng)值:
設(shè)置示例:writeConcern: { JavaScript 使用示例:
建議對(duì)于重要數(shù)據(jù)可以應(yīng)用 w:'majority' 設(shè)置,普通數(shù)據(jù) w:1 設(shè)置則可以保證性能最佳,w 設(shè)置的節(jié)點(diǎn)數(shù)越多,等待的延遲也就越大,如果 w 等于總節(jié)點(diǎn)數(shù),一旦其中某個(gè)節(jié)點(diǎn)出現(xiàn)故障就會(huì)導(dǎo)致整個(gè)寫入失敗,也是有風(fēng)險(xiǎn)的。 docs.mongodb.com/manual/reference/write-concern/?spm=a2c4e.10696291.0.0.68d519a4ob3Yya 事務(wù)和 Read Preference在一個(gè)事務(wù)操作中使用事務(wù)級(jí)別的 readPreference 來決定讀取時(shí)從哪個(gè)節(jié)點(diǎn)讀取??煞奖愕膶?shí)現(xiàn)讀寫分離、就近讀取策略。 可選值以下 5 個(gè):
場景選擇
使用示例
mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017,mongodb2.example.com:27017/admin?replicaSet=myRepl&readPreference=secondary
測試時(shí)可借助 db.fsyncUnlock() 對(duì)從節(jié)點(diǎn)鎖定,僅主節(jié)點(diǎn)寫入數(shù)據(jù)。 docs.mongodb.com/manual/core/read-preference/#replica-set-read-preference 事務(wù)和 Read ConcernMongoDB 3.2 引入了 readConcern 來決定讀取的策略,但是與 readPreference 不同,readPreference 決定從哪個(gè)節(jié)點(diǎn)讀取,readConcern 決定該節(jié)點(diǎn)的哪些數(shù)據(jù)是可讀的。主要保證事務(wù)中的隔離性,避免臟讀。 可選值
更新配置項(xiàng)在啟動(dòng) Mongod 實(shí)例時(shí),指定 --enableMajorityReadConcern 選項(xiàng)或在配置文件中配置 enableMajorityReadConcern=true 重新啟動(dòng)實(shí)例,Mongo shell 登陸實(shí)例,使用
使用示例db.user.find().readConcern('majority') readConcern 總結(jié)MongoDB 的 readConcern 默認(rèn)情況下是臟讀,例如,用戶在主節(jié)點(diǎn)讀取一條數(shù)據(jù)之后,該節(jié)點(diǎn)未將數(shù)據(jù)同步至其它從節(jié)點(diǎn),就因?yàn)楫惓斓袅?,待主?jié)點(diǎn)恢復(fù)之后,將未同步至其它節(jié)點(diǎn)的數(shù)據(jù)進(jìn)行回滾,就出現(xiàn)了臟讀。 readConcern 級(jí)別的 majority 可以保證讀到的數(shù)據(jù)已經(jīng)落入到大多數(shù)節(jié)點(diǎn)。所以說保證了事務(wù)的隔離性,所謂隔離性也是指事務(wù)內(nèi)的操作,事務(wù)外是看不見的。 readConcern 參考
讀寫分離實(shí)踐一個(gè)典型的應(yīng)用場景是用戶寫入訂單數(shù)據(jù)(數(shù)據(jù)寫入 Primary),立即調(diào)用查詢接口,由于采用讀寫分離模式,鏈接字符串設(shè)置 readPreference=secondaryPreferred 訂單寫入主節(jié)點(diǎn)之后并不能保證數(shù)據(jù)立即同步到從節(jié)點(diǎn),若此時(shí)直接由從節(jié)點(diǎn)讀取數(shù)據(jù), 偶爾會(huì)出現(xiàn)訂單數(shù)據(jù)無法找到,用戶就會(huì)感覺很奇怪,明明下了訂單,卻又查找不到,造成一些異常訂單。 一種導(dǎo)致下單之后再次查找丟失訂單的的寫法如下:
解決方法一: 設(shè)置 readPreference=primary,將復(fù)制集的節(jié)點(diǎn)讀取由從節(jié)點(diǎn)轉(zhuǎn)換為主節(jié)點(diǎn)。 這種方式一個(gè)缺點(diǎn)是數(shù)據(jù)量大了之后會(huì)增加主節(jié)點(diǎn)的壓力,也就沒有了主從分離的模式。 解決方法二: 使用 writeConcern、readConcern 組合來解決,即保證讀寫分離模式,也保證了數(shù)據(jù)的一致性。 // 寫入時(shí)保證大多數(shù)節(jié)點(diǎn)寫入成功 |
|