MongoDB高可用复制集特性初探
来源:互联网 发布:靠谱的淘宝二手显卡店 编辑:程序博客网 时间:2024/06/04 11:17
MongoDB高可用复制集特性初探
近年来,NoSQL风头甚健,对传统数据库厂商发起不断冲击。众多NoSQL解决方案中,最出名的则得数MongoDB。虽然该项目背后的厂商目前收入菲薄(据说一年收入才千万美元),但去年10月就成功拿到1.5亿的融资,公司估值也达到了12亿。知名数据库 DB-Engines Ranking 在2014年1月7号发布的2013最受欢迎数据库排行榜,更将其评选为年度数据库魁首。
鉴于MongoDB这么火热,那很有必要与时俱进,学习研究一番。MongoDB官网文档非常详尽丰富,其特性、CRUD操作、Aggregation框架等,都有翔实文档和示例。在这里就先研究一下其水平扩展(Scale out)的配置操作和管理。
MongoDB有3中配置方式:单机、主从和复制集。从机制设计看,后者显然更优秀,可以容易的实现数据的读写分离,并保持数据库集群自动容灾和高可用性。
下面,通过实际操作来进行演示。
系统:Mac OS
MongoDB:2.4.9
安装:从官网下载压缩包,解压。完毕。
启动数据库集群和复制集
集群里面包含3个节点:Node1,Node2,Node3
由于是在单机上实验,其实是启动3个MongoDB示例,并分别指派不同的数据库存放目录和日志。命令如下:
bin / mongod -- dbpathnode1 -- port 10001 --replSet myMongo -- nojournal -- fork -- logpath node1. log
about to fork child process , waiting until serveris ready for connections .
forked process : 410
all output going to : / Users / yuanlinwu / mongodb / node1 . log
child process started successfully, parent exiting
启动成功,再启动两个实例。
bin / mongod -- dbpathnode2 -- port 10002 --replSet myMongo -- nojournal -- fork -- logpath node2. log
bin / mongod -- dbpathnode3 -- port 10003 --replSet myMongo -- nojournal -- fork -- logpath node3. log
启动复制集后,登录其中一个节点
$ bin / mongo localhost: 10001
MongoDB shell version : 2.4.9
connecting to : localhost : 10001 / test
Server has startup warnings:
Tue Jan 14 16 :44 : 20.966 [ initandlisten]
Tue Jan 14 16 :44 : 20.966 [ initandlisten] * * WARNING : soft rlimits too low .Number of files is 256, should be at least1000
这时候,我们看到一警告:soft rlimits too low。MongoDB官网解释,这个原因是操作系统的保守设定造成的,与MongoDB无关,因此这里也就不管了。
这时候,我们还可以通过网页版管理界面查看MongoDB的状态,网址为 host:11001(端口号+1000)。
查看复制集状态
反馈结果:
"startupStatus" : 3 ,
"info" : "run rs.initiate(...) if not yet done for the set",
"errmsg" : "can't get local.system.replset config from self or any seed (EMPTYCONFIG)"
从提示信息看出,我们还尚未对复制集进行初始化。
初始化操作:
设定集群信息:
replSet = { "_id" :"myMongo" , "members" : [ { "_id" : 1 ,"host" : "localhost:10001" } , { "_id" : 2 ,"host" : "localhost:10002" } , { "_id" : 3 ,"host" : "localhost:10003" } ] }
> rs . initiate (replSet )
"info" : "Config now saved locally. Should come online in about a minute.",
反馈信息:
"info" : "Config now saved locally. Should come online in about a minute.",
说明复制集配置已经保存成功。这时候还可以通过Log日志查看,复制集初始化的相关信息。
新建一个客户端来连接node1,我们会发现,提示信息已经有变化了,提示符前变成了Primary或Secondary。
$ bin / mongo localhost: 10001
myMongo : PRIMARY > rs . status ( )
"set" : "myMongo" ,
"date" : ISODate ( "2014-01-14T09:03:46Z") ,
"name" : "localhost:10001" ,
"stateStr" : "PRIMARY" ,
"optime" : Timestamp ( 1389690019 , 1 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:00:19Z" ) ,
"name" : "localhost:10002" ,
"stateStr" : "SECONDARY" ,
"optime" : Timestamp ( 1389690019 , 1 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:00:19Z" ) ,
"lastHeartbeat" : ISODate ("2014-01-14T09:03:45Z" ) ,
"lastHeartbeatRecv" : ISODate ("2014-01-14T09:03:46Z" ) ,
"syncingTo" : "localhost:10001"
"name" : "localhost:10003" ,
"stateStr" : "SECONDARY" ,
"optime" : Timestamp ( 1389690019 , 1 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:00:19Z" ) ,
"lastHeartbeat" : ISODate ("2014-01-14T09:03:45Z" ) ,
"lastHeartbeatRecv" : ISODate ("2014-01-14T09:03:45Z" ) ,
"syncingTo" : "localhost:10001"
导入数据
这时候,我们向数据库中插入一些数据,看看是不是在各个节点都自动进行了复制。 为感性了解一下MongoDB的数据写入能力,我这里用的数据集来自于 《Mining the Social Web》 中安然公司的邮件数据集,下载位置: https://github.com/ptwobrussell/Mining-the-Social-Web-2nd-Edition/tree/master/ipynb/resources/ch06-mailboxes/data
新开一个命令终端,执行导入命令:
$ bin / mongoimport -- host localhost -- port10001 -- db enron --collection mails -- file enron . mbox . json
Tue Jan 14 17 :15 : 40.009 Progress :35267686 / 151226171 23 %
Tue Jan 14 17 :15 : 40.009 9600 3200/ second
Tue Jan 14 17 :15 : 43.014 Progress :86409448 / 151226171 57 %
Tue Jan 14 17 :15 : 43.014 23500 3916/ second
Tue Jan 14 17 :15 : 46.014 Progress :143605879 / 151226171 94 %
Tue Jan 14 17 :15 : 46.014 38900 4322/ second
Tue Jan 14 17 :15 : 46.449 check 941299
Tue Jan 14 17 :15 : 46.449 imported 41299objects
包含4万多个对象体积约151Mb的json文件,大概用了6秒钟插入完毕。
开启新客户端进入node 2,查看插入node1的数据是否被复制到node2。
$ bin / mongo localhost: 10002
myMongo : SECONDARY > show dbs
enron 0.453125GB
local 0.328125GB
这时候,我们看到enron数据库已经出现了,数据库体积与node1一致。之前说的,MongoDB可以通过复制集来实现读写分离,那我们来操作一下。
myMongo : SECONDARY > use enron
switched to db enron
myMongo : SECONDARY > show collections
Tue Jan 14 17 :26 : 43.721 error :{ "$err" : "not master and slaveOk=false", "code" : 13435 }at src / mongo /shell / query . js: 128
出现错误,提示slaveOk=false。MongoDB默认设置,SECONDARY节点是不允许读的,需要人工打开或在配置文件里面设置。
myMongo : SECONDARY > rs . slaveOk ( ) ;
myMongo : SECONDARY > show collections
myMongo : SECONDARY > db . mails . findOne ( )
"_id" : ObjectId ( "52d50039242bb597037cb808") ,
执行rs.slaveOk()命令后,已经可以进行读操作了。
复制集高可用性实验
下面,就到本文的重点部分了。
实验步骤:
1、人为让Primary节点失败倒掉,看MongoDB集群能否正常继续运行
2、将失败的节点,重启修复后,恢复到集群内
在命令终端里查看mongod进程,找到primary node进程后杀掉。
$ ps - A | grep mongod
410 ? ? 0 :30.61 bin / mongod --dbpath node1 -- port 10001-- replSet myMongo -- nojournal-- fork -- logpath node1. log
424 ? ? 0 :28.20 bin / mongod --dbpath node2 -- port 10002-- replSet myMongo -- nojournal-- fork -- logpath node2. log
427 ? ? 0 :28.40 bin / mongod --dbpath node3 -- port 10003-- replSet myMongo -- nojournal-- fork -- logpath node3. log
1197 ttys002 0 : 00.00 grep mongod
杀掉 410进程
kill -9 3925
在之前的Primary Shell中执行命令
myMongo : PRIMARY > rs . status ( )
Tue Jan 14 17 :36 : 43.572 DBClientCursor :: init call ( ) failed
Tue Jan 14 17 :36 : 43.572 Error :error doing query : failedat src / mongo /shell / query . js: 78
Tue Jan 14 17 :36 : 43.573 trying reconnectto localhost : 10001
Tue Jan 14 17 :36 : 43.573 reconnect localhost: 10001 failed couldn ' t connect to server localhost: 10001
这时候,我们看到已经不能连接 localhost:10001 了。那我们在Secondary 中执行rs.status()
"set" : "myMongo" ,
"date" : ISODate ( "2014-01-14T09:38:03Z") ,
"name" : "localhost:10001" ,
"stateStr" : "(not reachable/healthy)" ,
"optime" : Timestamp ( 1389690946 , 2490 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:15:46Z" ) ,
"lastHeartbeat" : ISODate ("2014-01-14T09:38:02Z" ) ,
"lastHeartbeatRecv" : ISODate ("2014-01-14T09:36:28Z" ) ,
"name" : "localhost:10002" ,
"stateStr" : "PRIMARY" ,
"optime" : Timestamp ( 1389690946 , 2490 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:15:46Z" ) ,
"name" : "localhost:10003" ,
"stateStr" : "SECONDARY" ,
"optime" : Timestamp ( 1389690946 , 2490 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:15:46Z" ) ,
"lastHeartbeat" : ISODate ("2014-01-14T09:38:02Z" ) ,
"lastHeartbeatRecv" : ISODate ("2014-01-14T09:38:01Z" ) ,
"lastHeartbeatMessage" : "syncing to: localhost:10002",
"syncingTo" : "localhost:10002"
这时候看到,复制集成员 localhost:10001 的状态为(not reachable/healthy),说明原来的Primary已经倒掉了。注意到这时候我们在操作的是Secondary,那是不是说复制集里面已经没有Primary了呢?考虑到我们的环境里面有3个节点,我们连接node3看看。
$ bin / mongo localhost: 10003
MongoDB shell version : 2.4.9
connecting to : localhost : 10003 / test
Server has startup warnings:
myMongo : SECONDARY > quit ( )
我们看到node3依然是SECONDARY,那PRIMARY跑哪里去了?重新连接node2
$ bin / mongo localhost: 10002
MongoDB shell version : 2.4.9
connecting to : localhost : 10002 / test
myMongo : PRIMARY >
哈,node2已经变成了复制集中的PRIMARY!
事实上,MongoDB复制集中,如果集群的节点数为奇数个时,复制集中的Primary节点失败,会自动从Secondary节点中推选除一个来顶替原来的Primary。而节点为偶数个时,则需要一个节点担任仲裁者。具体的介绍,可以参考:
接下来,我们试图恢复node1。
恢复失败节点
首先,删除node1数据文件夹下面的锁文件,mongod.lock
然后,执行修复命令
$ bin / mongod --dbpath node1 -- port 10001-- replSet myMongo -- nojournal-- fork -- logpath node1. log -- repair
about to fork child process , waiting until serveris ready for connections .
forked process : 1236
all output going to : / Users / yuanlinwu / mongodb / node1 . log
log file [ / Users/ yuanlinwu / mongodb /node1 . log ] exists; copied to temporary file[ / Users / yuanlinwu/ mongodb / node1 .log . 2014 - 01 - 14T09 - 47 - 45]
child process started successfully, parent exiting
启动失败节点
$ bin / mongod --dbpath node1 -- port 10001-- replSet myMongo -- nojournal-- fork -- logpath node1. log
about to fork child process , waiting until serveris ready for connections .
forked process : 1240
all output going to : / Users / yuanlinwu / mongodb / node1 . log
log file [ / Users/ yuanlinwu / mongodb /node1 . log ] exists; copied to temporary file[ / Users / yuanlinwu/ mongodb / node1 .log . 2014 - 01 - 14T09 - 48 - 11]
child process started successfully, parent exiting
从反馈信息看到,已经成功把失败的node1节点启动了。
在mongo终端查看复制集状态
myMongo : PRIMARY > rs . status ( )
"set" : "myMongo" ,
"date" : ISODate ( "2014-01-14T09:49:07Z") ,
"name" : "localhost:10001" ,
"stateStr" : "SECONDARY" ,
"optime" : Timestamp ( 1389690946 , 2490 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:15:46Z" ) ,
"lastHeartbeat" : ISODate ("2014-01-14T09:49:07Z" ) ,
"lastHeartbeatRecv" : ISODate ("2014-01-14T09:49:07Z" ) ,
"lastHeartbeatMessage" : "syncing to: localhost:10002",
"syncingTo" : "localhost:10002"
"name" : "localhost:10002" ,
"stateStr" : "PRIMARY" ,
"optime" : Timestamp ( 1389690946 , 2490 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:15:46Z" ) ,
"name" : "localhost:10003" ,
"stateStr" : "SECONDARY" ,
"optime" : Timestamp ( 1389690946 , 2490 ) ,
"optimeDate" : ISODate ( "2014-01-14T09:15:46Z" ) ,
"lastHeartbeat" : ISODate ("2014-01-14T09:49:06Z" ) ,
"lastHeartbeatRecv" : ISODate ("2014-01-14T09:49:07Z" ) ,
"syncingTo" : "localhost:10002"
从复制集状态信息中,我们看到成员localhost:10001 已经成功恢复加入到myMongo复制集,并且向Primary进行同步。
关闭数据库
在节点Shell执行关闭服务器命令,进行干净的关机。
use admin
db.shutdownServer()
小结
从上面的操作可看出,MongoDB在集群管理、高可用性方面,的确具有易用方便的优势。其他特性,待有空后进一步研究。
- MongoDB高可用复制集特性初探
- mongodb高可用部署有主从复制和复制集
- 利用Mongodb的复制集搭建高可用分片,Replica Sets + Sharding的搭建过程
- 利用Mongodb的复制集搭建高可用分片,Replica Sets + Sharding的搭建过程
- 利用Mongodb的复制集搭建高可用分片,Replica Sets + Sharding的搭建过程
- Mongodb高可用架构
- mongoDB高可用
- Mongodb Replica Set高可用
- Mongodb Replica Set高可用
- 搭建高可用mongodb集群
- 高可用的MongoDB集群
- mongodb高可用Replica Set
- 搭建高可用MongoDB集群
- 搭建高可用mongodb集群
- 搭建高可用MongoDB集群
- 搭建高可用mongoDB集群
- MongoDB如何确保高可用
- Mongodb Replica Set高可用
- 进程和线程
- 使用TextView实现跑马灯效果
- OS X 10.11.1 安装CocoaPods
- 数据结构、算法与应用 (C++描述) 第二版 1.6
- 取每组数据的第一条记录的SQL语句
- MongoDB高可用复制集特性初探
- 链队列
- 大鱼吃小鱼游戏-baby.js
- Ceph 网络模块(4)——SimpleMessenger数据结构及代码流程分析
- SQL注入漏洞全接触--入门篇
- 多继承的构造顺序
- 循环队列
- 矫情的C++——不明确行为(undefined behavior)
- 烦请哪位老大可以介绍一下C语言中的内存对齐的原理和实现?