Docker快速部署Mongodb主副本集實踐指南
系列文章目錄
第一章 Mongodb的主副本集
前言
公司有項目需要滿足數(shù)據(jù)內(nèi)容不固定,Mongodb更適合此業(yè)務,但是不支持事務,于是了解到主副本集可以滿足。
一、Mongodb基礎介紹
數(shù)據(jù)庫(Database)
Mongodb 中的數(shù)據(jù)庫是一組集合(Collection)的容器,每個數(shù)據(jù)庫在文件系統(tǒng)中有獨立的文件存儲。數(shù)據(jù)庫名稱區(qū)分大小寫,通常用于邏輯隔離不同應用或模塊的數(shù)據(jù)。
集合(Collection)
集合是 Mongodb 中存儲文檔(Document)的容器,類似于關系型數(shù)據(jù)庫中的表。集合不需要預先定義結構,可以動態(tài)存儲不同格式的文檔。集合名稱同樣區(qū)分大小寫。
文檔(Document)
文檔是 Mongodb 中的數(shù)據(jù)基本單元,采用 BSON(Binary JSON)格式存儲。文檔由鍵值對組成,鍵是字符串,值可以是多種數(shù)據(jù)類型(如字符串、數(shù)字、數(shù)組、嵌套文檔等)。例如:
{
"name": "Alice",
"age": 30,
"address": {
"city": "New York",
"zip": "10001"
}
}BSON(Binary JSON)
BSON 是 JSON 的二進制編碼格式,擴展了 JSON 的數(shù)據(jù)類型(如日期、二進制數(shù)據(jù)等)。Mongodb 使用 BSON 在內(nèi)部存儲和傳輸數(shù)據(jù),支持高效查詢和索引。
_id(主鍵)
每個文檔必須包含一個唯一的 _id 字段作為主鍵。如果插入文檔時未指定 _id,Mongodb 會自動生成一個 ObjectId 類型的值。_id 字段默認建立索引。
索引(Index)
索引用于加速查詢性能,類似于關系型數(shù)據(jù)庫的索引。Mongodb 支持單字段索引、復合索引、多鍵索引(數(shù)組字段)、全文索引等。例如創(chuàng)建索引的命令:
db.collection.createIndex({ "name": 1 }) // 1表示升序,-1表示降序分片(Sharding)
分片是 Mongodb 的橫向擴展機制,將數(shù)據(jù)分散到多個分片(Shard)上。每個分片是獨立的數(shù)據(jù)庫實例,共同組成一個邏輯數(shù)據(jù)庫。分片通過分片鍵(Shard Key)路由數(shù)據(jù)。
副本集(Replica Set)
副本集是一組維護相同數(shù)據(jù)的 Mongodb 實例,提供高可用性。包含一個主節(jié)點(Primary)和多個從節(jié)點(Secondary)。主節(jié)點處理寫操作,從節(jié)點同步數(shù)據(jù)并支持讀操作。
聚合管道(Aggregation Pipeline)
聚合管道是數(shù)據(jù)處理框架,通過多個階段(Stage)對文檔進行轉換和計算。每個階段處理輸入文檔并輸出結果到下一階段。常見階段包括 $match、$group、$sort 等。
CRUD 操作
CRUD 指 Mongodb 的基本數(shù)據(jù)操作:
- Create:
insertOne()、insertMany() - Read:
find()、findOne() - Update:
updateOne()、updateMany() - Delete:
deleteOne()、deleteMany()
寫關注(Write Concern)
寫關注定義寫操作的確認級別,控制數(shù)據(jù)持久化的可靠性。例如:
db.collection.insertOne(
{ "key": "value" },
{ writeConcern: { w: "majority", j: true } } // w: 寫入節(jié)點數(shù),j: 日志持久化
)讀偏好(Read Preference)
讀偏好指定查詢請求的路由規(guī)則,允許從主節(jié)點或從節(jié)點讀取數(shù)據(jù)。選項包括 primary、secondary、nearest 等,適用于讀寫分離場景。
二、Mongodb事務
事務的基本概念
MongoDB 從 4.0 版本開始支持多文檔事務,適用于副本集;從 4.2 版本開始支持分片集群的事務。事務提供 ACID 特性,確保數(shù)據(jù)操作的原子性、一致性、隔離性和持久性。
啟用事務的前提條件
MongoDB 事務需要運行在副本集或分片集群上,單機模式不支持事務。確保 MongoDB 實例已正確配置為副本集或分片集群。
事務的使用方法
在 MongoDB 中使用事務需要通過會話(Session)來管理。以下是一個基本的事務操作示例:
const session = db.getMongo().startSession();
session.startTransaction({
readConcern: { level: "snapshot" },
writeConcern: { w: "majority" }
});
try {
const collection1 = session.getDatabase("db1").collection1;
const collection2 = session.getDatabase("db2").collection2;
collection1.insertOne({ name: "Alice" }, { session });
collection2.updateOne({ name: "Bob" }, { $set: { age: 30 } }, { session });
session.commitTransaction();
} catch (error) {
session.abortTransaction();
throw error;
} finally {
session.endSession();
}事務的隔離級別
MongoDB 提供 snapshot 隔離級別,確保事務內(nèi)讀取的數(shù)據(jù)來自同一快照。可以通過 readConcern 設置:
readConcern: { level: "snapshot" }事務的寫關注
事務中的寫操作可以通過 writeConcern 指定確認級別,通常設置為 majority 以確保數(shù)據(jù)持久性:
writeConcern: { w: "majority" }事務的注意事項
事務中的操作必須顯式指定會話(Session),否則操作不會包含在事務中。事務的執(zhí)行時間不宜過長,避免鎖競爭和性能問題。事務支持的文檔操作包括插入、更新、刪除和查詢。
事務的性能優(yōu)化
為了減少事務對性能的影響,盡量縮小事務范圍,減少事務內(nèi)的操作數(shù)量。避免在事務中執(zhí)行耗時操作,如大規(guī)模數(shù)據(jù)掃描。合理設置事務超時時間,防止長時間占用資源。
事務的錯誤處理
事務執(zhí)行過程中如果發(fā)生錯誤,必須捕獲異常并顯式調(diào)用 abortTransaction 回滾事務。確保事務結束后調(diào)用 endSession 釋放會話資源。
事務的限制
MongoDB 事務不支持某些操作,如創(chuàng)建或刪除集合、創(chuàng)建或刪除索引。事務內(nèi)的寫操作不能影響分片鍵的值。單個事務的文檔修改量默認限制為 16MB,超過會導致錯誤。
三、Docker部署MongoDB主副本集
環(huán)境準備
- linux服務器,內(nèi)存不少于8G,cpu至少I5,磁盤500G起步,這里我用的是CentOS7,架構是x86_64,通過如下命令確認
[root@host ~]# cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"
[root@host ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 16 On-line CPU(s) list: 0-15 Thread(s) per core: 2 Core(s) per socket: 8 座: 1 NUMA 節(jié)點: 1 廠商 ID: GenuineIntel CPU 系列: 6 型號: 165 型號名稱: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz 步進: 5 CPU MHz: 800.048 CPU max MHz: 4800.0000 CPU min MHz: 800.0000 BogoMIPS: 5800.00 虛擬化: VT-x L1d 緩存: 32K L1i 緩存: 32K L2 緩存: 256K L3 緩存: 16384K NUMA 節(jié)點0 CPU: 0-15
Docker安裝
看 歐拉系統(tǒng)部署Docker實踐指南, 參考前面部分就行。
具體安裝
- 鏡像用的是mongo最新版,可以直接拉取,也可以docker run時拉取
- 這里配置3個,做1主兩從
- 新建目錄,用于掛載存放配置文件
mkdir -p /home/mongodb && chown -R 200 /home/mongodb
- 確定主端口:27017,2個從分別是27018、27019
- 命令列表
#自定義網(wǎng)絡 docker network create --subnet=172.18.0.0/16 my-network # 查看已存在網(wǎng)絡 docker network ls # mongo容器認證啟動方式 docker run --restart=always --privileged -p 27017:27017 --name mongodbMaster --network my-network --ip 172.18.0.1 -v /home/mongo/mongoMaster/config:/data/configdb -v /home/mongo/mongoMaster/db:/data/db -v /home/mongo/mongoMaster/logs:/data/log -d mongo --replSet rs docker run --restart=always --privileged -p 27018:27017 --name mongodbSlave1 --network my-network --ip 172.18.0.2 -v /home/mongo/mongoSlave1/config:/data/configdb -v /home/mongo/mongoSlave1/db:/data/db -v /home/mongo/mongoSlave1/logs:/data/log -d mongo --replSet rs docker run --restart=always --privileged -p 27019:27017 --name mongodbSlave2 --network my-network --ip 172.18.0.3 -v /home/mongo/mongoSlave2/config:/data/configdb -v /home/mongo/mongoSlave2/db:/data/db -v /home/mongo/mongoSlave2/logs:/data/log -d mongo --replSet rs
- 執(zhí)行docker images | grep mongo, 發(fā)現(xiàn)3個容器已經(jīng)創(chuàng)建并運行
- 進入容器,創(chuàng)建賬號、授權
docker exec -it mongodbMaster /bin/bash
進入MongoDB交互式命令行并切換到admin數(shù)據(jù)庫
mongo
use admin
//管理員
db.createUser({ user: 'rwuser', pwd: 'xxxxx', roles: [ { role: "userAdminAnyDatabase", db: "admin" } ] });
db.auth('rwuser', 'xxxxx') //返回1表示認證成功
db.getCollectionNames() //所有創(chuàng)建的用戶都會存儲在system.users集合中
//factory-dev
use factory-dev //切換到目標數(shù)據(jù)庫
db.createUser({ user: 'test', pwd: 'xxxxx', roles: [ { role: "readWrite", db: "db1" } ] });
db.auth('test', 'xxxxx') //返回1表示認證成功
# 查看主節(jié)點,找到members[].stateStr:主節(jié)點應為 "PRIMARY",說明ok。
rs:PRIMARY> rs.status()
{
"set" : "rs",
"date" : ISODate("2025-09-04T00:32:31.156Z"),
"myState" : 1,
"term" : NumberLong(335),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 2,
"votingMembersCount" : 3,
"writableVotingMembersCount" : 3,
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"lastCommittedWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"appliedOpTime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"durableOpTime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"lastAppliedWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"lastDurableWallTime" : ISODate("2025-09-04T00:32:25.880Z")
},
"lastStableRecoveryTimestamp" : Timestamp(1756945915, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2025-09-03T06:59:13.712Z"),
"electionTerm" : NumberLong(335),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(1756882537, 1),
"t" : NumberLong(334)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1756882547, 1),
"t" : NumberLong(334)
},
"numVotesNeeded" : 2,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"numCatchUpOps" : NumberLong(0),
"newTermStartDate" : ISODate("2025-09-03T06:59:13.799Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2025-09-03T06:59:14.450Z")
},
"electionParticipantMetrics" : {
"votedForCandidate" : true,
"electionTerm" : NumberLong(333),
"lastVoteDate" : ISODate("2025-09-03T06:54:18.247Z"),
"electionCandidateMemberId" : 2,
"voteReason" : "",
"lastAppliedOpTimeAtElection" : {
"ts" : Timestamp(1756882339, 1),
"t" : NumberLong(331)
},
"maxAppliedOpTimeInSet" : {
"ts" : Timestamp(1756882339, 1),
"t" : NumberLong(331)
},
"priorityAtElection" : 1
},
"members" : [
{
"_id" : 0,
"name" : "f1737b1cbbc5:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 63539,
"optime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"optimeDate" : ISODate("2025-09-04T00:32:25Z"),
"lastAppliedWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"lastDurableWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1756882753, 1),
"electionDate" : ISODate("2025-09-03T06:59:13Z"),
"configVersion" : 5,
"configTerm" : 335,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "172.18.0.1:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 63207,
"optime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"optimeDurable" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"optimeDate" : ISODate("2025-09-04T00:32:25Z"),
"optimeDurableDate" : ISODate("2025-09-04T00:32:25Z"),
"lastAppliedWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"lastDurableWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"lastHeartbeat" : ISODate("2025-09-04T00:32:31.006Z"),
"lastHeartbeatRecv" : ISODate("2025-09-04T00:32:31.009Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "f1737b1cbbc5:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 5,
"configTerm" : 335
},
{
"_id" : 2,
"name" : "172.18.0.2:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 63206,
"optime" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"optimeDurable" : {
"ts" : Timestamp(1756945945, 1),
"t" : NumberLong(335)
},
"optimeDate" : ISODate("2025-09-04T00:32:25Z"),
"optimeDurableDate" : ISODate("2025-09-04T00:32:25Z"),
"lastAppliedWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"lastDurableWallTime" : ISODate("2025-09-04T00:32:25.880Z"),
"lastHeartbeat" : ISODate("2025-09-04T00:32:31.009Z"),
"lastHeartbeatRecv" : ISODate("2025-09-04T00:32:31.006Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncSourceHost" : "f1737b1cbbc5:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 5,
"configTerm" : 335
}
],
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1756945945, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1756945945, 1)
}- 一定要注意mongoDB重啟順序:docker start mongodbMaster,docker start mongodbSlave1,docker start mongodbSlave2
先啟動mongodbMaster那個就會成為PRIMARY,也是可以讀寫的,其他的都是副本集,屬于SECONDARY,只能讀
驗證
使用Navicat數(shù)據(jù)庫連接工具,點擊連接,選擇monogb

輸入ip 端口,賬號、密碼、數(shù)據(jù)庫名,這里端口填寫主端口27017,最后點擊一下"測試連接",返回OK說明配置連接成功。

右鍵新一個數(shù)據(jù)庫test

選擇集合,新建一個集合demo1

建表SQL,我這里用的是腳本執(zhí)行的
// ----------------------------
// Collection structure for autoId
// ----------------------------
db.getCollection("demo1").drop();
db.createCollection("demo1");
// ----------------------------
// Documents of autoId
// ----------------------------
db.getCollection("demo1").insert([ {
_id: "6394049da732a862951f5a62",
autoId: NumberInt("1288641"),
collectionName: "product"
} ]);
插入成功后,效果如下

事務驗證這塊,因為使用的代碼驗證的,你們只能自行用代碼驗證了,方法很簡單,開啟事務后,先執(zhí)行一個插入,再制造一個異常,比如 1/0, 看數(shù)據(jù)是否回滾。
小結
- 遇到無法寫入數(shù)據(jù)時,先進入任何一個容器
比如 docker exec -it mongodbMaster /bin/bash
mongo
rs.status();
查看
members[].stateStr:主節(jié)點應為 “PRIMARY”。
members[].health:健康節(jié)點值為 1。
若都為SECONDARY,說明還沒有確定誰是PRIMARY,先等一會再執(zhí)行看看是否有PRIMARY,有的那個就是可以連接和讀寫的容器
若一直都是SECONDARY,就要檢查容器情況了。
到此這篇關于Docker快速部署Mongodb主副本集實踐的文章就介紹到這了,更多相關Docker部署Mongodb內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
.netcore 使用surging框架發(fā)布到docker
這篇文章主要介紹了netcore 使用surging框架發(fā)布到docker,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03
docker-compose部署etcd集群的實現(xiàn)步驟
本文主要介紹了docker-compose部署etcd集群的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10
docker實踐之docker-compose部署mysql方式
這篇文章主要介紹了docker實踐之docker-compose部署mysql方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
Logshark調(diào)試Logstash及Filebeat?pipelines使用詳解
這篇文章主要為大家介紹了Logshark調(diào)試Logstash及Filebeat?pipelines使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12
Dockerfile與.gitlab-ci.yml的關系以及構建自動化鏡像方式
GitLabCI/CDPipeline中構建Docker鏡像的步驟如下:1.了解Dockerfile和.gitlab-ci.yml之間的關系;2.定義構建Docker鏡像的階段;3.在階段中調(diào)用Dockerfile來構建鏡像2024-11-11

