在生产中使用 MongoDB, 为了数据安全性和访问稳定性. 副本集是经常被使用到的.
书接上回, 话说 MongoDB 副本集已经安装过很多次了. 但是每次都要去 百度 具体命令细节.
只好自己整理笔记, 记录下来, 以备查询.
MongoDB 的下载与安装, 请参考:
http://blog.51cto.com/hsbxxl/2149500
1. 什么是 Replica Set - 副本集
副本集就是 mongoDB 副本所组成的一个集群.
其原理是, 写操作发生在主库, 从库同步主库的 OpLog 日志.
集群中没有特定的主库, 主库是选举产生, 如果主库 down 了, 会再选举出一台主库.
2. 早期的 MongoDB 版本使用 master-slave, 一主一从和 MySQL 类似, 但 slave 在此架构中为只读, 当主库宕机后, 从库不能自动切换为主. 目前已经淘汰 master-slave 模式, 改为副本集, 这种模式下有一个主 (primary), 和多个从(secondary), 只读. 支持给它们设置权重, 当主宕掉后, 权重最高的从切换为主. 在此架构中还可以建立一个仲裁(arbiter) 的角色, 它只负责裁决, 而不存储数据. 此架构中读写数据都是在主上, 要想实现负载均衡的目的需要手动指定读库的目标 server.
简而言之 MongoDB 副本集是有自动故障恢复功能的主从集群, 有一个 Primary 节点和一个或多个 Secondary 节点组成. 类似于 MySQL 的 MMM 架构. 更多关于副本集的介绍请见官方文档:
官方文档地址:
https://docs.mongodb.com/manual/replication/
3. 副本集有以下特点:
- <1>. 最小构成是: primary,secondary,arbiter, 一般部署是: primary,2 secondary.
- <2>. 成员数应该为奇数, 如果为偶数的情况下添加 arbiter,arbiter 不保存数据, 只投票.
- <3>. 最大 50 members, 但是只能有 7 voting members, 其他是 non-voting members.
配置副本集
4. 本次实验, 配置的是 1 主 1 从 1 仲裁 的副本集. 两个物理机
- host1 192.168.67.101:27017
- host2 192.168.67.102:27017
- host2 192.168.67.102:27018
5. 分别启动 mongo 进程
host1 上启动 primary
mongod --port 27017 --dbpath /mongodbs/mgdata/ --logpath /mongodbs/mgdata/db.log --replSet rs0 --fork
host2 上启动 secondary
mongod --port 27017 --dbpath /mongodbs/mgdata/ --logpath /mongodbs/mgdata/db.log --replSet rs0 --fork
host2 上启动 arb
mongod --port 28018 --dbpath /mongodbs/arb/ --logpath /mongodbs/arb/db.log --replSet rs0 --fork
6. 配置副本集, 由于只有两台物理机, 希望 host1 机器正常情况下, 能更多的做为 mongo 的 primary. 所以 priority 设置为 2
- #mongo
- > cfg={ _id:"rs0", members:[ {_id:0,host:'192.168.67.101:27017',priority:2},{_id:2,host:'192.168.67.102',priority:1}, {_id:1,host:'192.168.67.102:28018',arbiterOnly:true}]}
7. 执行初始化节点配置
>rs.initiate(cfg)
8. 查看节点配置 & 信息
- >rs.conf()
- > rs.status()
9. 具体命令输出如下
- > cfg={ _id:"rs0", members:[ {_id:0,host:'192.168.67.101:27017',priority:2},{_id:2,host:'192.168.67.102',priority:1}, {_id:1,host:'192.168.67.102:28018',arbiterOnly:true}]}
- {
- "_id" : "rs0",
- "members" : [
- {
- "_id" : 0,
- "host" : "192.168.67.101:27017",
- "priority" : 2
- },
- {
- "_id" : 2,
- "host" : "192.168.67.102",
- "priority" : 1
- },
- {
- "_id" : 1,
- "host" : "192.168.67.102:28018",
- "arbiterOnly" : true
- }
- ]
- }
- > rs.initiate(cfg)
- { "ok" : 1 }
- rs0:OTHER> rs.conf()
- {
- "_id" : "rs0",
- "version" : 1,
- "protocolVersion" : NumberLong(1),
- "members" : [
- {
- "_id" : 0,
- "host" : "192.168.67.101:27017",
- "arbiterOnly" : false,
- "buildIndexes" : true,
- "hidden" : false,
- "priority" : 2,
- "tags" : {
- },
- "slaveDelay" : NumberLong(0),
- "votes" : 1
- },
- {
- "_id" : 2,
- "host" : "192.168.67.102:27017",
- "arbiterOnly" : false,
- "buildIndexes" : true,
- "hidden" : false,
- "priority" : 1,
- "tags" : {
- },
- "slaveDelay" : NumberLong(0),
- "votes" : 1
- },
- {
- "_id" : 1,
- "host" : "192.168.67.102:28018",
- "arbiterOnly" : true,
- "buildIndexes" : true,
- "hidden" : false,
- "priority" : 1,
- "tags" : {
- },
- "slaveDelay" : NumberLong(0),
- "votes" : 1
- }
- ],
- "settings" : {
- "chainingAllowed" : true,
- "heartbeatIntervalMillis" : 2000,
- "heartbeatTimeoutSecs" : 10,
- "electionTimeoutMillis" : 10000,
- "getLastErrorModes" : {
- },
- "getLastErrorDefaults" : {
- "w" : 1,
- "wtimeout" : 0
- }
- }
- }
- rs0:SECONDARY> rs.status()
- {
- "set" : "rs0",
- "date" : ISODate("2018-07-24T06:59:34.195Z"),
- "myState" : 2,
- "term" : NumberLong(2),
- "syncingTo" : "192.168.67.101:27017",
- "heartbeatIntervalMillis" : NumberLong(2000),
- "members" : [
- {
- "_id" : 0,
- "name" : "192.168.67.101:27017",
- "health" : 1,
- "state" : 1,
- "stateStr" : "PRIMARY",
- "uptime" : 60,
- "optime" : {
- "ts" : Timestamp(1532415537, 2),
- "t" : NumberLong(2)
- },
- "optimeDate" : ISODate("2018-07-24T06:58:57Z"),
- "lastHeartbeat" : ISODate("2018-07-24T06:59:32.964Z"),
- "lastHeartbeatRecv" : ISODate("2018-07-24T06:59:33.372Z"),
- "pingMs" : NumberLong(0),
- "electionTime" : Timestamp(0, 0),
- "electionDate" : ISODate("1970-01-01T00:00:00Z"),
- "configVersion" : 1
- },
- {
- "_id" : 1,
- "name" : "192.168.67.102:28018",
- "health" : 1,
- "state" : 7,
- "stateStr" : "ARBITER",
- "uptime" : 60,
- "lastHeartbeat" : ISODate("2018-07-24T06:59:32.957Z"),
- "lastHeartbeatRecv" : ISODate("2018-07-24T06:59:30.356Z"),
- "pingMs" : NumberLong(0),
- "configVersion" : 1
- },
- {
- "_id" : 2,
- "name" : "192.168.67.102:27017",
- "health" : 1,
- "state" : 2,
- "stateStr" : "SECONDARY",
- "uptime" : 615,
- "optime" : {
- "ts" : Timestamp(1532415537, 2),
- "t" : NumberLong(2)
- },
- "optimeDate" : ISODate("2018-07-24T06:58:57Z"),
- "syncingTo" : "192.168.67.101:27017",
- "configVersion" : 1,
- "self" : true
- }
- ],
- "ok" : 1
- }
更多命令
10. 添加从库命令
rs0:PRIMARY> rs.add('host3:27017')
可以指定 priority
rs0:PRIMARY> rs.add({host: "host3:27017", priority: 1})
11. 移除一个从库
先关闭从库的 mongoDB, 然后在主库上移除从库
rs0:PRIMARY> rs.remove('host3:27019')
12. 读写分离
主库, 从库都支持读操作. 但是, 默认情况读也是从主库来读.
从库可以通过设置 ReadPreference 打开支持读操作, ReadPreference 有几种模式:
- Primary #从主库读, 默认
- primaryPreferred #基本上从主库读, 主不可用时, 从从库读
- secondary #从从库读
- secondaryPreferred #基本上从从库读, 从不可用时, 从主库读
- nearest #从网络延迟最小的库读
基本上常用的是, Primary,secondary,nearest
13. 副本集的设定中可以通过 Tag 把成员归类, 通过下面方法指定读的类型:
- <1>. 程序连接的时候, 指定读的类型 ReadPreference
- <2>. 用 mongo 命令连接, 只对当前连接有效
- rs0:SECONDARY> db.getMongo().setReadPref('secondaryPreferred')
14. 特殊成员类型
Secondary 还有一些特殊的成员类型:
Priority 0 #不能升为主, 可以用于多数据中心场景
Hidden #对客户端来说是不可见的, 一般用作备份或统计报告用
Delayed #数据比副集晚, 一般用作 rolling backup 或历史快照
副本集的配置也是比较简单的. 后面有时间, 再分享一下 MongoDB Sharded Cluster.
参考链接:
- https://www.cnblogs.com/ee900222/p/mongodb_2.html
- http://blog.51cto.com/zero01/2059033
- http://chenzhou123520.iteye.com/blog/1634676
来源: http://blog.51cto.com/hsbxxl/2149531