.NET Core+MongoDB叢集搭建與實戰
阿新 • • 發佈:2020-10-18
[TOC]
## 安裝 MongoDB
安裝 MongoDB 網上有很多教程,MongoDB 官方文件:[https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/)
筆者這裡簡單寫一下安裝過程,筆者使用 ubuntu 系統。
要按照的目標版本:MongoDB 4.4 Community Edition
支援的系統:
- 20.04 LTS (“Focal”)
- 18.04 LTS (“Bionic”)
- 16.04 LTS (“Xenial”)
更新軟體源
```shell
sudo apt update
sudo apt upgrade
```
### apt 直接安裝(方法1)
如果你要安裝穩定版本,則直接使用一條命令安裝:
```shell
sudo apt install mongodb
```
執行命令檢查 MingoDB 的狀態:
```shell
sudo systemctl status mongodb
```
### apt 倉庫安裝(方法2)
此種方式可以讓你安裝最新版本的 MongoDB 。
**匯入包管理系統使用的公鑰**
```csharp
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
```
**新增 MongoDB 的倉庫原始檔**
```csharp
/etc/apt/sources.list.d/mongodb-org-4.4.list
```
**新增 MongoDB 的倉庫源地址**
```csharp
# ubuntu 16.04
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
# ubuntu 18.04
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
# ubuntu 20.04
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
```
**載入 MongoDB 的軟體包**
```shell
sudo apt-get update
```
**安裝最新穩定版本的 MongoDB**
```shell
sudo apt-get install -y mongodb-org
```
如果你想安裝指定版本:
```shell
sudo apt-get install -y mongodb-org=4.4.1 mongodb-org-server=4.4.1 mongodb-org-shell=4.4.1 mongodb-org-mongos=4.4.1 mongodb-org-tools=4.4.1
```
### 方法1、2啟動 MongoDB
**執行命令檢查 MongoDB 的狀態**:
```shell
sudo systemctl status mongodb
```
**啟動 MongoDB**:
```shell
sudo systemctl start mongod
```
**開機啟動 MongoDB**:
```shell
sudo systemctl enable mongod
```
**檢視 MongoDB 版本**:
```shell
mongo --version
mongod --version
```
注意:由於 Linux/Unix 系統會對檔案描述符的數量或者執行緒數量加以限制,如果安裝過程或者啟動時報錯,需要自行另外查詢方法解決,這裡不再贅述。
### 通過二進位制包安裝(方法3)
適合網路不會或者離線安裝,有 `tgz`、`deb` 、`source code` 等方法安裝,這裡只使用 `tgz` 方式。
#### 安裝依賴
```shell
# ubuntu 16.04
sudo apt-get install libcurl3 openssl liblzma5
# ubuntu 18.04 & 20.04
sudo apt-get install libcurl4 openssl liblzma5
```
**選擇合適的系統下載二進位制包**:
[https://www.mongodb.com/try/download/community?tck=docs_server](https://www.mongodb.com/try/download/community?tck=docs_server)
Package 可以選擇包的形式,如 shell(deb)、shell(tgz)。
注意,要在伺服器下載的話,就不要點選 Download,而是點選 `Copy Link` 複製二進位制包的下載連結。
請注意下載的軟體版本,mongos 、tagz 包含全部功能;
其它的是單獨提供 server 或者 client(shell) 功能。
本小節將提供安裝 .deb 和 tgz 包的說明,請自行選擇要安裝的包!(建議直接下載 tgz)。
![不同種類的軟體包](https://img2020.cnblogs.com/blog/1315495/202010/1315495-20201017210808666-1071566095.png)
#### deb 安裝 MongoDB
如果下載了 .deb 檔案,請使用下面命令安裝。
```shell
wget {下載地址}
sudo dpkg -i {軟體包名}.deb
```
#### tgz 安裝 MongoDB
如果下載了 `.tar.gz` 檔案,請使用下面命令安裝。
```shell
tar -zxvf mongodb-{版本}.tgz
# 下面是示例
cd mongodb-linux-x86_64-ubuntu1604-4.4.1
... ...
|-- bin
| `-- mongo
|-- LICENSE-Community.txt
|-- MPL-2
|-- README
`-- THIRD-PARTY-NOTICES
```
開啟解壓的目錄,執行:
```shell
sudo cp bin/* /usr/local/bin/
# 實際上就是將二進位制可執行檔案放到 bin 目錄
```
#### 啟動 MongoDB
**建立資料存放目錄**:
```shell
sudo mkdir -p /var/lib/mongo
```
**建立日誌存放目錄:**
```shell
sudo mkdir -p /var/log/mongodb
```
如果不是使用 root 使用者登入,則需要獲取檔案許可權:
```shell
# whoami是你的使用者名稱
sudo chown `whoami` /var/lib/mongo
sudo chown `whoami` /var/log/mongodb
```
**執行 MongoDB:**
```shell
mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
之後終端會提示已經成功啟動;也可以檢視 `/var/log/mongodb/mongod.log` 日誌檔案中的內容確定 MongoDB 的執行情況;
`cat /var/log/mongodb/mongod.log` 日誌檔案,會發現第一行:
```shell
pid=22639 port=27017
```
port 即 MongoDB 的連線埠。
### 解除安裝方法
#### apt 解除安裝方法
適合使用 映象倉庫安裝的 MongoDB。
```shell
sudo apt-get purge mongodb mongodb-clients mongodb-server mongodb-dev
sudo apt-get purge mongodb-10gen
sudo apt-get autoremove
```
注:執行過程報錯不用管。
#### tgz 解除安裝方法
適合解除安裝使用 .tar.gz 安裝的包。
```shell
rm /usr/local/bin/mongo*
```
### 指定啟動的配置
#### 通過配置檔案
如果前面提到過配置檔案 `/etc/mongod.conf`,如果通過配置檔案啟動,則會方便很多,使用配置檔案啟動 MongoDB 的方法:
```shell
mongod --config /etc/mongod.conf
```
#### 通過引數
通過引數啟動 MongoDB 的話,每次啟動都比較麻煩:
```shell
mongod --bind_ip=0.0.0.0 --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
### MongoDB 繫結IP、埠
檢視 MongoDB 配置:
```shell
# 進入 shell
mongo
# 執行
use admin
db.runCommand( { getParameter : '*' } )
```
預設 MongoDB 是本地服務,外界無法訪問主機的 MongoDB 服務,這裡來配置一下,使其能夠被外網訪問。
在 MongoDB 啟動後,執行以下命令修改配置。
```shell
# 繫結所有地址
mongod --bind_ip_all
# 修改埠
mongod --port 27017
```
或者停了 MongoDB 服務後,使用以下命令啟動:
```shell
mongod --bind_ip=0.0.0.0 --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
或者手動修改 `/etc/mongod.conf` 配置檔案,把其中一段改成 `0.0.0.0`:
```shell
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
```
修改完畢後,需要關閉 MongoDB,再開啟,請參考後面 ”停止 MongoDB“ 一節。
#### 測試遠端 IP 連線
測試連線指定 IP 和 port 的 MongoDB 服務:
```shell
mongo {你的伺服器公網IP}:27017
```
### 加上密碼驗證
#### 設定賬號密碼
```shell
mongo
# 進入 MongoDB shell 後
use admin
db.createUser({user:"admin",pwd:"123456",roles:[{role:"root",db:"admin"}]})
```
如果不生效,請自行找方法解決,這裡不再贅述~
#### 開啟登入驗證
然後開啟 `/etc/mongod.conf` 檔案,將 `#security:` 改成:
```shell
security:
authorization: enabled
```
如果不生效,請自行找方法解決,這裡不再贅述~
### 停止 MongoDB
```shell
mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --shutdown
```
## 搭建叢集
按照此方法,再炮製一臺伺服器就行。
建議使用 docker 一次性搞好,自己手動在物理機上面安裝,太折騰了。
接下來,我們要根據官方文件,搭建簡單的副本叢集。
官方文件地址:[https://docs.mongodb.com/manual/replication/](https://docs.mongodb.com/manual/replication/)
### 副本集
副本集是一組 MongoDB 例項來維護相同資料集。
官網文件解釋:一個副本集包含多個數據承載節點和一個仲裁器節點(可選)。在資料承載節點中,只有一個成員被視為主要節點,而其他節點則被視為次要節點。
用一下官方的圖:
![mongoDB副本集](https://img2020.cnblogs.com/blog/1315495/202010/1315495-20201017211004159-962848062.png)
### 故障轉移
圖中有三臺 MongoDB 例項,當 Primary 掛了後,`Secondary` 可以換掉掛了的伺服器,成為新的 Primary。
![故障轉移](https://img2020.cnblogs.com/blog/1315495/202010/1315495-20201017211023896-613602242.png)
由於我只有兩臺伺服器,因此只能組雙機熱備。
### 方案
**主節點(Primary)**
對外接收所有請求,然後將修改同步到所有 Secondary 中。
當 主節點(Primary) 掛了後,其它 Secondary 或者 Arbiter 節點就會重新選舉一個主節點出來。
**副本節點(Secondary)**
副本節點是備胎,資料集跟主節點(Primary)一致,當主節點掛了後,有機會成為正胎(Primary)。
**仲裁者(Arbiter)**
不儲存資料集,也不能成為(Primary)。作用是當主節點掛了後,投票給 Secondary,讓 Secondary 成為 Primary。
但是怎麼配置原有的 MongoDB 例項,使其成為 Primary - Secondary 叢集呢?Google 了很久。
找到 MongoDB 官方的文件:
[https://docs.mongodb.com/manual/tutorial/deploy-replica-set/](https://docs.mongodb.com/manual/tutorial/deploy-replica-set/)
### 設計例項名稱
在 primary 機器和 secondary 機器上,分別開啟 `/etc/mongod.conf` 檔案,找到 `#`replication,設定節點名稱。
```
replication:
replSetName: {名稱}
```
primary 機器設定 `primary`,secondary 機器設定 `beitai`。
replSetName 的作用解釋如下:
[https://docs.mongodb.com/manual/reference/configuration-options/#replication.replSetName](https://docs.mongodb.com/manual/reference/configuration-options/#replication.replSetName)
也可以在啟動 MongoDB 時加上 `--replSet "beitai"` 的引數。
```
mongod --replSet "beitai" ... ...
```
**請停止 MongoDB 後,使用長命令的方法啟動 MongoDB**。
請在要設定為 Primary 的機器,執行:
```
mongod --replSet "primary" --bind_ip=0.0.0.0 --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
請在要設定為 Secondary 的機器,執行:
```
mongod --replSet "beitai" --bind_ip=0.0.0.0 --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
### 如何建立叢集
必須要做到以下兩點配置:
- Add Members to a Replica Set
- Deploy a Replica Set
筆者在這裡踩了很大的坑,試了很多種方法和配置才成功。
### 啟動兩個例項(配置)
提前說明,如果使用 `rs.` 指令配置例項,想重新配置,出現 ”"errmsg" : "already initialized"“,可以使用 `rs.reconfig()` 清除配置。
```shell
rsconf = rs.conf()
rsconf.members = [{_id: 1, host: "本機的ip:27017"}]
rs.reconfig(rsconf, {force: true})
```
在 Secondary 機器,執行命令停止執行:
```shell
mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --shutdown
```
重新啟動 Secondary 機器:
```shell
mongod --replSet "beitai" --bind_ip=0.0.0.0 --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
設定為 Secondary 節點:
```json
rs.initiate(
{
_id: "beitai",
version: 1,
members: [
{ _id: 0, host : "primary的ip:27017" }
{ _id: 1, host : "secondary的ip:27017" }
]
}
)
```
注:id是優先順序。
在 primary 機器,執行命令停止執行:
```
mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --shutdown
```
重新啟動 primary:
```shell
mongod --replSet "beitai" --bind_ip=0.0.0.0 --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
```
在 primary 進入 shell:
```shell
mongo
```
執行命令進行初始化並設定自己為 primary:
```json
rs.initiate(
{
_id: "primary",
version: 1,
members: [
{ _id: 0, host : "primary的ip:27017" },
{ _id: 1, host : "secondary的ip:27017" }
]
}
)
```
分別在兩個例項開啟 mongo shell,執行:
```
rs.status()
```
發現:
```
beitai:SECONDARY>
...
primary:PRIMARY>
```
使用工具連線 MongoDB 並建立一個名為 Test 的資料庫:
![連線MongoDB](https://img2020.cnblogs.com/blog/1315495/202010/1315495-20201017211112680-9833465.png)
### 副本集狀態檢視
檢視複製延遲:
```shell
rs.printSlaveReplicationInfo()
```
執行結果:
```shell
WARNING: printSlaveReplicationInfo is deprecated and may be removed in the next major release. Please use printSecondaryReplicationInfo instead.
source: *.*.*.*:27017
syncedTo: Sat Oct 17 2020 20:02:49 GMT+0800 (CST)
0 secs (0 hrs) behind the freshest member (no primary available at the moment)
source: *.*.*.*:27017
syncedTo: Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
1602936169 secs (445260.05 hrs) behind the freshest member (no primary available at the moment)
```
## .NET Core 連線 MongoDB
.NET 程式要連線 MongoDB ,需要通過 Nuget 包安裝 `MongoDB.Driver` 驅動。
我們來建立一個控制檯程式,Nuget 搜尋 [MongoDB.Driver](http://www.nuget.org/packages/mongodb.driver) 並安裝,接下來一步步使用連線 MongoDB。
文件地址:[https://mongodb.github.io/mongo-csharp-driver/2.10/getting_started/](https://mongodb.github.io/mongo-csharp-driver/2.10/getting_started/)
新增 using 引用:
```csharp
using MongoDB.Bson;
using MongoDB.Driver;
```
連線 MongoDB
```shell
var client = new MongoClient("mongodb://primary的ip:27017,secondary的ip:27017");
```
獲取資料庫
```shell
IMongoDatabase database = client.GetDatabase("Test");
```
獲取文件集合
```shell
var collection = database.GetCollection("MyCollection");
```
插入文件(json)
```csharp
var document = new BsonDocument
{
{ "name", "MongoDB" },
{ "type", "Database" },
{ "count", 1 },
{ "info", new BsonDocument
{
{ "x", 203 },
{ "y", 102 }
}}
};
```
其源結構的 json 如下:
```json
{
"name": "MongoDB",
"type": "database",
"count": 1,
"info": {
x: 203,
y: 102
}
}
```
將文件插入到集合中:
```csharp
collection.InsertOne(document);
// 使用非同步 await collection.InsertOneAsync(document);
```
然後執行程式,一會兒後,開啟 MongoDB 管理器,檢視集合。
![](https://img2020.cnblogs.com/blog/1315495/202010/1315495-20201017211139947-12585771