一:mongodb的主从架构:
简介:mongodb的主从模型分为两种:一种为副本集形式,另一种为heartbeat,
oplog:大小固定的文件,存储在local数据库
初始同步(initial sync)
回滚后追赶(post-rollback catch-up)
切分块迁移(sharding chunk migrations)
local:存放了副本集的所有元数据和oplog,用于存储oplog的是一个名为oplog.rs的collection;
oplog.rs的大小依赖于OS及文件系统,但可以自定义其大小oplogsize
[root@node1 ~]# mongod --help
Replication options: 默认大小为磁盘空间的5%
--oplogSize arg size to use (in MB) for replication op log. default is
5% of disk space (i.e. large is good)
二:mongodb的复制功能:
```cpp
两种类型:
master/slave
replica set:复制集,副本集
服务于同一个数据集的多个mongodb实列
主节点将数据修改操作保存至oplog中
三:复制集的中节点分类:
0优先级的节点;冷备节点,不会被选举成为主节点,但可以参与选举;
被隐藏的从节点:首先是一个0优先级的从节点,且对客户端不可见
延迟复制的从节点:首先是一个0优先级的从节点,且复制时间落后于主节点一个固定时长
四:主从复制的准备架构:三个节点。
节点 | ip |
---|---|
node1 | 192.168.178.128 |
node2 | 192.168.178.129 |
node3 | 192.168.178.130 |
(1)在三个节点同时安装mongodb。修改配置文件,启动mongodb。
[root@node1 ~]# yum install mongodb mongodb-server -y
[root@node2~]# yum install mongodb mongodb-server -y
[root@node3~]# yum install mongodb mongodb-server -y
[root@node1 ~]# vim /etc/mongodb.conf
bind_ip = 127.0.0.1,192.168.178.128 填写需要坚听的地址
replSet=testSet 给副本集起个名称。
replIndexPrefetch=_id_only 我们根据id为全索引
[root@node1 ~]# mongod --help 通过这个查看,相关参数。
Replica set options:
--replSet arg arg is <setname>[/<optionalseedhostlist>]
--replIndexPrefetch arg specify index prefetching behavior (if secondary)
[none|_id_only|all]
[root@node1 ~]# service mongod start 启动mongodb
[root@node1 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 :::22 :::*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 127.0.0.1:631 *:*
LISTEN 0 128 ::1:631 :::*
LISTEN 0 100 ::1:25 :::*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 127.0.0.1:6011 *:*
LISTEN 0 128 ::1:6011 :::*
LISTEN 0 128 192.168.178.128:27017 *:*
LISTEN 0 128 127.0.0.1:27017 *:*
[root@node1 ~]#
其余两个节点与上面操作一致。
(2)开始主从复制初始化,加入相关集群节点。
[root@node1 ~]# mongo 在node1上连入数据库。
MongoDB shell version: 2.4.14
connecting to: test
> help
db.help() help on db methods
db.mycoll.help() help on collection methods
sh.help() sharding helpers
rs.help() replica set helpers 相关副本集帮助。
help admin administrative help
help connect connecting to a db help
help keys key shortcuts
help misc misc things to know
help mr mapreduce
show dbs show database names
show collections show collections in current database
show users show users in current database
show profile show most recent system.profile entries with time >= 1ms
show logs show the accessible logger names
show log [name] prints out the last segment of log in memory, 'global' is default
use <db_name> set current database
db.foo.find() list objects in collection foo
db.foo.find( { a : 1 } ) list objects in foo where a == 1
it result of the last line evaluated; use to further iterate
DBQuery.shellBatchSize = x set default number of items to display on shell
exit quit the mongo shell
>
> rs.help()
rs.status() { replSetGetStatus : 1 } checks repl set status
rs.initiate() { replSetInitiate : null } initiates set with default settings
rs.initiate(cfg) { replSetInitiate : cfg } initiates set with configuration cfg
rs.conf() get the current configuration object from local.system.replset
rs.reconfig(cfg) updates the configuration of a running replica set with cfg (disconnects)
rs.add(hostportstr) add a new member to the set with default attributes (disconnects)
rs.add(membercfgobj) add a new member to the set with extra attributes (disconnects)
rs.addArb(hostportstr) add a new member which is arbiterOnly:true (disconnects)
rs.stepDown([secs]) step down as primary (momentarily) (disconnects)
rs.syncFrom(hostportstr) make a secondary to sync from the given member
rs.freeze(secs) make a node ineligible to become primary for the time specified
rs.remove(hostportstr) remove a host from the replica set (disconnects)
rs.slaveOk() shorthand for db.getMongo().setSlaveOk()
db.isMaster() check who is primary
db.printReplicationInfo() check oplog size and time range
reconfiguration helpers disconnect from the database so the shell will display
an error, even if the command succeeds.
see also http://<mongod_host>:28017/_replSet for additional diagnostic info
>
> rs.status() 查看副本集相关状态。
{
"startupStatus" : 3,
"info" : "run rs.initiate(...) if not yet done for the set", 这项说明需要我们进行初始化。
"ok" : 0,
"errmsg" : "can't get local.system.replset config from self or any seed (EMPTYCONFIG)"
}
>
> rs.initiate() 进行rs初始化。
{
"info2" : "no configuration explicitly specified -- making one",
"me" : "192.168.178.128:27017",
"info" : "Config now saved locally. Should come online in about a minute.",
"ok" : 1
}
> rs.status() 再次查看副本集状态。
{
"set" : "testSet", 这是副本集名称。
"date" : ISODate("2020-08-09T08:31:07Z"),
"myState" : 1,
"members" : [ 这表示副本集成员列表,
{
"_id" : 0, 这是节点标识符。
"name" : "192.168.178.128:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY", 这表示主节点
"uptime" : 17126, 这表示最后更改oplog的时间。
"optime" : Timestamp(1596961858, 1),
"optimeDate" : ISODate("2020-08-09T08:30:58Z"),
"self" : true 这说明这是不是此节点。
}
],
"ok" : 1
}
testSet:PRIMARY> rs.add("192.168.178.130") 加入两个节点。
{ "ok" : 1 }
testSet:PRIMARY> rs.add("192.168.178.129")
{ "ok" : 1 }
testSet:PRIMARY>
加入节点遇到的错误,原因是因为没有关闭防火墙。
testSet:PRIMARY> rs.add("192.168.178.130")
{
"errmsg" : "exception: need most members up to reconfigure, not ok : 192.168.178.130:27017",
"code" : 13144,
"ok" : 0
testSet:PRIMARY> rs.status()
{
"set" : "testSet",
"date" : ISODate("2020-08-09T08:51:19Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "192.168.178.128:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 18338,
"optime" : Timestamp(1596962851, 1),
"optimeDate" : ISODate("2020-08-09T08:47:31Z"),
"self" : true
},
{
"_id" : 1,
"name" : "192.168.178.130:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 275,
"optime" : Timestamp(1596962851, 1),
"optimeDate" : ISODate("2020-08-09T08:47:31Z"),
"lastHeartbeat" : ISODate("2020-08-09T08:51:18Z"),
"lastHeartbeatRecv" : ISODate("2020-08-09T08:51:18Z"),
"pingMs" : 0,
"syncingTo" : "192.168.178.128:27017"
},
{
"_id" : 2,
"name" : "192.168.178.129:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 228,
"optime" : Timestamp(1596962851, 1),
"optimeDate" : ISODate("2020-08-09T08:47:31Z"),
"lastHeartbeat" : ISODate("2020-08-09T08:51:19Z"),
"lastHeartbeatRecv" : ISODate("2020-08-09T08:51:18Z"),
"pingMs" : 0,
"syncingTo" : "192.168.178.128:27017"
}
],
"ok" : 1
}
testSet:PRIMARY> use testdb
switched to db testdb
testSet:PRIMARY> show dbs
local 6.0751953125GB
testdb (empty)
testSet:PRIMARY> use testdb
switched to db testdb
testSet:PRIMARY> db.students.insert({name:"guo jing",Age:40,Course:"xiangchong shibazhang"})
testSet:PRIMARY> db.students.find()
{ "_id" : ObjectId("5f2fc2f0898f2546c9ce15f0"), "name" : "guo jing", "Age" : 40, "Course" : "xiangchong shibazhang" }
testSet:PRIMARY> show dbs;
local 6.0751953125GB
testdb 0.203125GB
在主库中插入一些数据,看从数据库的同步状态。noed2节点。
testSet:SECONDARY> show dbs
local 6.0751953125GB
testdb 0.203125GB
testSet:SECONDARY>
testSet:SECONDARY> db.students.find() 查询相关数据报错,这表示我们需要在从库中开启查询功能
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
testSet:SECONDARY>
testSet:PRIMARY> rs.slaveOk()
testSet:SECONDARY> rs.slaveOk()
testSet:SECONDARY> db.students.find()
{ "_id" : ObjectId("5f2fc2f0898f2546c9ce15f0"), "name" : "guo jing", "Age" : 40, "Course" : "xiangchong shibazhang" }
testSet:SECONDARY>
判断哪个节点是主节点。
testSet:PRIMARY> rs.isMaster()
{
"setName" : "testSet",
"ismaster" : true,
"secondary" : false,
"hosts" : [
"192.168.178.128:27017",
"192.168.178.129:27017",
"192.168.178.130:27017"
],
"primary" : "192.168.178.128:27017",
"me" : "192.168.178.128:27017",
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"localTime" : ISODate("2020-08-09T10:14:30.739Z"),
"ok" : 1
}
testSet:PRIMARY>
testSet:PRIMARY> db.printReplicationInfo() 这表示查看oplog的大小及时间范围
configured oplog size: 4532.2263671875MB
log length start to end: 3758secs (1.04hrs)
oplog first event time: Sun Aug 09 2020 01:30:58 GMT-0700 (PDT)
oplog last event time: Sun Aug 09 2020 02:33:36 GMT-0700 (PDT)
now: Sun Aug 09 2020 03:16:29 GMT-0700 (PDT)
testSet:PRIMARY>
rs.stepDown([secs]) :这个表示将主节点强制成从节点。默认让它下线的。
(3)副本集重新选定的条件。
(1)心跳信息,优先级(高者优先,0是不可成为主节点的),uptime:必须与所有节点都一样,如果落后是不能成为主节点的,网络链接,网络分区
选举机制:
触发选举的事件:
新副本集初始化时
从节点联系不到主节点时
主节点下台时。:某主节点收到stepDown()命令时,某从节点有更高的优先级且已经满足成主节点其他所有条件。
修改配置文件,设置优先级,注意:必须在主节点进行操作。
testSet:PRIMARY> rs.conf() 默认的配置文件信息。
{
"_id" : "testSet",
"version" : 3,
"members" : [
{
"_id" : 0,
"host" : "192.168.178.128:27017"
},
{
"_id" : 1,
"host" : "192.168.178.130:27017"
},
{
"_id" : 2,
"host" : "192.168.178.129:27017"
}
]
}
接下来我们自定义优先级,使得从成为主节点。
testSet:PRIMARY> cfg.members[1].priority=2
2
testSet:PRIMARY> rs.reconfig(cfg) 重新载入配置信息
Sun Aug 9 03:38:12.036 DBClientCursor::init call() failed
Sun Aug 9 03:38:12.039 trying reconnect to 127.0.0.1:27017
Sun Aug 9 03:38:12.040 reconnect 127.0.0.1:27017 ok
reconnected to server after rs command (which is normal)
testSet:SECONDARY> rs.conf()
{
"_id" : "testSet",
"version" : 4,
"members" : [
{
"_id" : 0,
"host" : "192.168.178.128:27017"
},
{
"_id" : 1,
"host" : "192.168.178.130:27017",
"priority" : 2 看到从节点node2优先级变为了2
},
{
"_id" : 2,
"host" : "192.168.178.129:27017"
}
]
}
testSet:SECONDARY> rs.status() 查看状态信息可以看到node2成为了主节点。
{
"set" : "testSet",
"date" : ISODate("2020-08-09T10:39:53Z"),
"myState" : 2,
"syncingTo" : "192.168.178.130:27017",
"members" : [
{
"_id" : 0,
"name" : "192.168.178.128:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 24852,
"optime" : Timestamp(1596969492, 1),
"optimeDate" : ISODate("2020-08-09T10:38:12Z"),
"errmsg" : "syncing to: 192.168.178.130:27017",
"self" : true
},
{
"_id" : 1,
"name" : "192.168.178.130:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 101,
"optime" : Timestamp(1596969492, 1),
"optimeDate" : ISODate("2020-08-09T10:38:12Z"),
"lastHeartbeat" : ISODate("2020-08-09T10:39:52Z"),
"lastHeartbeatRecv" : ISODate("2020-08-09T10:39:52Z"),
"pingMs" : 0,
"syncingTo" : "192.168.178.128:27017"
},
{
"_id" : 2,
"name" : "192.168.178.129:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 101,
"optime" : Timestamp(1596969492, 1),
"optimeDate" : ISODate("2020-08-09T10:38:12Z"),
"lastHeartbeat" : ISODate("2020-08-09T10:39:52Z"),
"lastHeartbeatRecv" : ISODate("2020-08-09T10:39:52Z"),
"pingMs" : 0,
"lastHeartbeatMessage" : "syncing to: 192.168.178.130:27017",
"syncingTo" : "192.168.178.130:27017"
}
],
"ok" : 1
}
如何设置仲裁节点:
testSet:PRIMARY> cfg.members[0].arbiterOnly=true 设置仲裁节点。
true
testSet:PRIMARY> rs.reconfig(cfg)
{
"errmsg" : "exception: arbiterOnly may not change for members",
"code" : 13510,
"ok" : 0
}
总结:主从复制架构一些相关操作基本完成。我们了解主从复制其实复制的是oplog中的数据。
初始同步的步骤:
1,克隆所有数据库
2,应用数据集的所有改变,复制oplog并应用于本地
3,为所有collection构建索引。
版权声明:本文为yurun_house原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。