搭建: 一台机器启动多个实例


1、创建三个文件夹做为三个 MongoDB 实例的工作空间

  1. mkdir -p /myMongoDb/mongodb1
  2. mkdir -p /myMongoDb/mongodb2
  3. mkdir -p /myMongoDb/mongodb3

2、在三个工作空间下分别创建数据,日志,进程存放等目录或者文件

  1. mkdir -p /myMongoDb/mongodb1/data
  2. mkdir -p /myMongoDb/mongodb1/log
  3. mkdir -p /myMongoDb/mongodb1/pid
  4. mkdir -p /myMongoDb/mongodb2/data
  5. mkdir -p /myMongoDb/mongodb2/log
  6. mkdir -p /myMongoDb/mongodb2/pid
  7. mkdir -p /myMongoDb/mongodb3/data
  8. mkdir -p /myMongoDb/mongodb3/log
  9. mkdir -p /myMongoDb/mongodb3/pid
  10. touch /myMongoDb/mongodb1/log/mongodb.log
  11. touch /myMongoDb/mongodb2/log/mongodb.log
  12. touch /myMongoDb/mongodb3/log/mongodb.log
  13. touch /myMongoDb/mongodb1/pid/mongodb.pid
  14. touch /myMongoDb/mongodb2/pid/mongodb.pid
  15. touch /myMongoDb/mongodb3/pid/mongodb.pid

3、在每个工作空间下创建配置文件

enableMajorityReadConcern

是否开启 readConcern 的级别为 majority,默认为 false;只有开启此选项,才能在 read 操作中使用 majority

destination:

日志输出目的地,可以指定为 file 或者 syslog,表述输出到日志文件,如果不指定,则会输出到标准输出

journal

是否开启 journal 日志持久存储,journal 日志用来数据恢复,是 mongod 最基础的特性,通常用于故障恢复。64 位系统默认为 true,32 位默认为 false,建议开启,仅对 mongod 进程有效。

  1. vim /myMongoDb/mongodb[1, 2, 3]/mongodb.conf
  2. # 分别写入
  3. systemLog:
  4. destination: file
  5. logAppend: true
  6. path: /myMongoDb/mongodb[1, 2, 3]/log/mongodb.log
  7. storage:
  8. dbPath: /myMongoDb/mongodb[1, 2, 3]/data
  9. journal:
  10. enabled: true
  11. processManagement:
  12. fork: true
  13. pidFilePath: /myMongoDb/mongodb[1, 2, 3]/pid/mongodb.pid
  14. net:
  15. port: [7000, 7001, 7002]
  16. bindIp: 192.168.204.199
  17. replication:
  18. replSetName: rs0
  19. enableMajorityReadConcern: true

4、启动

  1. /usr/local/mongodb/bin/mongod -f /myMongoDb/mongodb1/mongodb.conf
  2. /usr/local/mongodb/bin/mongod -f /myMongoDb/mongodb2/mongodb.conf
  3. /usr/local/mongodb/bin/mongod -f /myMongoDb/mongodb3/mongodb.conf

客户端连接,初始化副本:

  1. mongo --host=192.168.204.199 --port=7000
  2. > rs.initiate()
  3. {
  4. "info2" : "no configuration specified. Using a default configuration for the set",
  5. "me" : "192.168.204.199:7000",
  6. "ok" : 1,
  7. "$clusterTime" : {
  8. "clusterTime" : Timestamp(1584452776, 1),
  9. "signature" : {
  10. "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
  11. "keyId" : NumberLong(0)
  12. }
  13. },
  14. "operationTime" : Timestamp(1584452776, 1)
  15. }
  16. rs0:OTHER>
  17. rs0:PRIMARY>
  18. OK为1的话 则初始化成功
  19. rs.conf() 查看副本信息

加入副本和仲裁节点

加入副本节点

rs.add("192.168.204.199:7001")

加入仲裁节点

不建议使用仲裁节点,因为一旦使用了仲裁节点,就不支持分布式事务

rs.addArb("192.168.204.199:7002")

运行测试

连接主节点

use test
db.xyj.insert({name:"猪八戒", age:28, gender:"男"});

连接副本节点

rs.slaveOk() 默认为 rs.slaveOk(true),不想复制的时候可以执行 rs.slaveOk(false)

mongo --host=192.168.204.199 --port=7001
show dbs // 会报错
rs.slaveOk() // 响应主节点
show dbs // 正常

连接仲裁节点

仲裁节点不会复制数据

mongo --host=192.168.204.199 --port=7002
rs.slaveOk()
show dbs

故障测试


副本挂掉的情况

主节点和仲裁节点不受影响,如果副本挂掉的时候主节点还写入数据,当副本重启时主会同步数据给副本

主节点挂掉的情况

执行故障转移,从节点成为主节点,仲裁节点没有被选举权(不会成为主节点),当挂掉的主节点回来了。将成为副本

主节点和仲裁节点挂掉的情况

副本还是副本,但是此时随便一个成员加入:

  • 仲裁节点加入: 副本成为主节点
  • 主节点加入:看谁的数据新,谁就是主节点

副本节点和仲裁节点挂掉的情况

主节点降级为副本

数据是如何复制的

当一个修改(增删改)操作到达主节点时,它对数据的操作经过特定的转化之后将被记录下来,这些称为oplog,

从节点通过在主节点上打开一个 tailable 游标不断获取新进入主节点的 oplog,并在自己的数据上回放。

故障转移


  • 具有投票权的节点之间两两互相发送心跳

  • 当 5 次心跳未收到则判断为节点失联

  • 如果是主节点,从节点会发起选举,选出主节点

  • 如果失联的是从节点则不会发生新的选举

  • 选举基于 RAFT 一致性算法,选举成功的必要条件是大多数投票节点存活

  • 复制集中最多可以有 50 个节点,但最多只能有 7 个投票节点

影响选举的因素

**
被选举为主节点的节点必须:

  1. 能与多数节点建立连接

  2. 具有较新的 oplog

  3. 根据配置文件的优先级