Docker安装MongoDB并配置主从同步

一、Docker快速安装MongoDB并配置主从同步

主机名 IP
mongodb 192.168.6.14

1.1、创建相关目录及授权

		1.创建主节点mongodb数据及日志目录并授权
mkdir -p /usr/local/mongodb/mongodb1/data
mkdir -p /usr/local/mongodb/mongodb1/logs
chmod 777 /usr/local/mongodb/mongodb1

		2.创建从节点mongodb数据及日志目录并授权
mkdir -p /usr/local/mongodb/mongodb2/data
mkdir -p /usr/local/mongodb/mongodb2/logs
chmod 777 /usr/local/mongodb/mongodb2

		3.创建keyFile
keyFile 是一个共享的密钥文件,用于主从节点数据复制时数据主从节点交互安全性,所有复制集成员必须拥有相同的文件内容,并且权限为 600(仅所有者可读)

openssl rand -base64 750 > /usr/local/mongodb/mongodb1/mongodb-keyfile
chmod 600 /usr/local/mongodb/mongodb1/mongodb-keyfile

		4.主从节点使用同一个keyfile
cp /usr/local/mongodb/mongodb1/mongodb-keyfile /usr/local/mongodb/mongodb2
chmod 600 /usr/local/mongodb/mongodb2/mongodb-keyfile

		5.MongoDB 容器默认以 mongodb 用户运行,需确保该用户有权限访问密钥文件
chown -R 999:999 /usr/local/mongodb/mongodb1/mongodb-keyfile
chown -R 999:999 /usr/local/mongodb/mongodb2/mongodb-keyfile

1.2、下载并运行MongoDB容器

docker pull mongo:latest

# 或使用国内镜像
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mongo:latest

运行mongoDB主节点容器

docker run -d \
  --name mongodb1 \
  -p 27017:27017 \
  -v /usr/local/mongodb/mongodb1/data:/data/db \
  -v /usr/local/mongodb/mongodb1/logs:/var/log/mongodb \
  -v /etc/localtime:/etc/localtime:ro \
  -v /usr/local/mongodb/mongodb1/mongodb-keyfile:/keyfile \
  -e MONGO_INITDB_ROOT_USERNAME=root \
  -e MONGO_INITDB_ROOT_PASSWORD="123456" \
  -e MONGO_BIND_IP=0.0.0.0 \
  --restart=always \
  --privileged \
  mongo:latest \
  --replSet rs0 \
  --keyFile /keyfile \
  --auth
  
# 参数解释
-v /usr/local/mongodb/mongodb1/mongodb-keyfile:/keyfile   # 复制 keyfile 文件(用于副本集认证)
-e MONGO_INITDB_ROOT_USERNAME=root       # 初始化 MongoDB 的 root 用户名
-e MONGO_INITDB_ROOT_PASSWORD="123456"   # 初始化 MongoDB 的 root 密码
--privileged                             # 提升容器权限(一般用不到,但这里加上了)
--replSet rs0                            # 启用副本集模式,名称为 rs0
--keyFile /keyfile                       # 启用副本集 keyfile 认证,所有副本集成员用同一个 keyfile
--auth                                    # 开启用户名/密码认证

运行从节点容器

docker run -d \
  --name mongodb2 \
  -p 37017:27017 \
  -v /usr/local/mongodb/mongodb2/data:/data/db \
  -v /usr/local/mongodb/mongodb2/logs:/var/log/mongodb \
  -v /etc/localtime:/etc/localtime:ro \
  -v /usr/local/mongodb/mongodb2/mongodb-keyfile:/keyfile \
  -e MONGO_INITDB_ROOT_USERNAME=root \
  -e MONGO_INITDB_ROOT_PASSWORD="123456" \
  -e MONGO_BIND_IP=0.0.0.0 \
  --restart=always \
  --privileged \
  mongo:latest \
  --replSet rs0 \
  --keyFile /keyfile \
  --auth

1.3、配置主从复制

通过mongosh登录mongodb1(主节点

docker exec -it mongodb1 mongosh -u root -p '123456' --authenticationDatabase admin

图片

  • 切换到admin库

use admin

  • 始化复制集
rs.initiate({
     _id: "rs0",
     members: [
       { _id: 0, host: "192.168.6.14:27017", priority: 1 },
       { _id: 1, host: "192.168.6.14:37017", priority: 0.5 }
     ]
   });

图片

  • priority 参数用于控制节点在选举(election)过程中成为 Primary(主节点) 的优先级,priority=0则仅作为从节点(长用于同步数据); priority: 1, votes: 0 则 无投票权,仅备份

  • 检查复制集状态

  • 确保所有成员状态为 PRIMARY/SECONDARY(配置均设置0,表示暂停主从复制,实际使用主节点设置1、从节点设置0即可)
    rs.status()

rs0 [direct: primary] admin> rs.status()
{
  set: 'rs0',
  date: ISODate('2025-08-31T14:13:06.424Z'),
  myState: 1,
  term: Long('1'),
  syncSourceHost: '',
  syncSourceId: -1,
  heartbeatIntervalMillis: Long('2000'),
  majorityVoteCount: 2,
  writeMajorityCount: 2,
  votingMembersCount: 2,
  writableVotingMembersCount: 2,
  optimes: {
    lastCommittedOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
    lastCommittedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
    readConcernMajorityOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
    appliedOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
    durableOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
    writtenOpTime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
    lastAppliedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
    lastDurableWallTime: ISODate('2025-08-31T14:12:57.783Z'),
    lastWrittenWallTime: ISODate('2025-08-31T14:12:57.783Z')
  },
  lastStableRecoveryTimestamp: Timestamp({ t: 1756649517, i: 1 }),
  electionCandidateMetrics: {
    lastElectionReason: 'electionTimeout',
    lastElectionDate: ISODate('2025-08-31T14:11:17.676Z'),
    electionTerm: Long('1'),
    lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 1756649467, i: 1 }), t: Long('-1') },
    lastSeenWrittenOpTimeAtElection: { ts: Timestamp({ t: 1756649467, i: 1 }), t: Long('-1') },
    lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1756649467, i: 1 }), t: Long('-1') },
    numVotesNeeded: 2,
    priorityAtElection: 1,
    electionTimeoutMillis: Long('10000'),
    numCatchUpOps: Long('0'),
    newTermStartDate: ISODate('2025-08-31T14:11:17.723Z'),
    wMajorityWriteAvailabilityDate: ISODate('2025-08-31T14:11:18.239Z')
  },
  members: [
    {
      _id: 0,
      name: '192.168.6.14:27017',
      health: 1,
      state: 1,
      stateStr: 'PRIMARY',
      uptime: 265,
      optime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
      optimeDate: ISODate('2025-08-31T14:12:57.000Z'),
      optimeWritten: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
      optimeWrittenDate: ISODate('2025-08-31T14:12:57.000Z'),
      lastAppliedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
      lastDurableWallTime: ISODate('2025-08-31T14:12:57.783Z'),
      lastWrittenWallTime: ISODate('2025-08-31T14:12:57.783Z'),
      syncSourceHost: '',
      syncSourceId: -1,
      infoMessage: 'Could not find member to sync from',
      electionTime: Timestamp({ t: 1756649477, i: 1 }),
      electionDate: ISODate('2025-08-31T14:11:17.000Z'),
      configVersion: 1,
      configTerm: 1,
      self: true,
      lastHeartbeatMessage: ''
    },
    {
      _id: 1,
      name: '192.168.6.14:37017',
      health: 1,
      state: 2,
      stateStr: 'SECONDARY',
      uptime: 119,
      optime: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
      optimeDurable: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
      optimeWritten: { ts: Timestamp({ t: 1756649577, i: 1 }), t: Long('1') },
      optimeDate: ISODate('2025-08-31T14:12:57.000Z'),
      optimeDurableDate: ISODate('2025-08-31T14:12:57.000Z'),
      optimeWrittenDate: ISODate('2025-08-31T14:12:57.000Z'),
      lastAppliedWallTime: ISODate('2025-08-31T14:12:57.783Z'),
      lastDurableWallTime: ISODate('2025-08-31T14:12:57.783Z'),
      lastWrittenWallTime: ISODate('2025-08-31T14:12:57.783Z'),
      lastHeartbeat: ISODate('2025-08-31T14:13:06.109Z'),
      lastHeartbeatRecv: ISODate('2025-08-31T14:13:04.916Z'),
      pingMs: Long('0'),
      lastHeartbeatMessage: '',
      syncSourceHost: '192.168.6.14:27017',
      syncSourceId: 0,
      infoMessage: '',
      configVersion: 1,
      configTerm: 1
    }
  ],
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1756649577, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('IYife0nANqmIL4/030rBbkJhLos=', 0),
      keyId: Long('7544752054250504197')
    }
  },
  operationTime: Timestamp({ t: 1756649577, i: 1 })
}
rs0 [direct: primary] admin> 

1.4、客户端远程连接

上述配置完成后,使用navicat等客户端连接工具远程连接mongodb主库

图片

navicate连接成功后创建一个账户,用于程序连接账号使用(*可选*

图片

按上述再远程连接从库,最终两个库都连接成功

图片

1.5、验证主从同步

进入mongodb主容器

docker exec -it mongodb1 mongosh -u root -p '123456' --authenticationDatabase admin
# 使用 use 命令切换到目标数据库(若不存在则会自动创建)
use test-databases
# 创建集合
db.createCollection("sys_users")
# 给集合插入数据
db.sys_users.insertOne({ name: "Alice", age: 30 });

进入mongodb从容器查看数据

docker exec -it mongodb2 mongosh -u root -p '123456' --authenticationDatabase admin

rs0 [direct: secondary] test> show dbs;
admin           188.00 KiB
config          240.00 KiB
local           444.00 KiB
test             40.00 KiB
test-databases   40.00 KiB

rs0 [direct: secondary] test> use test-databases
switched to db test-databases
rs0 [direct: secondary] test-databases> show collections
sys_users

rs0 [direct: secondary] test-databases> db.sys_users.find()
[
  { _id: ObjectId('68b45b68332dcf9d7bfe6912'), name: 'Alice', age: 30 }
]

刷新从库后,也生成了测试库、测试集合、并且插入了数据

同理,修改、删除主库的数据库、集合、数据,刷新从库,从库也会同步修改、删除主库的数据库、集合、数据

1.6、常用命令

    使用 use 命令切换到目标数据库(若不存在则创建)
use test;
    创建集合
db.createCollection("sys_users")
    给集合插入数据
db.sys_users.insertOne({ name: "Alice", age: 30,hisdate: 19981201 });
    后台创建索引(针对大数量集合,异步原理,防止数据库卡顿)
db.sys_users.createIndex({ hisdate: 1 }, { background: true });
    删除索引
db.sys_users.dropIndex("indexName")
    查询某个集合索引
db.sys_users.getIndexes();
    大数据量集合创建索引执行状态查询
db.currentOp({ "command.createIndexes": "sys_users" });
    解释sql,查看查询语句是否使用索引优化
db.sys_users.find( 
    { hisdate: { $gte: 20250101, $lte: 20250101 } }
).explain("executionStats");
    查询某个集合存储大小(单位:GB)
printjson(db.runCommand({ collstats: 'daq_result_tmp_curve' }).storageSize/(1024*1024*1024))
    mongodb资源实时监控
mongostat 是MongoDB自带的实时监控工具,每秒刷新一次关键指标,以下是几个关键指标:
cpu:CPU使用率(用户+系统),低版本可能不支持
res:MongoDB进程的物理内存(Resident Set Size)使用量
flushes:WiredTiger每秒缓存强制刷新次数(高值(如>1/s)可能表示磁盘性能不足或内存不足)
qr|qw:读/写队列长度(高值表示操作积压)
ar:活跃客户端数
docker exec mongodb1 /usr/bin/mongostat --host 192.168.6.14 --port 27017 -u root -p '123456' --authenticationDatabase admin

图片

    查询指定库每个集合文档总数和索引总数
# 切换数据库
use acquistion-system;
# 集合总数
var collectionNum=0;
# 查询指定库里集合总数和索引总数
var indexCount = db.getCollectionInfos().reduce((total, coll,collParam) => {
    # 获取当前集合的引用
    var collection = db.getCollection(coll.name);
    # 获取文档数
    var documentCount = collection.count();
    # 获取索引数
    var indexCount = collection.getIndexes().length;
    # 输出结果
    print("集合名称: " + coll.name + ", 文档数: " + documentCount + ", 索引数: " + indexCount);
        collectionNum++;
    return total + db.getCollection(coll.name).getIndexes().length;
}, 0);
print("集合总数:" + collectionNum + ";  索引总数: " + indexCount);
posted @ 2025-08-31 22:37  kennyy  阅读(19)  评论(0)    收藏  举报