UDN-企业互联网技术人气社区

板块导航

浏览  : 2025
回复  : 1

[文档] MongoDB学习札记第六篇之主从复制

[复制链接]
htmlman的头像 楼主
发表于 2016-5-3 10:00:03 | 显示全部楼层 |阅读模式
  环境准备:
复制代码

  主从复制是MongoDB中最常见的复制方式。这种方式非常灵活,可用于备份,故障恢复,读扩展 等。

  本次试验中,我们采用一个主节点,一个从节点。

  首先先创建master和slave的目录
  1. lwb@ubuntu:~$ mkdir -p ~/mongoData/master
  2. lwb@ubuntu:~$ mkdir -p ~/mongoData/slave
复制代码

  创建之后,启动master
  1. lwb@ubuntu:~$ mongod --master --dbpath ~/mongoData/master/ --port 10000
复制代码

  然后再启动slave
  1. lwb@ubuntu:~$ mongod --dbpath  ~/mongoData/slave/ --port 10001 --slave --source localhost:10000
复制代码
  接着,连接到master的机器,
  1. lwb@ubuntu:~$ mongo --host localhost --port 10000
复制代码

  往test数据库的users集合里面插入两条数据:
  1. > db.users.find()
  2. { "_id" : ObjectId("55763d98db85929bb8addedf"), "username" : "lwb" }
  3. { "_id" : ObjectId("55764a694b24187a7a3c6693"), "username" : "mongodb master-slave" }
复制代码

  在master操作完成之后,在连接slave的mongod
  1. lwb@ubuntu:~$ mongo --host localhost --port 10001
  2. MongoDB shell version: 3.0.3
  3. connecting to: localhost:10001/test
  4. Server has startup warnings:
  5. 2015-06-08T19:02:31.866-0700 I CONTROL  [initandlisten]
  6. 2015-06-08T19:02:31.866-0700 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/   mm/transparent_hugepage/defrag is 'always'.
  7. 2015-06-08T19:02:31.866-0700 I CONTROL  [initandlisten] **        We suggest set   ting it to 'never'
  8. 2015-06-08T19:02:31.866-0700 I CONTROL  [initandlisten]
  9. >
  10. > show dbs
  11. 2015-06-08T19:09:17.770-0700 E QUERY    Error: listDatabases failed:{ "note" : "   from execCommand", "ok" : 0, "errmsg" : "not master" }
  12.     at Error (<anonymous>)
  13.     at Mongo.getDBs (src/mongo/shell/mongo.js:47:15)
  14.     at shellHelper.show (src/mongo/shell/utils.js:630:33)
  15.     at shellHelper (src/mongo/shell/utils.js:524:36)
  16.     at (shellhelp2):1:1 at src/mongo/shell/mongo.js:47
  17. >
  18. > rs.slaveOk()
  19. >
  20. > show dbs
  21. local  0.078GB
  22. test   0.078GB
  23. >
  24. > use test
  25. switched to db test
  26. > show collections
  27. system.indexes
  28. users
  29. >
  30. > db.users.find()
  31. { "_id" : ObjectId("55763d98db85929bb8addedf"), "username" : "lwb" }
  32. { "_id" : ObjectId("55764a694b24187a7a3c6693"), "username" : "mongodb master-slave" }
复制代码

  我遇到的问题及解决方法

  问题一:

  我的主从复制实验分为两次进行,刚开始我配置的master的端口是 10000 ,salve的端口是10001 ; 后因为电脑内存使用率暴涨,90+% 。 所以关掉电脑重启。问题就出现在这里,重启之后,我指定master端口的时候指定为 27000 , 指定slave端口为 27001 所以就出现了如下问题:terminating mongod after 30 seconds
  1. 2015-06-08T18:11:37.981-0700 I NETWORK  [initandlisten] waiting for connections on port 27001
  2. 2015-06-08T18:11:38.975-0700 I REPL     [replslave] repl: --source localhost:27000 != localhost:10000 from local.sources collection
  3. 2015-06-08T18:11:38.976-0700 I REPL     [replslave] repl: for instructions on changing this slave's source, see: 2015-06-08T18:11:38.976-0700 I REPL     [replslave] http://dochub.mongodb.org/co re/masterslave
  4. 2015-06-08T18:11:38.976-0700 I REPL     [replslave] repl: terminating mongod after 30 seconds
  5. 2015-06-08T18:12:08.976-0700 I CONTROL  [replslave] dbexit:  rc: 3
复制代码

  解决方法:

  如果仔细观察日志的同学应该会发现:
  1. 2015-06-08T18:11:38.975-0700 I REPL     [replslave] repl: --source localhost:27000 != localhost:10000 from local.sources collection
复制代码

  所以,在一开始的时候我们已经为slave指定了master的host和port,这个会插入到local.sources 这个集合的。所以,把master端口改成10000就可以了。

  问题二

  主从启动之后,连接slave可以成功连上,但是在slave中执行 show dbs 的时候就报错了:
  1. QUERY    Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }
复制代码

  解决方法:

  在报错的slave机器上执行 rs.slaveOk()方法即可。
  1. > rs.slaveOk()
  2. > show dbs
  3. local  0.078GB
  4. test   0.078GB
  5. > use test
  6. switched to db test
  7. > show collections
  8. system.indexes
  9. users
  10. > db.users.find()
  11. { "_id" : ObjectId("55763d98db85929bb8addedf"), "username" : "lwb" }
  12. { "_id" : ObjectId("55764a694b24187a7a3c6693"), "username" : "mongodb master-sla
复制代码

  具体slaveOk方法是什么意思?

  rs.slaveOk()
  1. Provides a shorthand for the following operation:

  2. db.getMongo().setSlaveOk()
  3. This allows the current connection to allow read operations to run on secondary members. See the readPref() method for more fine-grained control over read preference in the mongo shell.
复制代码

  Master-Slave安全
  这个主从安全在 MongoDB官网说的很清楚。不能和普通的mongod权限验证那样。这里除了需要加入 —auth 还需要加入 —keyFile 的验证。

  首先,我们生成我们的keyFile,根据官网提供的说明,这个keyfile是可以任意内容的,只要保证所有集群中的机器都拥有同样的文件即可。在linux环境下,我们通过
  1. openssl rand -base64 741 > /usr/localhsot/mongodb/mongo-keyfile
复制代码

  这条命令来生成我们的keyFile。 生成之后就可以在启动mongod的时候指定了。

  首先先启动 master
  1. root@ubuntu:/usr/local/mongodb# mongod --master --dbpath ~/mongoData/master/ --port 10000 --auth --keyFile /usr/local/mongodb/mongo-keyfile
复制代码

  这里在启动的时候可能会遇到一些问题,我是在ubuntu环境下,所以经常操作要sudo,很繁琐。因此,让当前用户获得root权限是很有必要的。
  1. 在命令行模式执行 vi etc/passwd
  2. 我的用户名是 lwb ,所以将lwb所在的行改成
  3. lwb:x:0:0:Ubuntu12.04,,,:/home/lwb:/bin/bash
  4. 原来的值是(将1000 改成 0 即可): lwb:x:1000:1000:Ubuntu12.04,,,:/home/lwb:/bin/bash
复制代码

  修改完成之后重启登录就可以让当前用户获得root权限了。

  回到正题,在生成mongo-keyfile后,并指定keyFile参数来启动mongod的时候,可能还会遇到另一个问题:
  1. root@ubuntu:~# mongod --master --dbpath ~/mongoData/master/ --port 10000 --auth --keyFile /usr/local/mongodb/mongo-keyfile
  2. 2015-06-08T21:34:43.864-0700 I ACCESS   permissions on /usr/local/mongodb/mongo-keyfile are too open
复制代码

  这个错误的意思是说 mongo-keyfile权限太大了,降低一下这个文件的权限。
  1. root@ubuntu:/usr/local/mongodb# chmod 400 mongo-keyfile
  2. root@ubuntu:/usr/local/mongodb# ll
  3. total 84
  4. drwxr-xr-x  4 root root  4096 Jun  8 21:34 ./
  5. drwxr-xr-x 11 root root  4096 Jun  8 16:49 ../
  6. -rw-r--r--  1 root root 34520 Jun  6 07:24 GNU-AGPL-3.0
  7. -rw-r--r--  1 root root  1359 Jun  6 07:24 README
  8. -rw-r--r--  1 root root 22660 Jun  6 07:24 THIRD-PARTY-NOTICES
  9. drwxr-xr-x  2 root root  4096 Jun  6 07:24 bin/
  10. drwxr-xr-x  3 root root  4096 Jun  7 13:02 data/
  11. -r--------  1 root root  1004 Jun  8 21:34 mongo-keyfile
复制代码

  重启一下mongod即可正常运行。

  接着启动slave

  mongod --slave --dbpath ~/mongoData/slave/ --port 10001 --source localhost:10000 --auth --keyFile /usr/local/mongodb/mongo-keyfile

  一切都顺利的进行着。

  使用创建的用户操作master里面的数据库以及集合都是正常的。但是使用同样的用户操作slave的时候就有不正常了。还是提示

  QUERY Error: listDatabases failed:{ "note" : "from execCommand", "ok" : 0, "errmsg" : "not master" }

  这个错误上面已经提到了。解决方法也是一样的。 rs.slaveOk() 执行完这条语句之后既可以正常操作了。

  可以发现,用keyFile的方式启动mongod服务器其实和平常启动没什么区别,唯一的区别就是在启动参数中指定了 --keyFile keyfile 而已。

  具体怎么创建用户参考: MongoDB学习札记第二篇之mongodb安全

相关帖子

发表于 2016-6-1 09:58:28 | 显示全部楼层
请教楼主:连接到master的机器时,报错:network error while attempting to run command 'isMaster' on host


是乍回事?
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部