MongoDB复制集架构
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB复制集架构相关的知识,希望对你有一定的参考价值。
MongoDB复制集架构
由数据结点,投票结点组成,需要配置集群信息,可自动检测集群中的结点健康状态,当有结点出故障时,自动下线和切换主从结点。适用于数据量较大,高可用服务
通常,为了防止单点故障应用程序需要做集群。然而在数据库中除了防止单点故障,还需要做到数据库备份,读写分离,故障转移等。而 MongoDB 的 Replica Set 恰恰都能满足这些要求。
Replica Set角色
Replica Set 的成员是一堆有着同样的数据内容 mongod 的实例集合,包含以下三类角色:
主节点(Primary)
是 Replica Set 中唯一的接收写请求的节点,并将写入指令记录到 oplog 上。副本节点通过复制 oplog 的写入指令同步主节点的数据。Secondary。一个 Replica Set 有且只有Primary 节点,当Primar挂掉后,其他 Secondary 或者 Arbiter 节点会重新选举出来一个主节点。应用程序的默认读取请求也是发到 Primary节点处理的。副本节点(Secondary)
通过复制主节点 oplog 中的指令与主节点保持同样的数据集,当主节点挂掉的时候,参与主节点选举。仲裁者(Arbiter)
不存储实际应用数据,只投票参与选取主节点,但不会被选举成为主节点。
复制集架构配置:
架构:
Arbite:127.0.0.1:27017
primary:127.0.0.1:27018
secondary: 127.0.0.1:27019
配置文件内容如下,只要修改logpath、dbpath、pidfilepath和端口即可
arbiter.conf
# syslog配置 logpath=/var/log/mongo/logs/mongod1.log logappend=true timeStampFormat=iso8601-utc # storage 存储配置 dbpath=/data/mongo/repldb1 directoryperdb=true # processManagement 进程管理配置 fork=true # 进程 PID 文件保存目录 pidfilepath=/var/run/mongod1.pid # net 网络配置 bind_ip=127.0.0.1 port=27017 # security 配置 #auth=true # 复制集 replSet=test-set
primary.conf
# syslog配置 logpath=/var/log/mongo/logs/mongod2.log logappend=true timeStampFormat=iso8601-utc # storage 存储配置 dbpath=/data/mongo/repldb2 directoryperdb=true # processManagement 进程管理配置 fork=true # 进程 PID 文件保存目录 pidfilepath=/var/run/mongod2.pid # net 网络配置 bind_ip=127.0.0.1 port=27018 # security 配置 #auth=true # 复制集 replSet=test-set
secondary.conf
# syslog配置 logpath=/var/log/mongo/logs/mongod3.log logappend=true timeStampFormat=iso8601-utc # storage 存储配置 dbpath=/data/mongo/repldb3 directoryperdb=true # processManagement 进程管理配置 fork=true # 进程 PID 文件保存目录 pidfilepath=/var/run/mongod3.pid # net 网络配置 bind_ip=127.0.0.1 port=27019 # security 配置 #auth=true # 复制集 replSet=test-set
分别启动这三个实例:
mongod --config arbiter.conf mongod --config primary.conf mongod --config secondary.conf
初始化:
使用mongodb客户端登陆两个常规节点(primary和secondary)中的任何一个,执行如下命令
mongod 127.0.0.1:27018
登陆后执行初始化命令
> rs.initiate( ... {"_id":"test-set", ... "members":[ ... {"_id":1,"host":"127.0.0.1:27018"}, ... {"_id":2,"host":"127.0.0.1:27019"} ... ] ... }); { "ok" : 1 } test-set:SECONDARY> rs.addArb("127.0.0.1:27017") { "ok" : 1 }
查看集群状态:
test-set:PRIMARY> rs.status() { "set" : "test-set", "date" : ISODate("2018-04-19T07:22:22.813Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1524122535, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1524122535, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1524122535, 1), "t" : NumberLong(1) } }, "members" : [ { "_id" : 1, "name" : "127.0.0.1:27018", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1303, "optime" : { "ts" : Timestamp(1524122535, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-04-19T07:22:15Z"), "electionTime" : Timestamp(1524121903, 1), "electionDate" : ISODate("2018-04-19T07:11:43Z"), "configVersion" : 2, "self" : true }, { "_id" : 2, "name" : "127.0.0.1:27019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 649, "optime" : { "ts" : Timestamp(1524122535, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1524122535, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-04-19T07:22:15Z"), "optimeDurableDate" : ISODate("2018-04-19T07:22:15Z"), "lastHeartbeat" : ISODate("2018-04-19T07:22:21.472Z"), "lastHeartbeatRecv" : ISODate("2018-04-19T07:22:21.472Z"), "pingMs" : NumberLong(0), "syncingTo" : "127.0.0.1:27018", "configVersion" : 2 }, { "_id" : 3, "name" : "127.0.0.1:27017", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 69, "lastHeartbeat" : ISODate("2018-04-19T07:22:21.471Z"), "lastHeartbeatRecv" : ISODate("2018-04-19T07:22:18.484Z"), "pingMs" : NumberLong(0), "configVersion" : 2 } ], "ok" : 1 }
登录127.0.0.1:27019 角色显示为Secondary
mongo 127.0.0.1:27019
2018-04-19T07:00:44.075Z I CONTROL [initandlisten] test-set:SECONDARY> test-set:SECONDARY> test-set:SECONDARY>
在primary上创建数据,测试secondary上是否会同步
test-set:PRIMARY> show dbs admin 0.000GB local 0.000GB test-set:PRIMARY> use testdb switched to db testdb test-set:PRIMARY> show collections test-set:PRIMARY> db.test.insert({"name":"user1"}); WriteResult({ "nInserted" : 1 })
登录secondary,查看
test-set:SECONDARY> rs.slaveOk() test-set:SECONDARY> show dbs admin 0.000GB local 0.000GB testdb 0.000GB test-set:SECONDARY> use testdb switched to db testdb test-set:SECONDARY> show collections test test-set:SECONDARY> db.test.find() { "_id" : ObjectId("5ad844efa46a748c5a90fe41"), "name" : "user1" }
secondary上插入数据报错,说明secondary上没有写的权限
test-set:SECONDARY> db.test.insert({"name":"user2"}); WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })
验证复制集架构容灾功能
kill掉primary的进程,登录127.0.0.1:27019
test-set:PRIMARY> show dbs admin 0.000GB local 0.000GB testdb 0.000GB test-set:PRIMARY> rs.status() { "set" : "test-set", "date" : ISODate("2018-04-19T07:44:28.912Z"), "myState" : 1, "term" : NumberLong(2), "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1524123775, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1524123862, 1), "t" : NumberLong(2) }, "durableOpTime" : { "ts" : Timestamp(1524123862, 1), "t" : NumberLong(2) } }, "members" : [ { "_id" : 1, "name" : "127.0.0.1:27018", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDurable" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2018-04-19T07:44:27.023Z"), "lastHeartbeatRecv" : ISODate("2018-04-19T07:42:59.830Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Connection refused", "configVersion" : -1 }, { "_id" : 2, "name" : "127.0.0.1:27019", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 2625, "optime" : { "ts" : Timestamp(1524123862, 1), "t" : NumberLong(2) }, "optimeDate" : ISODate("2018-04-19T07:44:22Z"), "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1524123790, 1), "electionDate" : ISODate("2018-04-19T07:43:10Z"), "configVersion" : 2, "self" : true }, { "_id" : 3, "name" : "127.0.0.1:27017", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 1395, "lastHeartbeat" : ISODate("2018-04-19T07:44:27.009Z"), "lastHeartbeatRecv" : ISODate("2018-04-19T07:44:28.662Z"), "pingMs" : NumberLong(0), "configVersion" : 2 } ], "ok" : 1 }
可以看到127.0.0.1:27018 有一个 "stateStr" : "(not reachable/healthy)"的报错,而127.0.0.1:27019已经变成了primary角色
启动原来的primary.conf配置的实例,角色由原来的primary变成了secondary
test-set:SECONDARY> show dbs 2018-04-19T15:50:04.113+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435, "codeName" : "NotMasterNoSlaveOk" } : [email protected]/mongo/shell/utils.js:25:13 [email protected]/mongo/shell/mongo.js:62:1 [email protected]/mongo/shell/utils.js:782:19 [email protected]/mongo/shell/utils.js:672:15 @(shellhelp2):1:1 test-set:SECONDARY>
其他命令:
rs.slaveOk():secondary默认不允许读写,执行此命令后,从节点有可读权限
rs.conf():查看配置情况
test-set:SECONDARY> rs.conf() { "_id" : "test-set", "version" : 2, "protocolVersion" : NumberLong(1), "members" : [ { "_id" : 1, "host" : "127.0.0.1:27018", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "127.0.0.1:27019", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 3, "host" : "127.0.0.1:27017", "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("5ad841247ffb05dbb6b4a13b") } }
以上是关于MongoDB复制集架构的主要内容,如果未能解决你的问题,请参考以下文章