目标:

  • 通过在一台机器上运行3个实例来搭建一个最简单的复制集。通过实验,学会以下三点:
  • 如果启动一个MongoDB实例;
  • 如何将3个MongoDB实例搭建成一个复制集;
  • 如何对复制集运行参数做一些常规调整和数据的操作;

1.准备


  • 安装最新的MongoDB版本;
  • 事先配置,Windows中配置好Mongo可执行文件的环境变量;Linux或Mac OS配置好PATH变量;
  • 确保有10GB以上的硬盘空间;

2.创建数据目录

  • MongoDB启动时将使用一个数据目录存放所有数据文件。
  • 将3个复制集节点创建在各自的数据目录中。
  • Linux/MacOS:
mkdir -p /data/db{1,2,3} #创建db1、db2、db3三个文件夹
  • Windows:
md c:\data\db1
md c:\data\db2
md c:\data\db3

3.创建配置文件

  • 复制集的每个mongod进程应该位于不同的服务器。
  • 现在是在一台机器上做实验,也需要运行3个进程,因此要做3个各自的配置文件。
  • 不同的端口。实验中将使用28017/28018/28019.
  • 不同的数据目录。实验中将使用:
/data/db1、2、3 
#或
c:\data\db1、2、3
  • 不同日志文件路径。实验中将使用:
/data/db1、2、3/mongod.log
#或
c:\data\db1、2、3\mongod.log

3.准备配置文件(内容)注意mongo3.0之后默认配置是yaml格式的

  • Linux/MacOS
# /data/db1/mongod.conf
systemLog:
  destination: file
  path: /data/db1/mongod.log	# log path - 改成相应的db1、2、3,操作的系统日志。
  logAppend: true
storage:
  dbPath: /data/db1	# data directory - 改成相应的db1、2、3
net:
  bindIp: 0.0.0.0 # 会在所有的网卡的地址上监听,如果没有加这个就发现在其他机器上访问不到mongo,只能在127.0.0.1上监听。
  port: 28017 # port - 改成相应的28017、28018、28019
replication: # 表示这是一个复制集,没有这个参数的话就表示是单节点。
  replSetName: rs0 # 复制集的名字(复制集设置时最少要有这一个参数)
processManagement:
  fork: true # 把这个进程跑在后台运行,在Windows上无效,在Linux/MacOS上是用得到的。
  • Windows
# c:\data\db1\mongod.conf
systemLog:
  destination: file
  path: c:\data1\mongod.log # 日志文件路径 - 改成对应
  logAppend: true
stroage:
  dbPath: c:\data\db1 # 数据目录 - 改成对应
net:
  bindIp: 0.0.0.0
  port: 28017 # 端口 - 改成对应
replication:
  replSetName: rs0
  # 注意Windows不支持fork,启动的命令需要在3个不同的窗口中执行,执行后不可关闭窗口否则进程会结束。

4.开启进程(以 MacOS 为例)


˙```shell
mongod -f db1/mongod.conf # 2、3同理
# 启动成功,输出 
# about to fork child process, waiting until server is ready for connections.
# forked process: 2024
# child process started successfully, parent exiting

# 查看一下进程
ps -ef | grep --color=auto mongod
# 输出
# 501  1978     1   0  6:35下午 ??         0:05.76 mongod -f db1/mongod.conf
# 501  2024     1   0  6:45下午 ??         0:02.84 mongod -f db2/mongod.conf
# 501  2039     1   0  6:46下午 ??         0:02.44 mongod -f db3/mongod.conf
# 501  2076  1219   0  6:51下午 ttys000    0:00.00 grep --color=auto mongod

```

5.添加复制集


方法1
add("hostname:port")
对应的删除 remove("hostname:port")
$ mongod -f db1/mongod.conf # 启动服务
$ mongo localhost:28017 # mongo --port 28017
> rs.initiate() # initiates set with default settings.
# 输出
#  {
#    "info2" : "no configuration specified. Using a default configuration for the set",
#    "me" : "appledeMacBook-Pro.local:28017",
#    "ok" : 1,
#    "$clusterTime" : {
#      "clusterTime" : Timestamp(1616986870, 1),
#      "signature" : {
#        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
#        "keyId" : NumberLong(0)
#      }
#    },
#    "operationTime" : Timestamp(1616986870, 1)
#  }
rs0:SECONDARY>
rs0:PRIMARY> rs.status() # checks repl set status.
# 输出
#  {
#    "set" : "rs0",
#    "date" : ISODate("2021-03-29T03:03:38.678Z"),
#    "myState" : 1,
#    "term" : NumberLong(1),
#    "syncingTo" : "",						# 节点同步到哪里
#    "syncSourceHost" : "",				# 节点从哪里同步
#    "syncSourceId" : -1,
#    "heartbeatIntervalMillis" : NumberLong(2000),
#    "majorityVoteCount" : 1,
#    "writeMajorityCount" : 1,
#    "optimes" : {
#      "lastCommittedOpTime" : {
#        "ts" : Timestamp(1616987013, 4),
#        "t" : NumberLong(1)
#      },
#      "lastCommittedWallTime" : ISODate("2021-03-29T03:03:33.988Z"),
#      "readConcernMajorityOpTime" : {
#        "ts" : Timestamp(1616987013, 4),
#        "t" : NumberLong(1)
#      },
#      "readConcernMajorityWallTime" : ISODate("2021-03-29T03:03:33.988Z"),
#      "appliedOpTime" : {
#        "ts" : Timestamp(1616987013, 4),
#        "t" : NumberLong(1)
#      },
#      "durableOpTime" : {
#        "ts" : Timestamp(1616987013, 4),
#        "t" : NumberLong(1)
#      },
#      "lastAppliedWallTime" : ISODate("2021-03-29T03:03:33.988Z"),
#      "lastDurableWallTime" : ISODate("2021-03-29T03:03:33.988Z")
#    },
#    "lastStableRecoveryTimestamp" : Timestamp(1616986990, 1),
#    "lastStableCheckpointTimestamp" : Timestamp(1616986990, 1),
#    "electionCandidateMetrics" : {
#      "lastElectionReason" : "electionTimeout",
#      "lastElectionDate" : ISODate("2021-03-29T03:01:10.673Z"),
#      "electionTerm" : NumberLong(1),
#      "lastCommittedOpTimeAtElection" : {
#        "ts" : Timestamp(0, 0),
#        "t" : NumberLong(-1)
#      },
#      "lastSeenOpTimeAtElection" : {
#        "ts" : Timestamp(1616986870, 1),
#        "t" : NumberLong(-1)
#      },
#      "numVotesNeeded" : 1,
#      "priorityAtElection" : 1,
#      "electionTimeoutMillis" : NumberLong(10000),
#      "newTermStartDate" : ISODate("2021-03-29T03:01:10.737Z"),
#      "wMajorityWriteAvailabilityDate" : ISODate("2021-03-29T03:01:10.763Z")
#    },
#    "members" : [						# 这个复制集的所有的成员
#      {
#        "_id" : 0,
#        "name" : "appledeMacBook-Pro.local:28017",
#        "health" : 1,
#        "state" : 1,
#        "stateStr" : "PRIMARY",
#        "uptime" : 2106,
#        "optime" : {
#          "ts" : Timestamp(1616987013, 4),
#          "t" : NumberLong(1)
#        },
#        "optimeDate" : ISODate("2021-03-29T03:03:33Z"),
#        "syncingTo" : "",
#        "syncSourceHost" : "",
#        "syncSourceId" : -1,
#        "infoMessage" : "",
#        "electionTime" : Timestamp(1616986870, 2),
#        "electionDate" : ISODate("2021-03-29T03:01:10Z"),
#        "configVersion" : 1,
#        "self" : true,
#        "lastHeartbeatMessage" : ""
#      }
#    ],
#    "ok" : 1,
#    "$clusterTime" : {
#      "clusterTime" : Timestamp(1616987013, 4),
#      "signature" : {
#        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
#        "keyId" : NumberLong(0)
#      }
#    },
#    "operationTime" : Timestamp(1616987013, 4)
#  }
rs0.PRIMARY> rs.add("HOSTNAME:28018") # 注意这里的hostname需要与第一个节点的一致。可以对比rs.status中的member数组中对第一个成员的描述。该例子中可以使用 "HOSTNAME:28018"或"appledeMacBook-Pro.local:28018" 都可以。
rs0.PRIMARY> rs.add("HOSTNAME:28019") # 注:此方式的HOSTNAME需要解析,可以打一下"hostname -f"看一下,必须有值才能用这个方法。
方法2 略
initiate({...})
直接在初始化时候给三个节点的配置
$ mongod -f db1/mongod.conf # 启动服务
$ mongo localhost:28017 # mongo --port 28017
> rs.initiate({
    _id: "rs0",
    members: [{
      _id: 0,
      host: "localhost:28017"
    }, {
      _id: 1,
      host: "localhost:28018"
    }, {
      _id: 2,
      host: "localhost:28019"
    }]
  })

6.验证复制集设置是否成功


# 主节点进行写入
$ mongo localhost:28017
rs0:PRIMARY> db.user.insert({name:"Tom",age:18})
# 输出 # WriteResult({ "nInserted" : 1 })
# 从节点进行读取
$ mongo localhost:28018
rs0.SECONDARY> db.users.find()
# 输出
#  Error: error: {
#    "operationTime" : Timestamp(1616989151, 1),
#    "ok" : 0,
#    "errmsg" : "not master and slaveOk=false",    # 不是主节点,而且禁止了在从节点上读。
#    "code" : 13435,
#    "codeName" : "NotMasterNoSlaveOk",
#    "$clusterTime" : {
#      "clusterTime" : Timestamp(1616989151, 1),
#      "signature" : {
#        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
#        "keyId" : NumberLong(0)
#      }
#    }
#  }
rs0.SECONDARY> rs.slaveOk() # 允许从节点读取
rs0.SECONDARY> db.users.find()
# 输出
# { "_id" : ObjectId("60614c9f8c58271f50318d73"), "name" : "Tom", "age" : 18 }