工商銀行和華為雲牽頭,並聯合7家金融機構共同編製的《金融行業開放平臺資料庫轉型白皮書》榮獲2023年度十佳課題。 ...
本文是在ubuntu 22.03 系統版本上部署的,最低支持mongodb-6.0.4以上,所以這裡安裝mongodb7.0
1 安裝mongo
安裝方式有多種,本人是使用的第一種方式,時間也就20分鐘吧,能接受。
1.1 方法一:使用apt安裝
- S1.導入 MongoDB GPG 公鑰,用於驗證下載的軟體包的完整性,使用以下命令導入公鑰
curl -fsSL https://pgp.mongodb.com/server-7.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
具體需要導入的版本號,可以去https://www.mongodb.org/static/pgp 查詢
- S2. 創建一個 MongoDB 軟體源列表文件,該文件告訴 apt 去哪裡下載 MongoDB 軟體包。在
/etc/apt/sources.list.d/
目錄中創建一個新的文件並將以下行添加到文件中,根據你的需要更改版本號:
echo "deb [ arch=amd64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
- S3. 更新 apt 軟體包索引
sudo apt update
- S4. 現在已經配置了 MongoDB 軟體源,可以通過
apt
命令安裝 MongoDB 或更新到最新版本:
安裝最新版本,此命令包含mongodb幾乎所有的工具(本文檔採用此種方式)
sudo apt install -y mongodb-org
也可以安裝指定的版本號,且為各個工具指定統一版本號
sudo apt install mongodb-org=7.0 mongodb-org-server=7.0 mongodb-org-shell=7.0 mongodb-org-mongos=7.0 mongodb-org-tools=7.0
此種方式安裝,一是在配置GPG公鑰和apt源容易配置錯,同時,安裝的時候也非常的慢,我沒有去找國內的源,後續的朋友可以嘗試換個國內的源
成功安裝後,最後會有以下各個工具的版本信息:
Preparing to unpack .../6-mongodb-org_7.0.5_amd64.deb ...
Unpacking mongodb-org (7.0.5) ...
Setting up mongodb-mongosh (2.1.1) ...
Setting up mongodb-org-shell (7.0.5) ...
Setting up mongodb-database-tools (100.9.4) ...
Setting up mongodb-org-database-tools-extra (7.0.5) ...
Setting up mongodb-org-database (7.0.5) ...
Setting up mongodb-org-tools (7.0.5) ...
Setting up mongodb-org (7.0.5) ...
Processing triggers for man-db (2.10.2-1) ...
needrestart is being skipped since dpkg has failed
[1]+ Done sudo nohup mongod -f /mongodb/mongod-1.conf (wd: /mongodb/node1)
(wd now: /etc/apt/sources.list.d)
各個工具的介紹如下:
- mongodb-mongosh: Mongosh是MongoDB官方提供的命令行工具,用於連接和操作MongoDB資料庫。
- mongodb-org-shell: 這是MongoDB Shell的軟體包,它是一個互動式的JavaScript環境,用於執行資料庫操作和查詢。
- mongodb-database-tools: 這是MongoDB資料庫工具的軟體包,包括備份、還原、導入和導出等功能。
- mongodb-org-database-tools-extra: 這是附加的MongoDB資料庫工具軟體包,提供了更多的資料庫管理工具。
- mongodb-org-database: 這是MongoDB資料庫伺服器的軟體包,用於啟動和管理MongoDB伺服器實例。
- mongodb-org-tools: 這是MongoDB工具集的軟體包,包含了一些額外的輔助工具。
- S5.啟動mongodb
sudo systemctl start mongod.service
連接mongo
mongosh
再使用 show dbs;
查看當前預設的資料庫
- S6 設置為開機啟動
sudo systemctl enable mongod.service
1.2 方法二:下載包,直接安裝
可以從MongoDB 官網下載:https://www.mongodb.com/download-center/community/releases
- S1.選擇7.0.5 下麵的兩個包並下載:
Archive
: mongodb-linux-x86_64-ubuntu2204-7.0.5.tgzServer Package
: mongodb-org-server_7.0.5_amd64.debMongos Package
: mongodb-org-mongos_7.0.5_amd64.deb
Archive
是免安裝版本,下載後,解壓,裡面的bin下麵有各種 sh 執行文件
Server Pagekage
是伺服器的包
Mongos Package
是分片集群需要安裝的包,用於實現分片集群(Sharded Cluster)中的路由功能,因此,如果你需要使用MongoDB分片集群,就需要安裝mongos軟體包並配置mongos實例。而如果你只是想使用MongoDB資料庫,那麼只需要安裝MongoDB伺服器軟體包即可
- S2. 安裝
進入到下載的文件目錄,並執行安裝命令
sudo dpkg -i mongodb-org-server_7.0.5_amd64.deb
sudo dpkg -i mongodb-org-mongos_7.0.5_amd64.deb
- S3 mongo-shell 的安裝
由於mongodb 從6.0時代開始,不再提供 mongo-shell 的包,需要自己去下載對應的 mongodb-mongosh了。
這裡是2.1.1 對應的下載地址:mongodb-mongosh_2.1.1_amd64.deb
其它更多的mongo-shell,參見 https://github.com/mongodb-js/mongosh/releases
下載後,安裝如上一樣的
MongoDB 7.0 更新了不少的內容,具體參見 https://www.mongodb.com/docs/v7.0/release-notes/7.0/#general-changes
2 部署集群
這裡將採用3台伺服器,搭建 MongoDB 的 Sharding 集群
伺服器\mongo實例 | config | mongos | shard1(主shard) | shard2 | shard3 |
伺服器1(192.168.0.4) | 主節點 27016 | 主節點 27017 | 主節點27018 | 仲裁節點27019 | 副節點27020 |
伺服器2(192.168.0.5) | 副節點27016 | 副節點27017 | 副節點27018 | 主節點27019 | 仲裁節點27020 |
伺服器3(192.168.0.6) | 副節點27016 | 副節點27017 | 仲裁節點27018 | 副節點27019 | 主節點27020 |
分片副本集是可以不用仲裁節點的,但是考慮到仲裁節點不需要考慮讀寫請求的負載,也不涉及數據同步,只是參與主節點選舉並解決平票問題,所占用硬體資源(CPU、Memory)就小很多,這樣就能減輕伺服器壓力,同時也讓由三台伺服器搭建的集群有不錯的高可用性,掛掉任何一臺伺服器,都能正常運行
S1 在每台機器都創建以下目錄
sudo mkdir -p /data/mongodb/config/db
sudo mkdir -p /data/mongodb/config/logs
sudo mkdir -p /data/mongodb/mongos/logs
sudo mkdir -p /data/mongodb/shard1/db
sudo mkdir -p /data/mongodb/shard1/logs
sudo mkdir -p /data/mongodb/shard2/db
sudo mkdir -p /data/mongodb/shard2/logs
sudo mkdir -p /data/mongodb/shard3/db
sudo mkdir -p /data/mongodb/shard3/logs
//最後更改到feizhu到許可權
sudo chown -R feizhu:feizhu /data/
S2 再創建各個實例的配置文件
以伺服器1 為例
- config 實例的配置文件
sudo vim /data/mongodb/config/mongodb.conf
# 資料庫文件位置
dbpath=/data/mongodb/config/db
#日誌文件位置
logpath=/data/mongodb/config/logs/mongod.log
# 以追加方式寫入日誌
logappend=true
# 是否以守護進程方式運行
fork=true
bind_ip=192.168.0.1
port=27016
# 表示是一個配置伺服器
configsvr=true
#配置伺服器副本集名稱
replSet=configsvr
- mongos 實例的配置文件
sudo vim /data/mongodb/mongos/mongodb.conf
# mongos 不需要存儲數據,所以不配置此項
#dbpath=/data/mongodb/mongos/db
#日誌文件位置
logpath=/data/mongodb/mongos/logs/mongod.log
# 以追加方式寫入日誌
logappend=true
# 是否以守護進程方式運行
fork=true
bind_ip=0.0.0.0
port=27017
#配置伺服器副本集名稱
replSet=mongossvr
configdb=configsvr/192.168.0.1:27016,192.168.0.5:27016,192.168.0.6:27016
- Shard1 實例的配置文件
sudo vim /data/mongodb/shard1/mongodb.conf
# 資料庫文件位置
dbpath=/data/mongodb/shard1/db
#日誌文件位置
logpath=/data/mongodb/shard1/logs/mongod.log
# 以追加方式寫入日誌
logappend=true
# 是否以守護進程方式運行
fork=true
bind_ip=192.168.0.1
port=27018
#聲明開啟分片
shardsvr=true
#指定分片shar1的副本集名稱
replSet=shard1
- Shard2 實例的配置
shard2 和shard3實例跟shard1基本是一樣的,只需要把上面的shard路徑和埠寫對即可
sudo vim /data/mongodb/shard2/mongodb.conf
# 資料庫文件位置
dbpath=/data/mongodb/shard2/db
#日誌文件位置
logpath=/data/mongodb/shard2/logs/mongod.log
# 以追加方式寫入日誌
logappend=true
# 是否以守護進程方式運行
fork=true
bind_ip=192.168.0.1
port=27019
#聲明開啟分片
shardsvr=true
#指定分片shard2的副本集名稱
replSet=shard2
- Shard3 實例的配置
sudo vim /data/mongodb/shard3/mongodb.conf
# 資料庫文件位置
dbpath=/data/mongodb/shard3/db
#日誌文件位置
logpath=/data/mongodb/shard3/logs/mongod.log
# 以追加方式寫入日誌
logappend=true
# 是否以守護進程方式運行
fork=true
bind_ip=192.168.0.1
port=27020
#聲明開啟分片
shardsvr=true
#指定分片shard3的副本集名稱
replSet=shard3
最後將/data更改到 feizhu 許可權
sudo chown -R feizhu:feizhu /data/
S3 啟動 config server
把每台伺服器的 config server 實例啟動
mongod -f /data/mongodb/config/mongodb.conf
3台伺服器的config server都啟動後,從任意一臺伺服器登錄到主節點的config server,我們對照上面的實例部署表,伺服器1是config的主節點
mongosh --host 192.168.0.1 --port 27016
所以,登錄主節點這個config實例,然後初始化
rs.initiate()
初始化後,在回車,我們就發現已經顯示 configsvr [direct: primary]
的字樣,說明成功了,然後將另外兩個副節點加入即可
rs.add("192.168.0.5:27013")
rs.add("192.168.0.6:27013")
最後使用 rs.status()
查看一下結果,很明顯3個實例的config副本集就搭建了,接下來就是啟動 shard 實例了
S4 啟動 shard 實例
啟動 shard 實例,以啟動 shard1 為例,進入各個伺服器,分別啟動各自的shard1實例
mongod -f /data/mongodb/shard1/mongodb.conf
然後使用任意伺服器登錄到shard1主節點,我們希望shard1是以伺服器1為主節點,那麼就登錄到伺服器1的shard1實例
mongosh --host 192.168.0.1 --port 27018
登錄後,輸入以下命令,初始化
rs.initiate()
此時,就是以當前節點為主節點,再加入副節點和仲裁節點
rs.add("192.168.0.5:27018")
rs.addArb("192.168.0.6:27018")
rs.status()
查看狀態,發現已經成功了,以此方式,同等啟動shard2 和shard3,這裡就不過多描述
最後將上面的mongodb目錄,複製一份到伺服器2和伺服器3,將裡面的配置文件相應的 bind_id 改成本機的即可
S5 啟動 mongos 實例
- 配置 mongos 的配置文件,
sudo vim /data/mongodb/mongos/mongodb.conf
# mongos 不需要存儲數據,所以不配置此項
#dbpath=/data/mongodb/mongos/db
#日誌文件位置
logpath=/data/mongodb/mongos/logs/mongod.log
# 以追加方式寫入日誌
logappend=true
# 是否以守護進程方式運行
fork=true
# 允許所有IP 訪問
bind_ip=0.0.0.0
port=27017
#配置config server
configdb=configsvr/192.168.0.1:27016,192.168.0.5:27016,192.168.0.6:27016
-
啟動 mongos 實例
mongos -f /data/mongodb/mongos/mongodb.config
註意是前面是 mongos 而不是 mongod
因為我們這裡是 mongos 集群,所以需要分別在三台伺服器上都啟動
-
將 3 個shard 加入到分片集群
登錄任意一個 mongos 添加各個分片集群
use admin sh.addShard("shard1/192.168.0.1:27018,192.168.0.5:27018,192.168.0.5:27018") sh.addShard("shard2/192.168.0.5:27019,192.168.0.5:27019,192.168.0.6:27019") sh.addShard("shard3/192.168.0.1:27020,192.168.0.5:27020,192.168.0.6:27020")
然而在加入集群的時候報以下錯誤:
[direct: mongos] admin> sh.addShard("shard3/192.168.0.1:27020,192.168.0.5:27020,192.168.0.6:27020") MongoServerError: Cannot add shard3/192.168.0.1:27020,192.168.0.5:27020,192.168.0.6:27020 as a shard since the implicit default write concern on this shard is set to {w : 1}, because number of arbiters in the shard's configuration caused the number of writable voting members not to be strictly more than the voting majority. Change the shard configuration or set the cluster-wide write concern using the setDefaultRWConcern command and try again.
在 mongos 實例中 我們使用命令
db.adminCommand({ "getDefaultRWConcern": 1 })
可以查看到當前mongos 預設設置的寫入安全機制defaultWriteConcern,預設是majority
(多數確認),這是mongodb5.0後開始的預設設置 ,這意味著當進行寫操作時,至少要有超過大多數的數據節點確認寫操作成功,才會返回成功的響應,目前我們是3個節點,mongo系統定義的一半節點數是 (3+1)/2=2,需要超過2,也就是至少要有3個節點寫入成功才行,但是我們設置了一個 仲裁節點,導致3個shard節點中,只有2個可寫數據的節點,怎麼也不會寫成功了,所以導致失敗解決方法,將寫入安全級別調低,使用以下命令
db.adminCommand({ "setDefaultRWConcern" : 1, "defaultWriteConcern" : { "w" : 1 }})
-
"w" : 1 只要主節點寫入成功,就直接返回成功的響應,而不管副節點的同步情況
-
"w" : majority 超過節點半數【(節點數+1)/2】寫入成功,才返回成功響應
-
"w" : 0 不等待任何節點確認寫操作,只需寫入到記憶體就返回成功,這是最低級別的寫安全級別,這個配置可以提供寫入性能,但也有一定的風險
-
"w" :
等待指定數量的節點確認寫成功
-
S6 創建 database
- 登錄到 mongos 集群中,創建 jfj 資料庫
use jfj
db.createCollection('test')
db.test.insert({"name":"tom","sex":"1"})
- 創完後,使用
sh.status()
查看,可以看到以下這樣一段
{
database: {
_id: 'jfj',
primary: 'shard1',
partitioned: false,
version: {
uuid: UUID('21e70f6b-cd5a-485a-b8d6-baa9430c2d11'),
timestamp: Timestamp({ t: 1705977864, i: 2 }),
lastMod: 1
}
},
collections: {}
}
意思是 jfj 的資料庫預設使用的主節點是 shard1,也就是一些不使用分片的集合,會落在 shard1 上,如果想更改database的主shard,可以使用以下命令更改
db.adminCommand( { movePrimary: <databaseName>, to: <newPrimaryShard> } )
// 例如以下命令,會將資料庫 jfj 挪到shard2分片副本集上
db.adminCommand( { movePrimary : "jfj", to : "shard2" } )
- 開啟分片,併為集合創建片鍵
use admin
sh.enableSharding("jfj") // mongodb7.0 不需要這一步也可以
#以"name"作為分片鍵對集合 jfj.test進行分片
sh.shardCollection("jfj.test", {"name" : "hashed"})
至此,shard集群+副本集的mongodb集群就搭建完成了,使用 mongosh --host ip --port
可以連接到mongos進行操作
後面是安全認證的,生產環境的需要配置了
登錄到mongos實例,使用以下的這段shell腳本導入數據試試
var users = [];
for (var i = 1; i <= 1000; i++) {
users.push({"id": i, "name": "jiangfj" + i});
}
db.users.insertMany(users);
3 安全認證及用戶許可權
MongoDB 社區版本的安全認證只支持 keyfile(SCRAM) 和 x.509 CA 數字證書(公私鑰),我們這裡就採用 keyfile的方式,也就是密鑰的意思,稍微簡單一些
安全認證包括兩方面:
-
集群內部認證 (Internal Authentication)
-
用於集群內的各個組件(mongos, config server, shard)之間相互訪問認證
-
也就是所有的 mongos 進程和 mongod 進程之間相互訪問認證
-
內部認證通過 keyfile 密鑰文件實現,即所有的 monogs/mongod 公用同一個keyfile文件來相互認證
-
如果集群外隨便來一個 mongod 進程,如果沒有相同的 keyfile,想加入集群,是不可能的
-
-
外部用戶訪問集群 mongos 所需的用戶認證 (User Access Controls)
- 用於外部客戶端訪問 mongos 時,所需的用戶認證,我們配置用戶名+密碼的方式
S1 生成keyfile
首先在伺服器上生成一個 keyfile 密鑰文件,將其填充為隨機的 512 位元組數據,可以根據需要調整文件名和大小
openssl rand -base64 512 > ./keyfile
Keyfile 的內容
feizhuguOI1434VBHZcv8m+VafAe8041IkkaZt7Ag8vytW21qkRtYkZX7b4z4SBdp
ELYVMd7wf3HKdTH85ehehZa2fuALkld9sDF3HZSDZ5cKF4t2H9d0u8r8EQmEk8RU
pNopBCTMvwPMn9ve0coMvUrSiERNTYOLxSB7hSmUNleau9E6xAriyEIw7vYUEoSJ
SPahSYn6JqrQax4tX014lT957m3tSPMnvSjgsvbTX6YsD1t25TlWimDdrnpCEk+X
oRtDIg7HGJdxX4twY8dK0IQcyouw/twE9VugTMsbdk8DCvNI6qWoTVK37zHotGLF
k/QnXkF1KXdpmN9axj+Lo0ObJ86feizhuDlAo8XQIfRR5kENAzRdvPgRGliusnWxN
CuxD2qkR9UmtBze95Ztrb+zgioEhRe8O8Go1XXYzJhZz+yC6RoFELr2XZlallpFm
+5m9pK2RgHV38lQeQcVh72py+1ukwE5F46Em801PF8JIQ50mjnq4UL512824+DOv
TE+A/2SEdjLxUau9HuiSQ1R2zocyXIV1DCGcCqYq1qD/o1BH1STd8md+UCDMdAWY
E91kQUnf9ygiLxHCFAZUwYKlWzYfIX+UvMBp/sxyjwFldV33fCYXkRUKjE3ZlLvh
6bPrELnjy27YMSgoCGXaeP2+XaW5ZtzwJMGMBLfeizhu=
為了確保文件的安全性,設置只有 feizhu 用戶可讀寫
chmod 600 keyfile
將上面的 keyfile 文件複製到每個實例的目錄中,或者複製到每台伺服器上去,一臺伺服器都走同一個keyfile文件即可
S2 添加超級管理員用戶
連接任意一個 mongos 創建超級管理員 root
use admin;
db.createUser({user:"root",pwd:'password',roles:[{"role":"root","db":"admin"}]});
在
mongos
上添加的用戶,用戶信息實際保存在config server
上,mongos
本身不存儲任何數據,包括用戶信息
同時,
mongos
上創建的用戶,也不會自動添加到各個shard
分片伺服器上的,不管是主節點還是副節點都沒有
所以,為了以後方便維護shard
各個分片集群,分別登錄到每個分片伺服器的primary
節點,添加 root 用戶
use admin
db.createUser({user:"root",pwd:'password',roles:[{"role":"root","db":"admin"}]});
如果前期沒有為各個shard副本集上創建root用戶,但是後續又想用,就需要關閉config 實例和shard實例,在改配置文件,去掉安全認證的配置,在重啟config和shard實例,在創建用戶,完之後在改回來,特別麻煩,所以先創建好root,後續想乾什麼都行
S3 配置 mongodb.conf
配置各個 mongod 實例的 mongodb.conf 文件,在最後加上安全認證的配置
#auth
auth=true
keyFile=/data/mongodb/keyfile
配置各個 mongos 實例的 mongodb.conf 文件
keyFile=/data/mongodb/keyfile
mongos 不需要 auth=true
S4 重啟實例
停止集群所有 mongod 和 mongos 的進程
最後,按照如下順序啟動所有程式
1 config 集群 > 2 shard 集群 > 3 mongos 集群
在啟動shard的時候,至少需要config2個節點起來,也就是config集群可用才行
重啟完之後,可以登錄任一mongos實例
mongosh -u root -p password 192.168.0.1:27017/admin
S5 創建 jfj 資料庫的用戶許可權
使用管理員賬號登錄到mongos,創建一個 jfj 的只讀用戶
use jfj
db.createUser({user:"feizhu",pwd:'password',roles:[{"role":"readWrite","db":"jfj"}]});
連接試試
mongosh -u feizhu -p password 192.168.0.1:27017/jfj
至此,整個shard集群就搭建好了~!~
4 其它
4.卸載MongoDB
1.停止MongoDB
sudo service mongod stop
//或者
sudo systemctl stop mongod.service
// 或者直接kill
集群的話就需要進去實例裡面執行一下命令,或者直接kill
use admin
db.shutdownServer()
2.刪除包
sudo apt-get purge mongodb-org*
3.刪除數據目錄
- 刪除MongoDB資料庫和日誌文件