阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MongoDB高可用方案之副本集(Replica Set)

252次阅读
没有评论

共计 5716 个字符,预计需要花费 15 分钟才能阅读完成。

Replicat Set 比起传统的 Master – Slave 结构而言,应用场景更加多,也有了自动 failover 的能力。
在 mongo3.2 的文档中明确写道:

  1. Replica sets replace masterslave replication for most use cases. 
  2. If possible, use replica sets rather than masterslave replication for all new production deployments.

本文将简单 介绍 mongodb 副本集搭建

〇 副本集结构图

MongoDB 高可用方案之副本集 (Replica Set)
我在此处大致理解为“MySQL 中 1 主 2 从 +mha_manager” 的结构。
Replication 通过 Oplog 实现语句复现。

MongoDB 高可用方案之副本集(Replica Set)

〇 副本集成员的属性:
分别为 Primary、Secondary(Secondaries)
Primary 负责处理所有的 write 请求,并记录到 oplog(operation log)中。
Secondary 负责复制 oplog 并应用这些 write 请求到他们自己的数据集中。(有一些类似于 MySQL Replication)

所有的副本集都可以处理读操作,但是需要设置。

最小化的副本集配置建议有三个成员:
1 个 Primary + 2 个 Secondary
或者
1 个 Primary + 1 个 Secondary + 1 个 Arbiter( 仲裁者)

〇 Arbiter 和选举机制:
Arbiter 可以作为副本集的一部分,但它不是一个数据副本,故它不会成为 Primary。
Arbiter 在 Primary 不可用的时候,作为一个选举的角色存在。
如果Arbiter 不存在,Primary 挂掉的情况下,剩下的两个Secondary 则也会进行选举。

1 个 Primary + 2 个 Secondary 的情况下,failover 如下:

MongoDB 高可用方案之副本集(Replica Set)

〇 搭建

实验结构:
185(Arbiter)(后文用到)
186\187\188(1 个 Primary、2 个 Secondary)

在三台机器上分别创建对应目录然后启动 mongodb:

  1. mkdir p /data/mongo_replset
  2. mongod dbpath=/data/mongo_replset logpath=/data/mongo_replset/mongo.log fork replSet=first_replset

登录任意一台副本集的 mongo shell 
此处用的是 192.168.1.187

  1. > use admin

输入:

  1. > cnf = {_id:“first_replset”, members:[
  2.         {_id:1, host:“192.168.1.186:27017”},
  3.         {_id:2, host:“192.168.1.187:27017”},
  4.         {_id:3, host:“192.168.1.188:27017”},
  5.         ]
  6.     }
  7. 输出结果:
  8. > {
  9.         “_id” : “first_replset”,
  10.         “members” : [
  11.                 {
  12.                         “_id” : 1,
  13.                         “host” : “192.168.1.186:27017”
  14.                 },
  15.                 {
  16.                         “_id” : 2,
  17.                         “host” : “192.168.1.187:27017”
  18.                 },
  19.                 {
  20.                         “_id” : 3,
  21.                         “host” : “192.168.1.188:27017”
  22.                 }
  23.         ]
  24. }

初始化配置:

  1. > rs.initiate(cnf);
  2. {“ok” : 1 }
  3. first_replset:OTHER>
  4. first_replset:PRIMARY>
  5. first_replset:PRIMARY>

此时可以发现该 mongodb 实例已经成为 PRIMARY 了。

可以看一下这个副本集的各个成员的状态:

  1. first_replset:PRIMARY> rs.status();
  2. {
  3.         “set” : “first_replset”,
  4.         “date” : ISODate(“2016-11-15T08:22:10.316Z”),
  5.         “myState” : 2,
  6.         “term” : NumberLong(0),
  7.         “heartbeatIntervalMillis” : NumberLong(2000),
  8.         “members” : [
  9.                 {
  10.                         “_id” : 1,
  11.                         “name” : “192.168.1.186:27017”,
  12.                         “health” : 1,
  13.                         “state” : 2,
  14.                         “stateStr” : “SECONDARY”,
  15.                         ……………………
  16.                 },
  17.                 {
  18.                         “_id” : 2,
  19.                         “name” : “192.168.1.187:27017”,
  20.                         “health” : 1,
  21.                         “state” : 2,
  22.                         “stateStr” : “PRIMARY”,
  23.                         ……………………
  24.                 },
  25.                 {
  26.                         “_id” : 3,
  27.                         “name” : “192.168.1.188:27017”,
  28.                         “health” : 1,
  29.                         “state” : 2,
  30.                         “stateStr” : “SECONDARY”,
  31.                         ……………………
  32.                 }
  33.         ],
  34.         “ok” : 1
  35. }

〇 副本集复制状态测试
PRIMARY上 insert:

  1. [root@192.168.1.187]# mongo 127.0.0.1/test
  2. MongoDB shell version: 3.2.10
  3. connecting to: 127.0.0.1/test
  4. first_replset:PRIMARY> db.test_table.insert({“id”: 1})
  5. WriteResult({ “nInserted” : 1 })
  6. first_replset:PRIMARY> db.test_table.find()
  7. {“_id” : ObjectId(“582abba066fdf9fae28a1ba7”), “id” : 1 }

在 186、188 任意 SECONDARY 上查询:
同 master – slave 结构一样,默认 SECONDARY 是不可 读的,需要执行 rs.slaveOk()。

  1. first_replset:SECONDARY> rs.slaveOk()
  2. first_replset:SECONDARY> db.test_table.find()
  3. {“_id” : ObjectId(“582abba066fdf9fae28a1ba7”), “id” : 1 }

〇 failover 测试

此时情况:
187:PRIAMRY
186、188:SECONDARY

停掉 PRIAMRY:

  1. first_replset:PRIMARY> use admin
  2. switched to db admin
  3. first_replset:PRIMARY> db.shutdownServer()
  4. server should be down...
  5. 20161115T16:31:25.921+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
  6. 20161115T16:31:27.299+0800 I NETWORK [thread1] Socket recv() errno:104 Connection reset by peer 127.0.0.1:27017
  7. 20161115T16:31:27.299+0800 I NETWORK [thread1] SocketException: remote: (NONE):0 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27017]
  8. 20161115T16:31:27.299+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed
  9. 20161115T16:31:27.302+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
  10. 20161115T16:31:27.302+0800 W NETWORK [thread1] Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
  11. 20161115T16:31:27.302+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed
  12. >

(原 SECONDARY)188 上查到,此时 188 已经为 PRIMARY 了。

  1. first_replset:PRIMARY> rs.status()
  2. {
  3.         “set” : “first_replset”,
  4.         “date” : ISODate(“2016-11-15T16:31:45.773Z”),
  5.         “myState” : 1,
  6.         “term” : NumberLong(2),
  7.         “heartbeatIntervalMillis” : NumberLong(2000),
  8.         “members” : [
  9.                 {
  10.                         “_id” : 1,
  11.                         “name” : “192.168.1.186:27017”,
  12.                         “health” : 1,
  13.                         “state” : 2,
  14.                         “stateStr” : “SECONDARY”,
  15.                         ……………………
  16.                 },
  17.                 {
  18.                         “_id” : 2,
  19.                         “name” : “192.168.1.187:27017”,
  20.                         “health” : 0,
  21.                         “state” : 8,
  22.                         “stateStr” : “(not reachable/healthy)”,
  23.                         ……………………
  24.                 },
  25.                 {
  26.                         “_id” : 3,
  27.                         “name” : “192.168.1.188:27017”,
  28.                         “health” : 1,
  29.                         “state” : 1,
  30.                         “stateStr” : “PRIMARY”,
  31.                         ……………………
  32.                 }
  33.         ],
  34.         “ok” : 1
  35. }

〇 在副本集中添加一个属性为 Arbiter 的成员
然此处只 做添加实践,实际上并不建议在 Secondary-Primary-Secondary 的结构上再多一个 Arbiter 成员形成偶数个节点。
文档写到:

  1. Only add an arbiter to sets with even numbers of voting members. 
  2. If you add an arbiter to a set with an odd number of voting members, the set may suffer from tied elections.

192.168.1.185(另一台) 上启动一个 mongod 实例:

  1. mkdir p /data/arb
  2. mongod dbpath=/data/arb/ logpath=/data/arb/mongo.log fork replSet=first_replset

在 failover 后的 PRIMARY 节点添加 Arbiter

  1. first_replset:PRIMARY> rs.addArb(“192.168.1.185:27017”)
  2. {“ok” : 1 }
  3. first_replset:PRIMARY> rs.status()
  4.                 …………………
  5.                 {
  6.                         “_id” : 4,
  7.                         “name” : “192.168.1.185:27017”,
  8.                         “health” : 1,
  9.                         “state” : 7,
  10.                         “stateStr” : “ARBITER”,
  11.                         …………………
  12.                 }
  13.                 ……………………

此时回到 arbiter 的 mongo shell,发现正如文档所说,arbiter 是不会存有副本集中数据的。

  1. first_replset:ARBITER> rs.slaveOk()
  2. first_replset:ARBITER> use test;
  3. switched to db test
  4. first_replset:ARBITER> show tables;
  5. first_replset:ARBITER> db.test_table.find();
  6. Error: error: {“ok” : 0, “errmsg” : “node is recovering”, “code” : 13436 }

〇 文档:
Replication > Replica Set Tutorials > Replica Set Deployment Tutorials 
Reference > mongo Shell Methods > Replication Methods

本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-03/142379.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计5716字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中