nodejs+mongoose操作mongodb副本集實例


上一篇設置mongodb副本集之后,開始使用nodejs訪問mongodb副本集:

1:創建項目     express 項目名稱    

2:npm install mongoose    安裝mongoose包

3:mongoose連接數據庫配置 (需要寫primary,讀從secondary讀取數據,需要設置讀取偏好設置)

理解MongDB驅動支持5中讀偏好模式。

讀偏好模式 描述
primary 默認模式,所有的讀操作都從當前副本集主節點
primaryPreferred 多數情況下,從主節點讀取數據,但是如果主節點不可用了,會從從節點讀取
secondary 所有讀操作都從副本集的從節點讀取
secondaryPreferred 多數情況下, 從從節點進行讀操作,但是如果從節點都不可用了,從主節點讀取
nearest 從副本集中延遲最低的成員讀取,不考慮成員的類型

 

 

 

 

 

讀偏好在通過mongos連接到分片集群時也可以使用。mongos實例在連接到集群中副本集提供的分片時遵守讀偏好。

【一般來說,不要使用secondary和secondaryPreferred來提供額外的讀能力,因為:

  • 所有的副本集大致擁有相同的寫流量,所以,從節點服務讀操作的速率大致和主節點相同。
  • 副本集是異步同步的,因此在寫操作成功到復制到從節點有一定的延遲。從從節點讀取數據返回的可能是過期的數據,從不同從節點讀取可能導致非單調讀(不同節點返回不一致的數據)。
  • 對於分片集合的查詢,對於均衡器開啟的集群,由於不完整或被終止的塊合並,從節點可能返回丟失或重復的過期數據。

分片通過增加一組機器分散讀寫操作增加了讀寫性能,這通常是增加性能更好的方法。】

 

var mongoose = require('mongoose');
mongoose.Promise = Promise;

// Promise.promisifyAll(mongoose);

var uri = 'mongodb://172.16.9.241/replSetTest,mongodb://172.16.9.240/replSetTest,mongodb://172.16.9.84/replSetTest'; 
var opts = {
db: { native_parser: true },
server: {
poolSize: 5 ,
auto_reconnect: true,
readPreference: "secondaryPreferred", //讀偏好設置
    socketOptions: {keepAlive: 1}
},
replset: { rs_name:"testrepl",
readPreference: "secondaryPreferred"} //讀偏好設置
}
//mongoose連接 global.db = mongoose.createConnection(uri,opts); mongoose.connection = global.db; db.on("error",function(err){ console.error(err); }); db.on("open",function(){ console.log("dbopen"); });

4:schema/user.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var moment = require("moment");

var schema = new Schema({
index: {type: Number, default: 0},
name: {type: String, default: ""},
age: {type: Number},
createdAt:{type:Date, default:Date.now()},
remark:{type:String,default:""}
});

var formatCreatedAt = schema.virtual('formatCreatedAt');
formatCreatedAt.get(function () {
return new moment(this.createdAt).format("YYYY-MM-DD HH:mm:ss:SSS");
});
schema.pre('save',function(next){
this.createdAt = Date.now();
next();
});
module.exports = schema;

5: 寫數據操作,每隔一秒寫入一條數據

//寫數據操作
var index=0;
function getMaxIndex() {
return new Promise(function (resolve,reject) {
user.find({},function (err, items) {
console.log(items);
var maxItem = ++items.length;
console.log("maxItem:",maxItem);
if(err){
console.log("getMaxIndex:",err);
return reject(err);
}
return resolve(maxItem);
});
})
}
function createUser(index) {
console.log("index:",index);
return new Promise(function (resolve,reject) {
var u = {
index:index,
name:'user'+index,
age:22,
remark:"測試文字" };
user.create(u,function (err,res) {
if(err){
console.error(err);
return reject(err);
}
console.log("createUser:",res);
return resolve('ok');
})

})
}
setInterval(function () {
getMaxIndex().then(createUser);
},1000);

可以測試當primary節點下線,寫數據操作會自動寫入其他選舉后的主節點

6:讀操作,不停讀出最大Index的記錄,並將操作的數據寫入文件,比對讀文件時間和寫數據的時間,算出同步時間長。

//讀數據操作
function getUserByIndex() {
user.findOne({index:nextIndex},function (err, item) {
if (err) {
console.log("getUserByIndex:", err);
}
if(item) {
console.log(JSON.stringify(item));
let str = " Index: " + item.index + " read time: " + new moment(Date.now()).format("YYYY-MM-DD HH:mm:ss:SSS")+
" write time: " + item.formatCreatedAt + "\r\n";
content += str;
++nextIndex;
//console.log("user存在的nextIndex: ", nextIndex);

}
if(nextIndex==100){
writeFile(content);
}else {
process.nextTick(getUserByIndex);
}
});
}
getUserByIndex();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM