Mongodb从0到1系列六: 复制集
来源:互联网 发布:知乎怎么用 编辑:程序博客网 时间:2024/05/21 15:00
Mongodb从0到1系列一:下载、安装、启动、停止
Mongodb从0到1系列二:数据库与集合操作文档、增删改查
Mongodb从0到1系列三: 条件查询、大小写
Mongodb从0到1系列四: Limit与Skip方法、排序、索引
Mongodb从0到1系列五: 主从复制
11 复制集
复制集是一个带有故障转移的主从集群。是从现有的主从模式演变而来,增加了自动故障转移和节点成员自动恢复。复制集模式中没有固定的主结点,在启动后,多个服务节点间将自动选举产生一个主结点。该主结点被称为primary,一个或多个从结点被称为secondaries。primary结点基本上就是master结点,不同之处在于primary结点在不同时间可能是不同的服务器。如果当前的主结点失效了,复制集中的其余结点将会试图选出一个新的主结点。
复制集模式的好处是,一切自动化。首先,复制集模式本身做了大量的管理工作,自动管理从节点,确保数据不会不一致。其次,主节点挂掉后,会自动判断集群中的服务器并进行故障转移,推举新的主节点。
Primary 主节点,一个复制集有且仅有一台服务器处于Primary状态,只有主节点才对外提供读写服务。如果主节点挂掉,复制集将会投票选出一个备用节点成为新的主节点。
Secondary 备用节点,复制集允许有多台Secondary,每个备用节点的数据与主节点的数据是完全同步的。
Recovering 恢复中,当复制集中某台服务器挂掉或者掉线后数据无法同步,重新恢复服务后从其他成员复制数据,这时就处于恢复过程,数据同步后,该节点又回到备用状态。
Arbiter 仲裁节点,该类节点可以不用单独存在,如果配置为仲裁节点,就主要负责在复本集中监控其他节点状态,投票选出主节点。该节点将不会用于存放数据。如果没有仲裁节点,那么投票工作将由所有节点共同进行。
Down 无效节点,当服务器挂掉或掉线时就会处于该状态。
11.1 有仲裁节点
由于机器数量限制,只在一个节点上做测试,使用3个不同的dbpath和端口, 开3个sesion, 指定同一个replSetdb2a:~ # mkdir /data/repdb2
db2a:~ # mkdir /data/repdb3
db2a:~ # mongod --dbpath=/data/db --port 27017 --replSet rs1
db2a:~ # mongod --dbpath=/data/repdb2 --port 27018 --replSet rs1
db2a:~ # mongod --dbpath=/data/repdb3 --port 27019 --replSet rs1
新开一mongo shell Session:
//配置复制集,27019作为仲裁节点:
db2a:~ # mongo 192.168.37.1:27017
MongoDB Enterprise > config = {_id:"rs1", members:[{_id:0,host:"192.168.37.1:27017"}, {_id:1,host:"192.168.37.1:27018"}, {_id:2,host:"192.168.37.1:27019", arbiterOnly:true}]}
{
"_id" : "rs1",
"members" : [
{
"_id" : 0,
"host" : "192.168.37.1:27017"
},
{
"_id" : 1,
"host" : "192.168.37.1:27018"
},
{
"_id" : 2,
"host" : "192.168.37.1:27019",
"arbiterOnly" : true
}
]
}
MongoDB Enterprise > rs.initiate(config)
{ "ok" : 1 }
查看复制集配置:
MongoDB Enterprise rs1:SECONDARY> rs.conf()
{ "_id" : "rs1", "version" : 1, "protocolVersion" : NumberLong(1), "members" : [ { "_id" : 0, "host" : "192.168.37.1:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "192.168.37.1:27018", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "192.168.37.1:27019", "arbiterOnly" : true, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : 60000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("59740afc483597f1b29ddd33") }}
查看复制集状态,可以看到
27017的 "stateStr" : "PRIMARY"
27018的 "stateStr" : "SECONDARY"
27019的 "stateStr" : "ARBITER"
MongoDB Enterprise rs1:PRIMARY> rs.status()
{ "set" : "rs1", "date" : ISODate("2017-07-23T02:38:06.598Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1500777485, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1500777485, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1500777485, 1), "t" : NumberLong(1) } }, "members" : [ { "_id" : 0, "name" : "192.168.37.1:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 340, "optime" : { "ts" : Timestamp(1500777485, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-07-23T02:38:05Z"), "electionTime" : Timestamp(1500777223, 1), "electionDate" : ISODate("2017-07-23T02:33:43Z"), "configVersion" : 1, "self" : true }, { "_id" : 1, "name" : "192.168.37.1:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 274, "optime" : { "ts" : Timestamp(1500777475, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1500777475, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-07-23T02:37:55Z"), "optimeDurableDate" : ISODate("2017-07-23T02:37:55Z"), "lastHeartbeat" : ISODate("2017-07-23T02:38:05.508Z"), "lastHeartbeatRecv" : ISODate("2017-07-23T02:38:05.068Z"), "pingMs" : NumberLong(0), "syncingTo" : "192.168.37.1:27017", "configVersion" : 1 }, { "_id" : 2, "name" : "192.168.37.1:27019", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 274, "lastHeartbeat" : ISODate("2017-07-23T02:38:05.508Z"), "lastHeartbeatRecv" : ISODate("2017-07-23T02:38:04.268Z"), "pingMs" : NumberLong(0), "configVersion" : 1 } ], "ok" : 1}
查看当前连接Server状态:发现是primary:
MongoDB Enterprise rs1:PRIMARY> rs.isMaster()
{ "hosts" : [ "192.168.37.1:27017", "192.168.37.1:27018" ], "arbiters" : [ "192.168.37.1:27019" ], "setName" : "rs1", "setVersion" : 1, "ismaster" : true, "secondary" : false, "primary" : "192.168.37.1:27017", "me" : "192.168.37.1:27017",...}
同时,可以分别在session1,2,3里看到以下信息:
Session1:
2017-07-23T10:33:43.277+0800 I REPL [ReplicationExecutor] transition to PRIMARY
------------
Session2:
2017-07-23T10:33:34.796+0800 I REPL [rsSync] transition to RECOVERING
2017-07-23T10:33:34.798+0800 I REPL [rsBackgroundSync] could not find member to sync from
2017-07-23T10:33:34.803+0800 I REPL [rsSync] transition to SECONDARY
------------
Session3:
2017-07-23T10:33:34.133+0800 I REPL [ReplicationExecutor] transition to ARBITER
连接到27018,查询状态,看到不是primary:
MongoDB Enterprise rs1:PRIMARY> exit
bye
db2a:~ # mongo 192.168.37.1:27018
MongoDB Enterprise rs1:SECONDARY> rs.isMaster()
{ "hosts" : [ "192.168.37.1:27017", "192.168.37.1:27018" ], "arbiters" : [ "192.168.37.1:27019" ], "setName" : "rs1", "setVersion" : 1, "ismaster" : false, "secondary" : true, "primary" : "192.168.37.1:27017", "me" : "192.168.37.1:27018",...}
查询数据,发现已经同步过来:
MongoDB Enterprise rs1:SECONDARY> rs.slaveOk()
MongoDB Enterprise rs1:SECONDARY> use test1
switched to db test1
MongoDB Enterprise rs1:SECONDARY> show collections
student
teacher
MongoDB Enterprise rs1:SECONDARY> db.student.find({},{"_id":0})
{ "name" : "Zhaoliu", "age" : 25, "course" : "Chinese" }
{ "name" : "Zhangsan", "age" : 22, "course" : "Chinese" }
{ "name" : "Lisi", "age" : 23, "course" : "computer" }
{ "name" : "Liuneng", "age" : 26, "course" : "English" }
{ "name" : "Wangwu", "age" : 24, "course" : "Chinese" }
{ "name" : "Xieguangkun", "age" : 42, "course" : "Art" }
连接到27019,并查询状态,可以看到是arbiter:
MongoDB Enterprise rs1:SECONDARY> exit
bye
db2a:~ # mongo 192.168.37.1:27019
MongoDB Enterprise rs1:ARBITER> rs.isMaster()
{ "hosts" : [ "192.168.37.1:27017", "192.168.37.1:27018" ], "arbiters" : [ "192.168.37.1:27019" ], "setName" : "rs1", "setVersion" : 1, "ismaster" : false, "secondary" : false, "primary" : "192.168.37.1:27017", "arbiterOnly" : true, "me" : "192.168.37.1:27019",..}
现在把27017的服务关闭,看一下27018会不会自动变为PRIMARY, 把session1里的mongodb服务结束使用Ctrl+c结束掉,再次查询session2的isMaster(),发现变为primary了:
MongoDB Enterprise rs1:ARBITER> exit
bye
db2a:~ # mongo 192.168.37.1:27018
MongoDB Enterprise rs1:PRIMARY> rs.isMaster()
{ "hosts" : [ "192.168.37.1:27017", "192.168.37.1:27018" ], "arbiters" : [ "192.168.37.1:27019" ], "setName" : "rs1", "setVersion" : 1, "ismaster" : true, "secondary" : false, "primary" : "192.168.37.1:27018", "me" : "192.168.37.1:27018", "electionId" : ObjectId("7fffffff0000000000000002"),...}
查看复制集状态,可以看到27017的状态已经变为"stateStr" : "(not reachable/healthy)"
MongoDB Enterprise rs1:PRIMARY> rs.status()
{... "members" : [ { "_id" : 0, "name" : "192.168.37.1:27017", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0,... }, { "_id" : 1, "name" : "192.168.37.1:27018", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 2475,... }, { "_id" : 2, "name" : "192.168.37.1:27019", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 2421,.... } ], "ok" : 1}
再次在session1里启动mongodb服务之后,查看复制状态,发现27017变为SECONDARY:
MongoDB Enterprise rs1:PRIMARY> rs.status()
{... "members" : [ { "_id" : 0, "name" : "192.168.37.1:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 29,... }, { "_id" : 1, "name" : "192.168.37.1:27018", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 2702,... }, { "_id" : 2, "name" : "192.168.37.1:27019", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 2648,... } ], "ok" : 1}
11.2 无仲裁节点
理论上不是需要仲裁节点的,这次只用了两个节点,db2a上一个primary,db2b上一个secondary:db2a:~ # mkdir /data/repdb4
db2a:~ # mongod --dbpath=/data/repdb4 --port 27017 --replSet rs2
db2b:~ # mkdir /data/repdb1
db2b:~ # mongod --dbpath=/data/repdb1 --port 27017 --replSet rs2
db2a:
db2a:~ # mongo db2a:27017
> config = {_id:"rs2", members:[{_id:0,host:"db2a:27017"}, {_id:1,host:"db2b:27017"}]}
> rs.initiate(config)
rs2:PRIMARY> rs.status()
rs2:PRIMARY> rs.isMaster()
> use test1
> db.student.insert({name:'Zhaoliu',age:25,course:'Chinese'})
> db.student.insert({name:'Zhangsan',age:22,course:'Chinese'})
db2b:
db2b:~ # mongo db2b:27017
rs2:SECONDARY> rs.slaveOk()
rs2:SECONDARY> use test1
rs2:SECONDARY> db.student.find({},{"_id":0})
{ "name" : "Zhaoliu", "age" : 25, "course" : "Chinese" }
{ "name" : "Zhangsan", "age" : 22, "course" : "Chinese" }
但中断db2a的服务之后,db2b不会自动变成Primary,只有再次启动db2a服务之后,db2b才变成了primary。
再添加一个节点:
db2b上:
db2b:~ # mkdir /data/repdb2
db2b:~ # mongod --dbpath=/data/repdb2 --port 27018 --replSet rs2
在mongo shell里:
MongoDB Enterprise rs2:PRIMARY> rs.add('db2b:27018')
{ "ok" : 1 }
MongoDB Enterprise rs2:PRIMARY> rs.status()
{.. "members" : [ { "_id" : 0, "name" : "db2a:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY",... }, { "_id" : 1, "name" : "db2b:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY",... }, { "_id" : 2, "name" : "db2b:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 60,... } ], "ok" : 1}
这种情况下,如果将PRIMARY停掉(db2b:27017),那么剩下的两个节点会自动选出一个来作为PRIMARY
阅读全文
0 0
- Mongodb从0到1系列六: 复制集
- Mongodb从0到1系列五: 主从复制
- Mongodb从0到1系列三: 条件查询、大小写
- Mongodb从0到1系列七: 分片
- Mongodb从0到1系列八: 备份与恢复
- Mongodb从0到1系列一:下载、安装、启动、停止
- Mongodb从0到1系列二:数据库与集合操作、文档增删改查
- Mongodb从0到1系列四: Limit与Skip方法、排序、索引
- Rails3教程系列之六:从Rails2到Rails3
- Rails3教程系列之六:从Rails2到Rails3
- 从初识Linux到离不开系列(六)辅助至上
- FAQ系列 | 从MySQL 5.6到5.7复制错误解决
- ttlsa教程系列之mongodb——(五)mongodb架构-复制原理&复制集
- MongoDB从入门到提高【第二集】
- MongoDB从入门到提高【第一集】
- 【MongoDB】从入门到精通mongdb系列学习宝典,想学mongodb小伙伴请进来
- mongodb:在mongo终端上操作将数据从一个字段复制到另一个字段上。
- mongodb系列之六:java聚合函数
- 二十二天
- 不聪明的话就要习惯努力
- 【简记】Java Web 内幕——编码问题
- javaWEB开发中的 / 傻傻分不清楚
- FMEA:失效模式与影响分析
- Mongodb从0到1系列六: 复制集
- ZooKeeper 学习 (一) ZooKeeper的基本概念
- Codeforces 832 C Strange Radiation
- 古文觀止卷七_原道_韓愈
- 注意程序的[error]log
- 各类MQ比较
- springframework Request method 'GET' not supported
- hibernate与spring整合:配置事务之后并不会滚的问题
- ubutu搭建pptp