mongo 主从副本集主从可以不同的存储引擎吗

secboy 的BLOG
用户名:secboy
文章数:36
访问量:23158
注册日期:
阅读量:5863
阅读量:12276
阅读量:348446
阅读量:1047843
51CTO推荐博文
Mongodb副本集配置 & &副本集就是有自动故障恢复功能的主从集群。主从集群和副本集最为明显的区别就是副本集没有固定的主节点。可以把副本集当做一个集群,整个集群会选出一个主节点,当其不能正常工作时则会激活其它节点。系统:CentOS 5.6 x86_64mongo版本:mongodb-linux-x86_64-2.0.6.tgz Server1 10.0.1.121:20001server2 10.0.1.212:20001Arbiter 10.0.1.212:20002目录规划:数据目录和日志单分出来Server1:/mongodb/mlogs应用程序日志统计放到/usr/local/mongoServer2:/mongodb/mlogs/arbiter应用程序日志统计放到/usr/local/mongo部署:1.防火墙开启20001端口,关闭selinux2.分别在两台机器上安装mongo服务tar xf mongodb-linux-x86_64-2.0.6.tgz -C /usr/local/mongo3.创建key文件Server1:mkdir /etc/keysecho &test123456& & r0Server2:mkdir /etc/keysecho &test123456& & r1Arbiter:echo &test123456& & r2chmod 600 r0 r1 r24.分别启动Server1和Server2的mongo服务Server1:/usr/local/mongo/bin/mongod --replSet rs1 --keyFile /usr/local/mongo/key/r0 --port 20001 --fork --dbpath=/mongodb/ --logpath /mlogs/Server1.log --fork为后台启动netstat -tunlp | grep mongo &查看端口是否被开启加入到开机启动脚本 /etc/rc.localServer2:/usr/local/mongo/bin/mongod --replSet rs1 --keyFile /usr/local/mongo/key/r1 --port 20001 --fork --dbpath=/mongodb/ --logpath /mlogs/Server2.log netstat -tunlp | grep mongo &查看端口是否被开启/usr/local/mongo/bin/mongod --replSet rs1 --keyFile /usr/local/mongo/key/r2 --port 20002 --fork --dbpath=/arbiter --logpath /mlogs/arbiter.log 加入到开机启动脚本 /etc/rc.local使机器重启后继续生效选项:--only在从节点上指定复制某个数据库(默认复制所有数据库)--slavedelay用在从节点上,当应用主节点的操作时增加延时(秒)--fastsync以主节点的数据快照为基础启动从节点,如果数据目录一开始是主节点的数据快照,从节点用这个选项启动要比完整同步快多了--autoresync如果从节点与主节点不同步,则自动重新同步--oplogSize主节点oplog的大小(MB)5.配置及初始化Replica Sets & config_pongo={..._id:'pongo',members:[...{_id:0,host:'10.0.1.121:20001',priority:1}, & &#如果有多个节点继续往下增加...{_id:1,host:'10.0.1.212:20001',priority:2}, ...{_id:2,host:&10.0.1.212:20002&,arbiterOnly : true}]...}rs.initiate(config_rs1); 初始化Replica Sets注:关于扩展节点和添加仲裁设备请看最下方、副本集中节点的类型standard:常规节点,它存储一份完整的数据副本,参与选举投票可以成为活跃节点。passive:存储了完整的数据副本,参与投票,不能成为活跃节点。arbiter:仲裁者只参与投票,不能接受复制数据,也不能成为活跃节点。每个参与节点(非仲裁者)都有个优先权,优先权为0是被动的,不能成为活跃节点,优先值不为0,则按照大小选出活跃节点。如果2个值一样,则数据最新的为活跃节点。在节点配置中修改priority键,来配置成标准节点或被动节点。注:如果配置成功master会变成PRIMARY &slave会变成SECONDARY6.使用rs.status()查看副本集的状态信息&health& : 1, & & & & & & & & & & & &--1表明正常; 0表明异常、&state& : 1, & & & & & & & & & & & & &-- 1表明是P 2 表明是S&stateStr& : &PRIMARY&, & & &--表明此机器是主库 主从操作日志oplog & &主节点的操作记录称为oplog(operation log)。Oplog存储在一个特殊的数据库中,叫做local。Oplog就在其中的oplog.$main集合里面。Oplog中的每个文档都代表主节点执行的一个操作。MongoDB的 Replica &Set 架构是通过一个日志来存储写操作的,这个日志就叫做”oplog”。oplog.rs是一个固定长度的 capped collection,它存在于”local”数据库中,用于记录Replica Sets操作日志。oplog的大小是可以通过mongod的参数”--oplogSize”来改变oplog的日志大小。Oplog内容样例:rs1:PRIMARY& db.oplog.rs.find() &local数据库中ts: &某个操作的时间戳 & op: &操作类型,只有1字节代码,如下: &i: insert & d: delete & u: update & ns: &命名空间,也就是操作的collection name & o: document的内容 查看master 的oplog元数据信息:rs1:PRIMARY& db.printReplicationInfo() configured oplog size: & &配置的oplog文件大小 & log length start to end: &oplog日志的启用时间段 & oplog first event time: & 产生时间 & oplog last event time: & & &最后一个事务日志的产生时间now: & & & & & & & & & & & & & &现在的时间 &注意:oplog不记录查询操作,oplog存储在固定集合里面,所以它们会自动替换旧的操作。 & & &我们在启动服务器的时候可以用--oplogSize指定这个大小(MB)查看slave的同步状态rs1:PRIMARY& db.printSlaveReplicationInfo() source: & & 从库的IP及端口 & syncedTo: & 目前的同步情况,延迟了多久等信息 主从配置信息主从配置信息 在local库中还有一个集合用于记录主从配置信息system.replsetrs1:PRIMARY& db.system.replset.find() 管理维护Replica Sets读写分离、从库要是进行查询,分担主库的大量的查询请求1)先向主库中插入一条测试数据2)在从库进行查询等操作3)让从库可以读,分担主库的压力执行db.getMongo().setSlaveOk(),我们就可查询从库了故障转移 副本集比传统的Master-Slave 有改进的地方就是它可以进行故障的自动转移,如果我们停掉复制集中的一个成员,那么剩余成员会再自动选举出一个成员,做为主库。1)杀掉Server1 20001 端口的MongoDB2)查看副本集状态 rs.status() 重新同步如果从节点的数据被主节点的数据拉开太远了,则从节点可能跟不上主节点的步子,有可能造成同步失败。解决方法是从新进行同步{&resync&:1},也可以在启动从节点的时候用--autoresync选项让其自动启动。建议oplog的大小是剩余磁盘空间的5%。复制状态和本地数据库本地数据库(local)用来存放所有内部复制状态。其内容不会被复制,从而确保了一个MongoDB服务器只有一个本地数据库。管理诊断当连接到主节点后,使用db.printReplicationInfo函数&db.printReplicationInfo(); 这些信息是oplog的大小和oplog中操作的时间范围。当连接到从节点时,用db.printSlaveReplicationInfo()函数,能得到从节点的一些信息。变更oplog的大小若发现oplog大小不适合,最简单的方法是停掉主节点,删除local数据库的文件,用新的设置(--oplogSize)重新启动。$ rm /data/db/local.*$ ./mongod --master --oplogSize size(新大小)重启主节点后,所有的从节点要用--autoresync重启,否则需要手动同步更新当在副本集中添加和删除节点时,需要的操作流程:1、利用另外一台secondary机器传送数据2、在新机器上中配置文件中添加fastsync=true配置(当需要从有数据中启动节点,那么必须加上fastsync=true,否则启动会报错,如果是从主库直接同步所有数据,那么就不需要添加这个参数)3、启动后,在primary节点中添加节点如:rs.add({_id:2,host:&10.100.100.202:19753&,priority:2) &当我们看到变为secondary后,就一切正常,可以正常提供线上服务了4、通过rs.conf()命令查看现在的节点信息(需要admin库密码权限)5、rs.remove()删除节点(rs.remove(&10.100.100.202:20001&))6、添加arbiter节点:rs.addArb(&10.0.1.123:20001&) &7、添加延时备份机器:rs.add({_id:4,host:&10.0.1.124:20001&,priority:0,slaveDelay:3600});8、当出现这个错误时:replSet error RS102 too stale to catch up,我们可以db.printReplicationInfo() 查看主库、从库的oplog信息;以上为我切换过程中用到的大部分命令,主要还是replica set管理工具,如果能掌握,那么升级、扩容、主库切换都能快速进行!本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&8001人阅读
Mongodb(20)
在前面的文章“”中,我们对如何搭建一个主从结构的Mongodb服务器环境进行了简单的介绍。但是对于主从结构,Mongodb官方并不推荐我们使用了,可能是因为主从模式存在以下两个缺点:
(1)主节点不可用之后,无法自动切换到从节点,无法确保业务访问的不间断性;
(2)所有的读写操作都是对主节点的,造成主节点的访问压力较大;
因此,Mongodb为我们提供了另外一种推荐的使用方法,那就是使用副本集ReplicaSets。在这篇文章中简单描述一下副本集是如何实现的,又是如何解决以上两个问题的。
首先我们先来搭建一个副本集(因为没有那么多服务器机器,这里采用在一台机器上,使用不同的端口号模拟不同的机器上的Mongodb实例)。
第一步:我们在本机的和3333三个端口上启动三个不同的Mongodb实例;
mongod --port 1111 --dbpath F:/mongodb1/data/db --logpath F:/mongodb1/data/log/mongodb.log --replSet test --logappend
mongod --port 2222 --dbpath F:/mongodb2/data/db --logpath F:/mongodb2/data/log/mongodb.log --replSet test --logappend
mongod --port 3333 --dbpath F:/mongodb3/data/db --logpath F:/mongodb3/data/log/mongodb.log --replSet test --logappend
在这里我们启动了三个Mongodb实例,并指定了相应的数据目录和日志目录,需要说明的是,这里需要使用--replSet说明该Mongodb实例是副本集中的节点,而该副本集的名称是test。
第二步:登录到一个实例上,编写指令,将三个不同的Mongodb实例结合在一起形成一个完整的副本集;
config_test={&_id&:&test&,members:[
&& &{_id:0,host:&127.0.0.1:1111&},
&& &{_id:1,host:&127.0.0.1:2222&},
&& &{_id:2,host:&127.0.0.1:3333&},
这里,members中可以包含多个&#20540;,这里列举的就是刚才启动的三个Mongodb实例,并且通过_id字段给副本集起了名字test。
第三步:通过执行下面的命令初始化副本集。
rs.initiate(config_test);
这里使用上面的配置初始化Mongodb副本集。
通过上面的三步,便可以简单的搭建起一个由三个Mongodb实例构成的名称为test的副本集了。如果想查看副本集的状态,可以使用rs.status()命令来进行查看。
副本集现在搭建起来了,那么这个副本集能不能解决我们上面主从模式的两个问题呢?
我们首先从第一个问题开始看,我们将1111端口的Mongodb服务器给关闭,然后我们使用rs.status()命令来查看下,如下所示:
在这里,需要对返回信息中的个别字段进行简单说明,health表示副本集中该节点是否正常,0表示不正常,1表示正常;state表示节点的身份,0表示非主节点,1表示主节点;stateStr用于对节点身份进行字符描述,PRIMARY表示主节点,SECONDARY表示副节点;name是副本集节点的ip和端口信息,等等。
从返回包信息中,可以看到关闭1111端口后,在副本集节点的状态中该节点是不可达的,重新选取产生的主节点是3333端口上启动的Mongodb实例,至于选取的流程在后面的文章中将会讲到,这里简单讲一点,当主节点挂掉之后,其他节点可以发起选举行为,只要在选举过程中某个节点得到副本集节点数一半以上的选票并且没有节点投反对票,那么该节点就可以成为主节点。
在1111端口上的Mongodb实例挂掉之后,3333成为了新的主节点,可以实现自动切换,因此解决了第一个问题。
至于第二个问题,那就是主节点负责所有的读写操作造成主节点压力较大,那么在副本集中如何解决这个问题了呢?正常情况下,我们在Java中访问副本集是这样的,如下所示:
&span style=&font-family:KaiTi_GB2312;font-size:18&&public class TestMongoDBReplSet {
public static void main(String[] args)
List&ServerAddress& addresses = new ArrayList&ServerAddress&();
ServerAddress address1 = new ServerAddress(&127.0.0.1& , 1111);
ServerAddress address2 = new ServerAddress(&127.0.0.1& , 2222);
ServerAddress address3 = new ServerAddress(&127.0.0.1& , 3333);
addresses.add(address1);
addresses.add(address2);
addresses.add(address3);
MongoClient client = new MongoClient(addresses);
DB db = client.getDB( &test&);
DBCollection coll = db.getCollection( &test&);
BasicDBObject object = new BasicDBObject();
object.append( &key1&, &value1& );
coll.insert(object);
DBCursor dbCursor = coll.find();
while (dbCursor.hasNext()) {
DBObject dbObject = dbCursor.next();
System. out.println(dbObject.toString());
} catch (Exception e) {
e.printStackTrace();
但是,上面不能做到在副本集中读写压力分散,其实在代码层面,我们可以设置再访问副本集的时候只从副节点上读取数据。副本集读写分离结构如下图所示:
为了在副本集上实现读写分离,我们需要实现以下两步:
(1)在副本节点上设置setSlaveOk;
(2)代码层面,在读操作过程中设置从副本节点读取数据,如下所示:
&span style=&font-family:KaiTi_GB2312;font-size:18&&public class TestMongoDBReplSet {
public static void main(String[] args)
List&ServerAddress& addresses = new ArrayList&ServerAddress&();
ServerAddress address1 = new ServerAddress(&127.0.0.1& , 1111);
ServerAddress address2 = new ServerAddress(&127.0.0.1& , 2222);
ServerAddress address3 = new ServerAddress(&127.0.0.1& , 3333);
addresses.add(address1);
addresses.add(address2);
addresses.add(address3);
MongoClient client = new MongoClient(addresses);
DB db = client.getDB( &test&);
DBCollection coll = db.getCollection( &test&);
BasicDBObject object = new BasicDBObject();
object.append( &key1&, &value1& );
ReadPreference preference = ReadPreference.secondary();
DBObject dbObject = coll.findOne(object, null , preference);
System. out .println(dbObject);
} catch (Exception e) {
e.printStackTrace();
读参数除了secondary以外,还有其他几个参数可以使用,他们的含义分别如下所示:
primary:默认参数,只从主节点上进行读取操作;
primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。
secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。
secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;
nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。
这样便实现了在副本集上的读写分离了,也就解决了文章最上面所说的第二个问题了。至于副本集中另一个比较重要的地方,主从数据如何同步?如何选举产生新的主节点?副本集中的各个节点如何信息同步?这些问题,将另起一篇文章进行描述,如敢兴趣,可以关注我的博客,谢谢。^_^
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:255321次
积分:4021
积分:4021
排名:第5730名
原创:135篇
转载:82篇
评论:26条
文章:12篇
阅读:2846
阅读:4479
文章:21篇
阅读:86847Mongodb多存储引擎支持机制 | MongoDB中文社区
> Feed" type="application/rss+xml" rel="alternate">MongoDB的主从复制及副本集的replSet配置教程
作者:lucifercn
字体:[ ] 类型:转载 时间:
MongoDB可以在以一个主节点处理客户端请求的情况下以其他节点服务器负责映射主节点上的数据,即为我们通常所说的主从复制功能,这里我们就来共同总结MongoDB的主从复制及副本集的replSet配置教程:
MongoDB的复制功能很重要,尤其是现在的存储引擎还不支持单击持久性。不仅可以用复制来应对故障切换,数据集成,还可以做读扩展,热备份或作为离线批处理的数据源。
1.主从复制
主从复制是MongoDB最常用的复制方式。可用于备份,故障恢复和读扩展等。
基本就是搭建一个主节点和一个或多个从节点,每个从节点需要知道主节点的地址。运行mongod --master启动主服务器。运行mongod --slave --source master_address启动从服务器。
[root@test02 ~]# mongod --fork --dbpath /data/node2 --logpath /data/mongodb.log --port 10001 --logappend --master
从节点选择不同的目录和端口,并且用--source为从节点指明主节点的地址。
[root@test02 ~]# mongod --fork --dbpath /data/node3 --logpath /data/mongodb2.log --port 10002 --logappend --slave --source localhost:10001
所有的从节点都是从主节点复制信息,目前还不能从节点到从节点复制机制,原因是从节点没有自己的oplog。
一个集群中从节点没有明确的限制,但是多个节点对单点主机发起的查询也是吃不消的,不超过12个节点的集群可以良好运转。
(1)--only
在从节点上指定只复制特定某个数据库(默认复制所有数据库)。
(2)--slavedelay
用在从节点上,当应用主节点的操作时增加延迟。这样可以轻松设置延时从节点了,这样的节点对于用户无意间删除重要数据或插入垃圾数据起到防护作用。通过延缓操作,可以有个恢复时间差。
(3)--fastsync
以主节点的数据快照为基础启动从节点。如果数据目录一开始时主节点的数据快照,从节点用这个选项启动要比做完整同步块很多。
(4)--autoresync
如果主节点和从节点不同步,可以自动同步了。
(5)--oplogsuze
主节点oplog的大小(单位是MB)。
1.2 添加以及删除源
cat && /etc/hosts &&EOF
192.168.27.212 test02
192.168.27.213 test03
192.168.27.214 test01
启动从节点时可以用--source指定主节点,也可以在shell中配置这个源。
[root@test02 ~]# mongod --fork --dbpath /data/node3 --logpath /data/mongodb.log --port 10003 --logappend --slave
将192.168.27.212:10001作为源插入到从节点上。
& db.sources.insert({ "host" : "192.168.27.212:10001"});
立即查询会得到插入的文档:
& use local
switched to db local
& db.sources.find();
{ "_id" : ObjectId("530be9cfe66b7"), "host" : "test02:10001"
当同步完成后,文档更新:
& db.sources.find();
{ "_id" : ObjectId("530bf0ab74c79c"), "host" : "test02:10001", "source" : "main", "syncedTo" : Timestamp(, 1), "dbsNextPass" : { "foo" : true, "test" : true } }
副本集就是有自动故障恢复功能的主从集群。主从集群和副本集最为明显的区别就是副本集没有固定的主节点:整个集群会选举出一个主节点,当其不能工作时,则变更到其它节点。副本集总会有一个活跃节点和一个或多个备份节点。
副本集最好的优点就是全自动化的。
mongod --fork --dbpath /data/node2 --logpath /data/mongodb.log --port 10001 --logappend --replSet myrepl/test03:10002
mongod --fork --dbpath /data/node3 --logpath /data/mongodb.log --port 10002 --logappend --replSet myrepl/test02:10001
副本集的亮点是自检测功能:在其中指定单台服务器后,MongoDB会自动搜索并连接其余的节点。
启动几台服务器后,日志会告诉你副本集没有初始化。需要在shell中初始化副本集。
连接任意一个服务器。初始化命令只执行一次:
& db.runCommand({"replSetInitiate" : {
... "_id" : "myrepl",
... "members" : [
"_id" : 1,
"host" : "test02:10001"
"_id" : 2,
"host" : "test03:10002"
"startupStatus" : 4,
"info" : "myrepl/test03:10002",
"errmsg" : "all members and seeds must be reachable to initiate set"
(1)"_id" : "myrepl"&&&& 副本集的名称
(2)"members" : [...]&&& 副本集中的服务器列表,每个服务器至少两个键。
(3)"_id" : N&&&&&&&&&&& 每个服务器唯一的ID
(4)"host" : hostname&&& 这个键指定服务器主机
config = {"_id" : "myrepl",
"members" : [
{"_id" : 0, "host" : "test02:10001"},
{"_id" : 1, "host" : "test03:10002"}
rs.initiate(config);
rs.status();
myrepl:SECONDARY& rs.status();
"set" : "myrepl",
"date" : ISODate("T02:17:39Z"),
"myState" : 2,
"syncingTo" : "test03:10002",
"members" : [
"_id" : 0,
"name" : "test02:10001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 968,
"optime" : Timestamp(, 1),
"optimeDate" : ISODate("T02:14:17Z"),
"errmsg" : "syncing to: test03:10002",
"self" : true
"_id" : 1,
"name" : "test03:10002",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 48,
"optime" : Timestamp(, 1),
"optimeDate" : ISODate("T02:14:17Z"),
"lastHeartbeat" : ISODate("T02:17:38Z"),
"lastHeartbeatRecv" : ISODate("T02:17:39Z"),
"pingMs" : 1,
"syncingTo" : "test02:10001"
如果这时候把primary节点停掉,在secondary节点执行写操作,就会发生如下错误提示:
myrepl:SECONDARY& db.test.insert({name : "baobao"});
not master
如果只有2台Mongodb,配置复制集群还不够安全,需要1个外在角色调整各个节点的角色。
(1)standard:常规节点,存储一份完整的数据副本,参与选举投票,可能称为活跃节点。
(2)passive:存储完整的数据副本,参与投票,不能成为活跃节点。
(3)arbiter:仲裁者只负责投票,不接受复制数据,也不能成为活跃节点。
当Primary宕掉后,可以通过Arbiter在Secodarys中选举一个Primary节点,避免单点故障。
可以增加一个仲裁节点,只负责仲裁,不做数据存储。
mongod --fork --dbpath /data/node1 --logpath /data/mongodb.log --port 10003 --logappend --replSet myrepl/test02:10001,test03:10002
myrepl:PRIMARY& rs.addArb("test01:10003");
{ "ok" : 1 }
查看各节点的状态:
myrepl:PRIMARY& rs.status();
"set" : "myrepl",
"date" : ISODate("T02:30:26Z"),
"myState" : 1,
"members" : [
"_id" : 0,
"name" : "test02:10001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1735,
"optime" : Timestamp(, 1),
"optimeDate" : ISODate("T02:30:09Z"),
"self" : true
"_id" : 1,
"name" : "test03:10002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 204,
"optime" : Timestamp(, 1),
"optimeDate" : ISODate("T02:30:09Z"),
"lastHeartbeat" : ISODate("T02:30:26Z"),
"lastHeartbeatRecv" : ISODate("T02:30:24Z"),
"pingMs" : 1,
"syncingTo" : "test02:10001"
"_id" : 2,
"name" : "test01:10003",
"health" : 1,
"state" : 6,
"stateStr" : "UNKNOWN",
"uptime" : 17,
"lastHeartbeat" : ISODate("T02:30:25Z"),
"lastHeartbeatRecv" : ISODate("T00:00:00Z"),
"pingMs" : 1,
"lastHeartbeatMessage" : "still initializing"
对比三个节点对自身节点性质的判断:
myrepl:PRIMARY& db.isMaster();
"setName" : "myrepl",
"ismaster" : true,
"secondary" : false,
"hosts" : [
"test03:10002",
"test02:10001"
"arbiters" : [
"test01:10003"
"primary" : "test03:10002",
"me" : "test03:10002",
"maxBsonObjectSize" : ,
"maxMessageSizeBytes" : ,
"localTime" : ISODate("T02:32:29.760Z"),
myrepl:SECONDARY& db.isMaster();
"setName" : "myrepl",
"ismaster" : false,
"secondary" : true,
"hosts" : [
"test02:10001",
"test03:10002"
"arbiters" : [
"test01:10003"
"primary" : "test03:10002",
"me" : "test02:10001",
"maxBsonObjectSize" : ,
"maxMessageSizeBytes" : ,
"localTime" : ISODate("T02:33:50.144Z"),
myrepl:SECONDARY& db.isMaster();
"setName" : "myrepl",
"ismaster" : false,
"secondary" : true,
"hosts" : [
"test02:10001",
"test03:10002"
"arbiters" : [
"test01:10003"
"primary" : "test03:10002",
"me" : "test02:10001",
"maxBsonObjectSize" : ,
"maxMessageSizeBytes" : ,
"localTime" : ISODate("T02:33:50.144Z"),
在节点配置中修改priority键,来配置成标准节点或者被动节点。
默认优先级为1,可以是0~1000.
"arbiterOnly"键可以指定仲裁节点。
备份节点会从活跃节点抽取oplog,并执行操作,就像活跃备份系统中的备份服务器一样。活跃节点也会写操作到自己的本地oplog,这样就能成为活跃节点了。oplog中的操作也包括严格递增的序号。通过序号判断数据的时效性。
2.1 故障切换和活跃节点的选举
如果活跃节点坏了,其他节点会选一个新的活跃节点。新的活跃节点由副本集中的大多数选举出来。仲裁节点只负责投票,避免出现僵局。新的节点是优先级最高的节点。
活跃节点使用心跳来跟踪集群中多少节点对其可见,如果不超过半数,则活跃节点自动降为备份节点。可以防止活跃节点一直不放权。
无论活跃节点何时变化,新活跃节点的数据被假定为系统的最新数据。其他节点的操作都会回滚,所有节点连接新的活跃节点后要重新同步。这些节点会查看自己的oplog,找出其中活跃节点没有执行过的操作,然后向活跃节点请求这些操作影响的文档的最新副本。
正在执行重新同步的节点被视为恢复中,在完成这个过程前,不能成为活跃节点候选者。
<span style="color: #ff 关于副本集replSet的配置我们文后会附带详细地讲。
3.在从服务器上执行操作
从节点的主要作用是作为故障恢复机制,以防止主节点数据丢失或者停止服务。
可以在从节点做备份的数据源。也可以用来扩展读取性能,或者进行数据处理。
3.1 读扩展
用MongoDB扩展读取的一种方式就是将查询放在从节点上,减轻主节点的负载。当负载是读密集型时这样非常不错。当是写密集型时,需要用自动分片来扩展。
使用从节点来扩展MongoDB的读取有个要点,就是数据复制并不同步,就是在主节点插入或更新数据口,有片刻从节点的数据不是最新的。
扩展读取需要打开一个特殊选项slaveOkey,告诉从服务器是否可以处理请求。
如果直接在secondary上操作,会发生如下错误:
myrepl:SECONDARY& db.test.find();
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
需要告知Mongodb集群,从哪台机器上进行读操作:
myrepl:SECONDARY& rs.slaveOk();
myrepl:SECONDARY& db.test.find();
{ "_id" : ObjectId("530bfc79eee2c2ce39f9cd95"), "name" : "caoqing" }
{ "_id" : ObjectId("530bfd8fdcb32"), "name" : "xiaobao" }
3.2 用从节点做数据处理
从节点的另外一个服务就是作为一种机制来减轻密集型处理的负载,或作为聚合,避免影响主节点的性能。用--master启动一个普通的从节点,同时使用--master和--slave矛盾。这意味着如果能对从节点进行写入,像平常一样查询,就把它作为一个主节点。从节点还是会不断的从主节点复制数据。这样就可以对从节点执行阻塞操作而不影响主节点的性能。
从节点第一次启动时不能有正在复制的数据库,如果有,数据库就不能完成同步,只能更新。
用这种技术要保证不能对正在复制主节点数据的从节点上的数据库执行写入。从节点不能恢复这些操作,就不能正确的映射主节点。
4.工作原理
MongoDB的复制至少需要两台服务器或者节点,其中一个主节点,负责处理客户端请求,其他的都是从节点,负责映射主节点的数据。主节点记录在其上的所有操作。
从节点定期轮询主节点获取这些操作,然后对数据副本执行这些操作。由于和主节点执行了相同的操作,从节点就能保持和主节点的数据同步。
主节点的操作记录成为polog(operation log)。oplog存储在一个特殊的数据库里,成为local。oplog就在其中的oplog.$main集合里面。oplog的每个文档都代表主节点执行的一个操作。
myrepl:PRIMARY& db.oplog.$main.help();
查看oplog的内容:
myrepl:PRIMARY&
switched to db local
myrepl:PRIMARY&
replset.minvalid
startup_log
system.indexes
system.replset
myrepl:PRIMARY& db.oplog.rs.find();
{ "ts" : Timestamp(, 1), "h" : NumberLong(0), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : Timestamp(, 1), "h" : NumberLong("-4979055"), "v" : 2, "op" : "i", "ns" : "test.test", "o" : { "_id" : ObjectId("530bfc79eee2c2ce39f9cd95"), "name" : "caoqing" } }
{ "ts" : Timestamp(, 1), "h" : NumberLong("403253"), "v" : 2, "op" : "i", "ns" : "test.test", "o" : { "_id" : ObjectId("530bfd8fdcb32"), "name" : "xiaobao" } }
{ "ts" : Timestamp(, 1), "h" : NumberLong("9102944"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "Reconfig set", "version" : 2 } }
myrepl:PRIMARY&
文档包含的键如下:
(1)ts 操作的时间戳。时间戳是一种内部类型,用于跟踪操作执行的时间。有4字节的时间戳和4字节的递增计数器构成。
(2)op 操作类型,只有1字节代码。
(3)ns 执行操作的命名空间。
(4)o& 进一步指定要执行操作的文档。
oplog只记录改变数据库状态的操作。oplog只是作为从节点和主节点保持数据同步的机制。
存储在oplog里的操作不是完全和主节点的操作一模一样的。这些操作在存储之前先做等幂变换,这些操作可以在从服务器端多次执行,只要顺序是对的,就不会有问题。
oplog在固定集合中,不能保证oplog不超过预先设定的大小。需要在创建mongodb服务时指定--oplogSize,参数指定oplog的大小。
一般64bit-linux,分配5%的剩余空间,单位为MB。
从节点第一次启动时,会对主节点数据进行完整的同步。从节点复制主节点上的每一个数据,耗费资源大。同步完成后,从节点查询主节点的oplog,并执行这些操作,保证数据是最新的。
如果从节点的操作被主节点落下太远了,从节点就跟不上同步了,从节点发生宕机或者疲于应付读取时,就会出现这种情况,也会在执行完完整同步后出现这种情况,因为oplog可能已经回滚一圈了。
从节点跟不上同步后,复制就会停下,从节点需要重新做完整的同步。可以用{"resync" : 1}命令手动执行同步,也可以在启动从节点是使用--autoresync选项让其自动同步。重新同步代价高昂,尽量避免,方法就是配置足够大的oplog。
4.3 复制状态和本地数据库
本地数据库用来存放所有内部复制状态,主节点和从节点都有。本地数据就是local,其内容不会被复制。可以确保一盒MongoDB数据库只有一个本地数据库。
本地数据库不限于存放MongoDB的内部状态。如果有不想复制的文档,也可以放在本地数据库的集合里。
主节点上的复制状态还包括从节点上的列表。这个列表存放在slaves集合中:
myrepl:PRIMARY& db.slaves.find();
{ "_id" : ObjectId("530bfbdc911eb0ac3bf2aa8b"), "config" : { "_id" : 1, "host" : "test03:10002" }, "ns" : "local.oplog.rs", "syncedTo" : Timestamp(, 1) }
从节点也在本地数据库中存放状态。在me集合中存放从节点的唯一标识符,在sources集合中存放源或节点的列表。
myrepl:SECONDARY& db.me.find();
{ "_id" : ObjectId("530bfbdc911eb0ac3bf2aa8b"), "host" : "test03" }
主节点和从节点都跟踪从节点的更新状况,这个是通过存放在"syncedTO"中的时间戳来完成的。
4.4 阻塞复制
开发者可以使用getLastrror的'w'参数来确保数据的同步性。运行getLastError会进入阻塞状态,直到N个服务器复制了最新的写入操作为止。
检查本连接的上一次数据库操作的错误。
myrepl:PRIMARY& db.runCommand("getlasterror")
"lastOp" : Timestamp(0, 0),
"connectionId" : 3525,
"err" : null,
指定"w"选项后,可以使用"wtimeout"选项,表示以毫秒为单位的超时。
阻塞复制会导致写操作明显变慢,尤其是"w"的值比较大时。
MongoDB包含很多有用的管理工具,用以查看复制的状态。
db.printReplicationInfo()
命令查看oplog状态。
myrepl:PRIMARY& db.printReplicationInfo();
configured oplog size: 997.1MB
log length start to end: 1126secs (0.31hrs)
oplog first event time: Tue Feb 25 :23 GMT+0800 (CST)
oplog last event time: Tue Feb 25 :09 GMT+0800 (CST)
Wed Feb 26 :23 GMT+0800 (CST)
输出信息包括oplog日志的大小,操作日志记录的起始时间。
查看从库同步状态。
myrepl:PRIMARY& db.printSlaveReplicationInfo();
source: test03:10002
syncedTo: Tue Feb 25 :09 GMT+0800 (CST)
= 56533 secs ago (15.7hrs)
source: test01:10003
no replication info, yet. State: ARBITER
输出信息包括从库的主机名,port信息等。
5.2 变更oplog的大小
如果发现oplog大小不合适,最简单的方法就是停掉主节点,删除local数据库的文件,用心的设置重新启动。
# rm -rf /data/node2/local*
为大型的oplog预分配空间非常耗费时间,且可能导致主节点停机时间增加,尽可能的手动预分配数据文件。
5.3 复制的认证问题
如果在复制中使用了认证,还需要做些配置,使得从节点可以访问俄主节点的数据。在主节点和从节点都需要在本地数据库增加用户,每个节点的用户名和口令相同。
从节点连接到主节点是,会用存储在local.system.users中的用户认证。最先尝试"repl"用户,如果没有,则用local.system.users中的第一个可用用户。
PS:副本集replSet具体配置
1.MongoDB:创建Replica Set
1.1 分别启动两台mongodb数据库
mongod --fork --dbpath /data/node2 --logpath /data/mongodb.log --port 10001 --logappend --replSet myrepl/test03:10002
mongod --fork --dbpath /data/node3 --logpath /data/mongodb.log --port 10002 --logappend --replSet myrepl/test02:10001
1.2 初始化副本集
config = {"_id" : "myrepl",
"members" : [
{"_id" : 0, "host" : "test02:10001"},
{"_id" : 1, "host" : "test03:10002"}
rs.initiate(config);
rs.status();
myrepl:SECONDARY& rs.status();
"set" : "myrepl",
"date" : ISODate("T02:17:39Z"),
"myState" : 2,
"syncingTo" : "test03:10002",
"members" : [
"_id" : 0,
"name" : "test02:10001",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 968,
"optime" : Timestamp(, 1),
"optimeDate" : ISODate("T02:14:17Z"),
"errmsg" : "syncing to: test03:10002",
"self" : true
"_id" : 1,
"name" : "test03:10002",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 48,
"optime" : Timestamp(, 1),
"optimeDate" : ISODate("T02:14:17Z"),
"lastHeartbeat" : ISODate("T02:17:38Z"),
"lastHeartbeatRecv" : ISODate("T02:17:39Z"),
"pingMs" : 1,
"syncingTo" : "test02:10001"
1.3 增加一个仲裁节点,只负责仲裁,不做数据存储。
mongod --fork --dbpath /data/node1 --logpath /data/mongodb.log --port 10003 --logappend --replSet myrepl/test02:10001,test03:10002
myrepl:PRIMARY& rs.addArb("test01:10003");
{ "ok" : 1 }
2 MongoDB:Replica Set 增加节点
2.1 现有环境:
myrepl:PRIMARY& rs.conf();
"_id" : "myrepl",
"version" : 2,
"members" : [
"_id" : 0,
"host" : "test02:10001"
"_id" : 1,
"host" : "test03:10002"
"_id" : 2,
"host" : "test01:10003",
"arbiterOnly" : true
现有三个节点,两台standard节点,一台arbiter节点。
2.2 增加节点
2.2.1 创建数据目录和日志文件:
mkdir -p /data/node/
touch /data/mongodb.log
2.2.2 安装mongodb:
tar zxf mongodb-linux-x86_64-2.4.9.tgz
mv mongodb-linux-x86_64-2.4.9 /opt/mongodb
echo "export PATH=$PATH:/opt/mongodb/bin" &&/etc/profile
source /etc/profile
mongod --config ~/.mongodb.conf
2.2.3 创建新从节点配置文件:
cat && ~/.mongodb.conf &&EOF
fork = ture
port = 10005
dbpath = /data/node
logpath = /data/mongodb.log
logappend = true
replSet = myrepl
2.2.4 更改节点信息
cat /etc/sysconfig/network
cat && /etc/hosts && EOF
192.168.27.214 test01
192.168.27.212 test02
192.168.27.213 test03
192.168.27.215 test04
192.168.27.216 test05
2.2.5 判断节点是否是主节点
myrepl:PRIMARY& rs.isMaster();
"setName" : "myrepl",
"ismaster" : true,
"secondary" : false,
"hosts" : [
"test02:10001",
"test03:10002"
"arbiters" : [
"test01:10003"
"primary" : "test02:10001",
"me" : "test02:10001",
"maxBsonObjectSize" : ,
"maxMessageSizeBytes" : ,
"localTime" : ISODate("T19:23:22.286Z"),
2.2.6 增加新从节点到replSet
myrepl:PRIMARY& rs.add("192.168.27.215:10004");
# 增加arbiter节点的方法:myrepl:PRIMARY& rs.addArb("test01:10003");
2.2.7 再次查看Replica Set状态信息
myrepl:PRIMARY& rs.conf();
"_id" : "myrepl",
"version" : 3,
"members" : [
"_id" : 0,
"host" : "test02:10001"
"_id" : 1,
"host" : "test03:10002"
"_id" : 2,
"host" : "test01:10003",
"arbiterOnly" : true
"_id" : 3,
"host" : "192.168.27.215:10004"
3.1 主节点插入数据
myrepl:PRIMARY& db.test.insert({"name" : "xiaohuan", "age" : 30});
3.2 从节点查询数据
myrepl:SECONDARY& rs.slaveOk();
myrepl:SECONDARY& db.test.find();
{ "_id" : ObjectId("530bfc79eee2c2ce39f9cd95"), "name" : "caoqing" }
{ "_id" : ObjectId("530bfd8fdcb32"), "name" : "xiaobao" }
{ "_id" : ObjectId("530ceeda279900"), "name" : "xiaohuan", "age" : 30 }
4. 把standard节点变为passive节点
myrepl:PRIMARY& cfg = rs.conf()
"_id" : "myrepl",
"version" : 3,
"members" : [
"_id" : 0,
"host" : "test02:10001"
"_id" : 1,
"host" : "test03:10002"
"_id" : 2,
"host" : "test01:10003",
"arbiterOnly" : true
"_id" : 3,
"host" : "192.168.27.215:10004"
myrepl:PRIMARY& cfg.members[3].priority = 0;
myrepl:PRIMARY& rs.reconfig(cfg);
myrepl:PRIMARY& rs.conf();
"_id" : "myrepl",
"version" : 4,
"members" : [
"_id" : 0,
"host" : "test02:10001"
"_id" : 1,
"host" : "test03:10002"
"_id" : 2,
"host" : "test01:10003",
"arbiterOnly" : true
"_id" : 3,
"host" : "192.168.27.215:10004",
"priority" : 0
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 mongo 主从同步 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信