MongoDB复制集入门

来源:互联网 发布:长者风靡网络的原因 编辑:程序博客网 时间:2024/06/14 07:40

MongoDB学习笔记系列博客


一,概述

MongoDB复制是将数据同步在多个服务器的过程。
复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
复制还允许您从硬件故障和服务中断中恢复数据。


二,什么是复制

  1. 保障数据的安全性
  2. 数据高可用性 (24*7)
  3. 灾难恢复
  4. 无需停机维护(如备份,重建索引,压缩)
  5. 分布式读取数据

三,MongoDB复制原理

mongodb的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
mongodb各个节点常见的搭配方式为:一主一从、一主多从。

MongoDB复制结构图如下所示:
这里写图片描述
以上结构图总,客户端总主节点读取数据,在客户端写入数据到主节点是, 主节点与从节点进行数据交互保障数据的一致性。

复制集特征

  1. N 个节点的集群
  2. 任何节点可作为主节点
  3. 所有写入操作都在主节点上
  4. 自动故障转移
  5. 自动恢复

四,部署复制集

这里使用Windows平台部署,基于MongoDB 3.4版本。

创建复制集中每个节点存放数据的目录。
D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_0
D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_1
D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_2

创建复制集中每个节点的日志文件。
D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_0.conf
D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_1.conf
D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_2.conf

创建复制集中的每个节点启动时所需的配置文件。

dbpath = D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_0logpath = D:\MongoDB\Server\3.4\data\db_rs0\data\logs\rs0_0.logjournal = trueport = 40000replSet = rs0

文件中dbpath指向数据库数据文件存放的路径(第1步中已经创建好),logpath指向数据库的日志文件路径(第2步中已创建好),journal表示对于此mongod实例是否启动日志功能,port为实例监听的端口号,rs0为实例所在的复制集名称,更多参数意思可以参考MongoDB手册。

第二个节点配置文件为D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_1.conf,内容如下所示。

dbpath = D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_1logpath = D:\MongoDB\Server\3.4\data\db_rs0\data\logs\rs0_1.logjournal = trueport = 40001replSet = rs0

第三个节点配置文件为D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_2.conf,内容如下所示。

dbpath = D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_2logpath = D:\MongoDB\Server\3.4\data\db_rs0\data\logs\rs0_2.logjournal = trueport = 40002replSet = rs0

启动上三个节点对应的MongoDB实例。

mongod -config D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_0.confmongod -config D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_1.confmongod -config D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_2.conf

现在已经启动了3个实例,但是复制集还没配置好,如上图所描述的那样,我们应该通过配置确定哪个节点为primary,哪个节点为secondary。

启动一个mongo客户端,连接到上面的一个mongod实例。

mongo -port 40000

结果:
这里写图片描述
这个时候的复制集只有刚才这个初始化的成员,通过如下命令查看。

rs.conf()

结果:
这里写图片描述
按照MongoDB的默认设置,刚才执行初始化命令的这个mongod实例将成为复制集中的primary节点。

添加复制集中的secondary节点,继续在上面的mongod实例上执行如下命令。
这里写图片描述

观察整个复制集的状态信息。

rs.status()

结果为:

/* 1 */{    "set" : "rs0",//复制集的名称    "date" : ISODate("2017-06-11T09:48:41.400Z"),    "myState" : 1,//当前节点成员所在复制集中的位置,如1表示primary,2表示secondary    "term" : NumberLong(1),    "heartbeatIntervalMillis" : NumberLong(2000),    "optimes" : {        "lastCommittedOpTime" : {            "ts" : Timestamp(1497174514, 1),            "t" : NumberLong(1)        },        "appliedOpTime" : {            "ts" : Timestamp(1497174514, 1),            "t" : NumberLong(1)        },        "durableOpTime" : {            "ts" : Timestamp(1497174514, 1),            "t" : NumberLong(1)        }    },    "members" : [ //复制集的所有成员信息        {            "_id" : 0,//成员编号            "name" : "VICTOR-PC:40000",//成员所在的服务器名称            "health" : 1.0,//成员在复制集中是否运行,1表示运行,0表示失败            "state" : 1,//成员在复制集中的状态,1是primary            "stateStr" : "PRIMARY",//成员在复制集中的状态名称            "uptime" : 1259,//成员的在线时间,单位是秒            "optime" : {                "ts" : Timestamp(1497174514, 1),                "t" : NumberLong(1)            },            "optimeDate" : ISODate("2017-06-11T09:48:34.000Z"),            "electionTime" : Timestamp(1497173622, 1),            "electionDate" : ISODate("2017-06-11T09:33:42.000Z"),            "configVersion" : 3,            "self" : true//成员为当前命令所在的服务器        },         {            "_id" : 1,            "name" : "VICTOR-PC:40001",            "health" : 1.0,            "state" : 2,//成员所在复制集中的状态,2是secondary            "stateStr" : "SECONDARY",            "uptime" : 119,            "optime" : {                "ts" : Timestamp(1497174514, 1),                "t" : NumberLong(1)            },            "optimeDurable" : {                "ts" : Timestamp(1497174514, 1),                "t" : NumberLong(1)            },            "optimeDate" : ISODate("2017-06-11T09:48:34.000Z"),            "optimeDurableDate" : ISODate("2017-06-11T09:48:34.000Z"),            "lastHeartbeat" : ISODate("2017-06-11T09:48:41.231Z"),            "lastHeartbeatRecv" : ISODate("2017-06-11T09:48:40.686Z"),            "pingMs" : NumberLong(0),//此远端成员到本实例间一个路由包的来回时间            "syncingTo" : "VICTOR-PC:40000",//此成员需要从哪个实例同步数据            "configVersion" : 3        },         {            "_id" : 2,            "name" : "VICTOR-PC:40002",            "health" : 1.0,            "state" : 2,            "stateStr" : "SECONDARY",            "uptime" : 106,            "optime" : {                "ts" : Timestamp(1497174514, 1),                "t" : NumberLong(1)            },            "optimeDurable" : {                "ts" : Timestamp(1497174514, 1),                "t" : NumberLong(1)            },            "optimeDate" : ISODate("2017-06-11T09:48:34.000Z"),            "optimeDurableDate" : ISODate("2017-06-11T09:48:34.000Z"),            "lastHeartbeat" : ISODate("2017-06-11T09:48:41.231Z"),            "lastHeartbeatRecv" : ISODate("2017-06-11T09:48:39.968Z"),            "pingMs" : NumberLong(0),            "syncingTo" : "VICTOR-PC:40001",            "configVersion" : 3        }    ],    "ok" : 1.0}

上面复制集状态信息的输出是基于primary实例的,也可以在secondary实例上输出复制集的状态信息,包含的字段与上面大致相同。


五,移除复制集节点

这里提供两个移除复制集节点的方法。

使用 rs.remove() 来移除节点

  • 关闭我们想要移除的 mongod 实例,可以通过在 mongo -port 端口号 连接要移除的mongod实例,执行 db.shutdownServer() 来关闭。
  • 连接到复制集现在的 primary的mongod实例。我们可以连接到任意一个复制集节点并执行 db.isMaster() 来确认是否为主节点。
  • 通过 rs.remove() 来移除节点。

我们以上面创建的复制集为例,删除40002端口的节点。
连接要移除的节点
这里写图片描述
连接primary节点
这里写图片描述

通过 rs.reconfig() 来移除节点

  • 关闭我们想要移除的 mongod 实例,可以通过在 mongo -port 端口号 连接要移除的mongod实例,执行 db.shutdownServer() 来关闭。
  • 连接到复制集现在的 primary的mongod实例。我们可以连接到任意一个复制集节点并执行 db.isMaster() 来确认是否为主节点。
  • 使用 rs.conf() 来查看现在的复制集配置,并记住我们需要移除的节点的 members 数组的位置。
>rs.conf()/* 1 */{    "_id" : "rs0",    "version" : 5,    "protocolVersion" : NumberLong(1),    "members" : [         {            "_id" : 0,            "host" : "VICTOR-PC:40000",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        },         {            "_id" : 1,            "host" : "VICTOR-PC:40001",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        },         {            "_id" : 2,            "host" : "VICTOR-PC:40002",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        }    ],    "settings" : {        "chainingAllowed" : true,        "heartbeatIntervalMillis" : 2000,        "heartbeatTimeoutSecs" : 10,        "electionTimeoutMillis" : 10000,        "catchUpTimeoutMillis" : 2000,        "getLastErrorModes" : {},        "getLastErrorDefaults" : {            "w" : 1,            "wtimeout" : 0        },        "replicaSetId" : ObjectId("593d1c42196120213b965f1f")    }}
  • 将现在的的配置赋值给 cfg。
cfg = rs.conf()
  • 修改 cfg 来移除节点。
//移除VICTOR-PC:40002节点cfg.members.splice(2,1)
  • 通过如下命令将新的配置覆盖应用在复制集用。
rs.reconfig(cfg)
  • 通过 rs.conf() 命令来再确认新的配置。
/* 1 */{    "_id" : "rs0",    "version" : 6,    "protocolVersion" : NumberLong(1),    "members" : [         {            "_id" : 0,            "host" : "VICTOR-PC:40000",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        },         {            "_id" : 1,            "host" : "VICTOR-PC:40001",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        }    ],    "settings" : {        "chainingAllowed" : true,        "heartbeatIntervalMillis" : 2000,        "heartbeatTimeoutSecs" : 10,        "electionTimeoutMillis" : 10000,        "catchUpTimeoutMillis" : 2000,        "getLastErrorModes" : {},        "getLastErrorDefaults" : {            "w" : 1,            "wtimeout" : 0        },        "replicaSetId" : ObjectId("593d1c42196120213b965f1f")    }}

六,添加仲裁者节点

添加仲裁者节点跟添加普通节点思路大致相同。

创建节点存储数据的目录。
D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_3

创建节点的日志文件。
D:\MongoDB\Server\3.4\data\db_rs0\data\logs\rs0_3.log

创建节点启动时所需的配置文件。
D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_3.conf
配置文件内容

dbpath = D:\MongoDB\Server\3.4\data\db_rs0\data\rs0_3logpath = D:\MongoDB\Server\3.4\data\db_rs0\data\logs\rs0_3.logjournal = trueport = 40003replSet = rs0

启动节点的MongoDB实例

mongod -config D:\MongoDB\Server\3.4\data\db_rs0\data\configs_rs0\rs0_3.conf

primary节点加入仲裁者节点

rs.addArb("VICTOR-PC:40003")

查看效果。

>rs.conf()/* 1 */{    "_id" : "rs0",    "version" : 7,    "protocolVersion" : NumberLong(1),    "members" : [         {            "_id" : 0,            "host" : "VICTOR-PC:40000",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        },         {            "_id" : 1,            "host" : "VICTOR-PC:40001",            "arbiterOnly" : false,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        },         {            "_id" : 2,            "host" : "VICTOR-PC:40003",            "arbiterOnly" : true,            "buildIndexes" : true,            "hidden" : false,            "priority" : 1.0,            "tags" : {},            "slaveDelay" : NumberLong(0),            "votes" : 1        }    ],    "settings" : {        "chainingAllowed" : true,        "heartbeatIntervalMillis" : 2000,        "heartbeatTimeoutSecs" : 10,        "electionTimeoutMillis" : 10000,        "catchUpTimeoutMillis" : 2000,        "getLastErrorModes" : {},        "getLastErrorDefaults" : {            "w" : 1,            "wtimeout" : 0        },        "replicaSetId" : ObjectId("593d1c42196120213b965f1f")    }}

七,将单节点转为复制集

关闭 standalone mongod 实例。
重启实例,并使用 –replSet 参数来指定复制集的名字。

mongod -config 配置文件路径 --replSet rs0

剩下的步骤跟上面添加节点一致。


八,更换复制集节点

我们可以通过下列命令来将复制集的members[0]节点的主机名修改为 “VICTOR-PC:40004”

cfg = rs.conf()cfg.members[0].host = "VICTOR-PC:40004"rs.reconfig(cfg)

注意:
复制集的任何配置变动都会使 primary 降职,并进行 election 。在选举过程中,所有已经建立的链接将会释放,这将返回一个错误,及时操作执行成功了。


九,参考

更多详细内容可以参考MongoDB官文文档https://docs.mongodb.com/manual/replication/

进一步学习复制集MongoDB复制集深入(设计复制集,日志,写关注,读关注,标签)

  • http://www.runoob.com/mongodb/mongodb-replication.html
  • http://docs.mongoing.com/manual-zh/administration/replica-sets.html
  • 《大数据存储 MongoDB实战指南》