1.前言 相信說起MongoDB很多人都知道是NoSql,非關係型之類的,但是需要註意 1.和傳統關係型資料庫Sqlserver、Mysql、Oracle相比,MongoDB身為非關係型資料庫,在數據存儲結構和數據查詢以及數據海量存儲上,擁有絕對的優勢,並且可以說它與關係型資料庫是互為優缺點,互補的 ...
1.前言
相信說起MongoDB很多人都知道是NoSql,非關係型之類的,但是需要註意
1.和傳統關係型資料庫Sqlserver、Mysql、Oracle
相比,MongoDB身為非關係型資料庫,在數據存儲結構和數據查詢以及數據海量存儲上,擁有絕對的優勢,並且可以說它與關係型資料庫是互為優缺點,互補的關係,所以不要主觀
的去給它們定義`誰更好一些",在實際中可以將模式固定的結構化數據存儲在RDS,靈活的業務存儲在MongoDB中
2.雖然Redis
也是非關係型資料庫,但它和MongoDB沒有可比性,因為Redis是操作記憶體,關註的是性能,多用於緩存和系統緩衝場景,而MongoDB則是文檔型資料庫,基於存儲結構的靈活,適用於存儲一些非標準且數據結構不固定的數據,所以不要去問MongoDB
可不可以用來做緩存,選擇正確的方式做正確的事,才是最佳實踐,因為業務場景決定技術點。
2.MongoDB基本操作及安裝
1.MongoDB的安裝參考這裡,有專門記錄Linux安裝步驟,至於windows下的太簡單,就不做記錄了
2.一些常用基本的命令,更多的就不介紹了,這些可以在官方手冊中查詢學習
1.資料庫操作
//查看已有資料庫
show dbs
//1.使用資料庫
//2.查看集合
use UserDB
show collecitons
//1.刪除資料庫
//2.修複資料庫
//3.從127.0.0.1克隆一份資料庫
db.dropDatabase();
db.repairDatabase();
db.cloneDatabase("127.0.0.1");
//1.獲取資料庫狀態,可以查看集合等信息
//2.獲取當前資料庫名字
//3.客戶端連接服務端的信息
//4.查看當前服務版本
db.stats();
db.getName();
db.getMongo();
db.version();
集合操作
//1.創建一個用戶集合,最大存放1000個文檔,達到容量自動刪除舊數據
//2.查看用戶表狀態
db.createCollection("User",{"size":1024,capped:true,max:1000});
db.User.stats();
//1.查詢所有用戶數據
//2.查詢指令列
db.User.find();
db.User.find({}, {name: 1, Code: 1});
//1.查詢用戶集合id大於5的數據
//2.查詢用戶集合id小於5的數據
//3.查詢用戶集合id大於3並且小9的數據
db.User.find({id: {$gt: 5}});
db.User.find({id: {$lt: 5}});
db.User.find({id: {$gte: 3, $lte: 9}});
//1.新增一條用戶數據
//2.修改一條用戶數據
//3.刪除一條用戶數據
db.User.save({name: '特朗普', id: 1, sex: unknow,age:8});
db.User.update({age: 9}, {$set: {name: '特朗普'}}, false, true);
db.User.remove({id: 1});
MongoDBHelper
1.首先需要通過Nuget或者手動下載Mongodb在C#中的驅動MongoDB.Bson
、MongoDB.Driver
、MongoDB.Driver.Builders
2.實現簡單的增刪改查,在此僅供參考,沒有很完善所以再拷貝去用的時候需要註意
internal class MongoHelper
{
private readonly MongoDatabase _db = null;
public MongoHelper()
{
var clientServer = new MongoClient("mongodb://127.0.0.1:27017").GetServer();
this._db = clientServer.GetDatabase("UserDB");
}
public bool Insert<T>(T entity)
{
BsonDocument doc = entity.ToBsonDocument();
WriteConcernResult result = this._db.GetCollection(typeof(T).Name).Insert(entity);
return result.Ok;
}
public bool DelEntity<T>(string whereField, string whereValue)
{
var query = Query.EQ(whereField, whereValue);
WriteConcernResult result = this._db.GetCollection(typeof(T).Name).Remove(query);
return result.Ok;
}
public bool UpdateEntity<T>(string whereField, string whereValue, string updateField, string updateValue)
{
var query = Query.EQ(whereField, whereValue);
var update = Update.Set(updateField, updateValue);
WriteConcernResult result = this._db.GetCollection(typeof(T).Name).Update(query, update);
return result.Ok;
}
public T FindOne<T>(string Field, string Value)
{
T oneEntity = default(T);
FindOneArgs args = new FindOneArgs { Query = Query.EQ(Field, Value) };
oneEntity = this._db.GetCollection(typeof(T).Name).FindOneAs<T>(args);
return oneEntity;
}
}
2.MongoDB適用場景
其實對於已經瞭解過基本概念的來說,我們更想知道什麼時候使用它,怎麼發揮他的特點,既然前面說到,他和關係傳統資料庫是互補的,並且擁有存儲不規則數據的絕對優勢,那麼我們可以擴展出對業務數據的解耦,例如存儲需要查詢不同系統的高併發數據,將他們組合起來存儲在MongoDB,避免使用時跨庫跨服務查詢以節約性能,具體如下
1.在我們的員工管理系統中,我們有3個不同的微服務,考勤、申請、以及用戶服務,員工的考勤信息與申請服務掛鉤,實際情況下一個微服務對應的數據表很多個,每天需要統計考勤信息,那麼就需要調用3個不同的服務以及多個庫表之間的連接,用於組合出需要的數據,此時我們可以利用,數據異構
工具,例如DataX
、Canal
、Kettle
等,在後臺將數據組合存儲到MondoDB,方便查詢,以緩解防止集中訪問時對伺服器的壓力
2.用戶系統中線上運行的服務會產生大量的運行及訪問日誌,日誌里會包含一些錯誤、警告、及用戶行為等信息,通常服務會以文本的形式記錄日誌信息,這樣可讀性強,方便於日常定位問題,但當產生大量的日誌之後,要想從大量日誌里挖掘出有價值的內容,則需要對數據進行進一步的存儲和分析。
3.項目初期資料庫結構不穩定的情況下,這時不確定哪些表會有改變,可以使用Mongodb,例如一個表存儲系統不同類型的數據, 某一天需求變更需要為某一個類型增加欄位,對於動態存儲,這時使用Mongodb就體現了優勢所在
3.MongoDB架構設計
MongoDB分為3個大的核心模塊,分別為MongoDB query Language
、MongoDB Data Model
、查詢引擎
,首先將客戶端請求通過MongoDB query Language
轉換為MongoDB可識別的語句命令,再通過MongoDB Data Model
轉換為Bson文檔,最終交給存儲引擎將數據存儲或讀取。
1.Wiredtiger引擎寫入原理
當數據給到MongoDB 引擎後,首先寫入內部緩存,然後將緩存數據同步磁碟,為防止在緩存寫入磁碟數據丟失,MongoDB 採用雙寫的策略,在寫入緩存的同時,利用journaling buffer
來存儲數據的日誌信息到journal
文件中
1.journaling buffer
是用於存放 mongodb 增刪改 指令的緩衝區
2.journal
文件類似於關係資料庫中的事務日誌
2.索引與查詢
1.單個索引
每個索引對應文檔中的單個值,預設索引在id上
2.複合索引
可以在查詢中使用多個索引,查詢數據,如果經常查詢多個欄位,我們可以使用建立複合索引來提升性能,但是需要註意複合索引的順序非常重要,大範圍在前小範圍在後
3.如果索引太多,插入更新數據會導致索引的重排,所以可以根據自身系統監控查詢的欄位,將查詢較多的設為索引鍵
4.索引在記憶體中大概占據4kb的大小,並且是非聚集的
4.MongoDB複製集
在上面介紹中,我們使用的是一臺伺服器,一個mongod
服務進程.如果單純的做學習和開發是完全可以承載的,但是在生產環境中,風險會增高,如果伺服器宕機或者故障導致資料庫有一段時間不可訪問,而使用mongodb的複製功能來將數據副本保存在多台伺服器上,即使一臺伺服器出錯,也可以保證程式正常運行和數據安全,在實際落地中實現MongoDB高可用
方案主從複製
建議最少3個節點,一個主節點用於讀寫
,2個從節點用於同步主節點數據
在主節點故障時保證可以提供服務。
1.集群搭建
1.在MongoDB中創建多個配置文件,數據
和日誌
需要創建實例自己獨立的文件夾,埠
需要設置為不同,或者拷貝3個mongodb文件作為獨立文件,然後獨立啟動
#複製三份配置文件
# Where and how to store data.
storage:
dbPath: /usr/local/mongodb/mongoserver/data/27017data #數據文件存放目錄
journal:
enabled: true
systemLog:
destination: file
logAppend: true
path: /usr/local/mongodb/mongoserver/log/mongodb27017.log
# network interfaces
net:
port: 27017 #27018 #27019
bindIp: 127.0.0.1
replication:
replSetName: rs0 #複製集名稱,多個配置寫一樣的
2.根據配置啟動不同埠的3個不同實例
./mongod -f mongo27017.conf
./mongod -f mongo27018.conf
./mongod -f mongo27019.conf
3.使用客戶端連接,然後使用rs.initiate()
集群初始化
//區域網連接需要將ip設置為0.0.0.0
mongodb.exe --host 192.168.0.106 --port 27018
rs.initiate()
4.查看集群狀態rs.status()
,然後使用rs.add("192.168.0.106:27019")
向集群中添加另外2個節點
5.然後客戶端連接集群
//連接字元串
mongodb://192.168.0.106:27018,192.168.0.106:27019,192.168.0.106:27020/?readPreference=primary&ssl=false
var clientServer = new MongoClient("mongodb://192.168.0.106:27018,192.168.0.106:27019,192.168.0.106:27020").GetServer();
2.選舉機制
1.現在有27018、27019、27020 一主2從,那麼當27018主節點宕機後,在各個節點有心跳檢測
機制,如果在一定時間內,沒有回覆,那麼從節點就會觸發選舉機制
選出新的主節點
- 1.從節點首先會各自投票
vote
自己為主節點 - 2.然後向其他節點拉票,如果節點給自己投了,就不能給別人投,選舉規則過半數則為主節點,集群節點為奇數節點,偶數節點會產生腦裂,形成多個主節點
- 3.當主節點連接後,自動變為從節點