MongoDB分片实验

下面来实战一下如何搭建高可用的mongodb集群:

首先确定各个组件的数量,mongos 3个, config server 3个,数据分3片 shard server 3个,每个shard 有一个副本一个仲裁也就是 3 * 2 = 6 个,总共需要部署15个实例。这些实例可以部署在独立机器也可以部署在一台机器,我们这里测试资源有限,只准备了 3台机器,在同一台机器只要端口不同就可以,看一下物理部署图:

5

实验环境:

Vmware 10 + 32位CentOS_6.5 + mongodb-3.2(32位)
3台虚拟机:192.168.192.132、192.168.192.133、192.168.192.134

1.创建如下目录:

/data/mongodbtest/mongos/log #mongos日志目录
/data/mongodbtest/config/data #config server数据目录
/data/mongodbtest/config/log #config server日志目录
/data/mongodbtest/shard1|2|3/data #分片1|2|3数据目录
/data/mongodbtest/shard1|2|3/log #分片1|2|3日志目录

2.启动配置服务器:

mongod --configsvr --dbpath /data/mongodbtest/config/data --port 21000 --logpath /data/mongodbtest/config/log/config.log --storageEngine=mmapv1 --fork

说明:测试机上加上这个参数【因为32位系统不支持默认的引擎】:--storageEngine=mmapv1

3. 启动mongos服务器:

mongos --configdb 192.168.192.132:21000,192.168.192.133:21000,192.168.192.134:21000 --port 20000 --logpath  /data/mongodbtest/mongos/log/mongos.log  --fork

4. 配置各分片的副本集:

mongod --shardsvr --replSet shard1 --port 22001 --dbpath /data/mongodbtest/shard1/data --storageEngine=mmapv1 --logpath /data/mongodbtest/shard1/log/shard1.log --fork --nojournal  --oplogSize 10
mongod --shardsvr --replSet shard2 --port 22002 --dbpath /data/mongodbtest/shard2/data --storageEngine=mmapv1 --logpath /data/mongodbtest/shard2/log/shard2.log --fork --nojournal  --oplogSize 10
mongod --shardsvr --replSet shard3 --port 22003 --dbpath /data/mongodbtest/shard3/data --storageEngine=mmapv1 --logpath /data/mongodbtest/shard3/log/shard3.log --fork --nojournal  --oplogSize 10
说明:测试机上加上这个参数【因为32位系统不支持默认的引擎】:--storageEngine=mmapv1

5. 登陆任意一台分片机配置副本集:[如:登陆192.168.192.132]

> mongo 127.0.0.1:22001

> use admin

> config = { _id:"shard1", members:[
{_id:0,host:"192.168.192.132:22001"},
{_id:1,host:"192.168.192.133:22001"},                      {_id:2,host:"192.168.192.134:22001",arbiterOnly:true}
]}

> rs.initiate(config);

> exit;

> mongo 127.0.0.1:22002

> use admin

> config = { _id:"shard2", members:[
{_id:0,host:"192.168.192.132:22002"},
{_id:1,host:"192.168.192.133:22002"},
{_id:2,host:"192.168.192.134:22002",arbiterOnly:true}
]}

> rs.initiate(config);

> exit;

> mongo 127.0.0.1:22003

> use admin

> config = { _id:"shard3", members:[
{_id:0,host:"192.168.192.132:22003"},{_id:1,host:"192.168.192.133:22003"},
{_id:2,host:"192.168.192.134:22003",arbiterOnly:true}
]}

> rs.initiate(config);

> exit;

6. 建立mongos与分片之间的联系:

mongo  127.0.0.1:20000

mongos > use admin

mongos> db.runCommand( { addshard : "shard1/192.168.192.132:22001,192.168.192.133:22001,192.168.192.134:22001"});

mongos> db.runCommand( { addshard : "shard2/192.168.192.132:22002,192.168.192.133:22002,192.168.192.134:22002"}); 

mongos > db.runCommand( { addshard : "shard3/192.168.192.132:22003,192.168.192.133:22003,192.168.192.134:22003"});   

mongos > db.runCommand( { listshards : 1 } );//查看分片列表

mongos > db.runCommand({enablesharding:"testdb"});//测试,设置要分片的库testdb

mongos > db.runCommand({shardcollection:"testdb.table1",key:{id:1}});//设置要分片的集合testdb.table1

7. 实践中遇到的问题:

mongos启动失败:

(1)报错:

Error initializing sharding system: ConfigServersInconsistent: hash from 192.168.192.132:21000: { chunks: "d41d8cd98f00b204e9800998ecf8427e", shards: "d41d8cd98f00b204e9800998ecf8427e", version: "34eb51f63387b033ac38ec27ab15aba4" } vs hash from 192.168.192.133:21000: {}

原因:

各配置服初始配置不一致,需要删除初始化配置文件重新启动,以保持多个配置服的一致性。

对策:

删除所有配置服务器data中的config.*,然后kill -9掉配置服启动进程重新启动,此时查看mongos.log发现报错消失,出现新的报错(2)

(2)报错:

Error initializing sharding system: DistributedClockSkewed: clock skew of the cluster 192.168.192.132:21000,192.168.192.133:21000,192.168.192.134:21000 is too far out of bounds to allow distributed locking.

原因:各配置服的linux时间不一致。

对策:使用ntpdate同步时间,使各配置服的linux时间保持一致:ntpdate  202.108.6.95

8.参考:

http://www.lanceyan.com/tech/arch/mongodb_shard1.html

MongoDB分片原理

在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的。而mongodb主打的就是海量数据架构,他不能解决海量数据怎么行!不行!“分片”就用这个来解决这个问题。

传统数据库怎么做海量数据读写?其实一句话概括:分而治之。上图看看就清楚了,如下 taobao岳旭强在infoq中提到的 架构图:

1

上图中有个TDDL,是taobao的一个数据访问层组件,他主要的作用是SQL解析、路由处理。根据应用的请求的功能解析当前访问的sql判断是在哪个业务数据库、哪个表访问查询并返回数据结果。具体如图:

2

说了这么多传统数据库的架构,那Nosql怎么去做到了这些呢?mysql要做到自动扩展需要加一个数据访问层用程序去扩展,数据库的增加、删除、备份还需要程序去控制。一但数据库的节点一多,要维护起来也是非常头疼的。不过mongodb所有的这一切通过他自己的内部机制就可以搞定!顿时石化了,这么牛X!还是上图看看mongodb通过哪些机制实现路由、分片:

3

从图中可以看到有四个组件:mongos、config server、shard、replica set。

mongos,数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。

config server,顾名思义为配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,这个可不能丢失!就算挂掉其中一台,只要还有存货, mongodb集群就不会挂掉。

shard,这就是传说中的分片了。上面提到一个机器就算能力再大也有天花板,就像军队打仗一样,一个人再厉害喝血瓶也拼不过对方的一个师。俗话说三个臭皮匠顶个诸葛亮,这个时候团队的力量就凸显出来了。在互联网也是这样,一台普通的机器做不了的多台机器来做,如下图:

4

一台机器的一个数据表 Collection1 存储了 1T 数据,压力太大了!在分给4个机器后,每个机器都是256G,则分摊了集中在一台机器的压力。也许有人问一台机器硬盘加大一点不就可以了,为什么要分给四台机器呢?不要光想到存储空间,实际运行的数据库还有硬盘的读写、网络的IO、CPU和内存的瓶颈。在mongodb集群只要设置好了分片规则,通过mongos操作数据库就能自动把对应的数据操作请求转发到对应的分片机器上。在生产环境中分片的片键可要好好设置,这个影响到了怎么把数据均匀分到多个分片机器上,不要出现其中一台机器分了1T,其他机器没有分到的情况,这样还不如不分片!

replica set,上两节已经详细讲过了这个东东,怎么这里又来凑热闹!其实上图4个分片如果没有 replica set 是个不完整架构,假设其中的一个分片挂掉那四分之一的数据就丢失了,所以在高可用性的分片架构还需要对于每一个分片构建 replica set 副本集保证分片的可靠性。生产环境通常是 2个副本 + 1个仲裁。

 

MongoDB副本集心跳和同步机制

MongoDB建议副本集成员为奇数。最多12个副本节点最多7个节点参与选举。限制副本节点的数量,主要是因为一个集群中过多的副本节点,增加了复制的成本,反而拖累了集群的整体性能。太多的副本节点参与选举,也会增加选举的时间。MongoDB官方推荐节点数量为奇数。主要在于副本集常常为分布式,可能位于不同的IDC。如果为偶数,可能出现每个IDC的节点数一样,从而如果网络故障,那么每个IDC里的节点都无法选出主节点,导致全部不可用的情况。比如,节点数为4,分处于2个IDC,现在IDC之间的网络出现故障,每个IDC里的节点都没有大于2,所以副本集没有主节点,变成只读。

MongoDB节点会向副本集中的其他节点每两秒就会发送一次pings包,如果其他节点在10秒钟之内没有返回就标示为不能访问。每个节点内部都会维护一个状态映射表,表明当前每个节点是什么角色、日志时间戳等关键信息。如果是主节点,除了维护映射表外还需要检查自己能否和集群中内大部分节点通讯,如果不能则把自己降级为secondary只读节点。

副本集同步分为初始化同步和keep复制。初始化同步指全量从主节点同步数据,如果主节点数据量比较大同步时间会比较长。而keep复制指初始化同步过后,节点之间的实时同步一般是增量同步。初始化同步不只是在第一次才会被触发,有以下两种情况会触发:

secondary第一次加入,这个是肯定的。

secondary落后的数据量超过了oplog的大小,这样也会被全量复制。

那什么是oplog的大小?前面说过oplog保存了数据的操作记录,secondary复制oplog并把里面的操作在secondary执行一遍。但是oplog也是mongodb的一个集合,保存在local.oplog.rs里,但是这个oplog是一个capped collection也就是固定大小的集合,新数据加入超过集合的大小会覆盖。所以这里需要注意,跨IDC的复制要设置合适的oplogSize,避免在生产环境经常产生全量复制。oplogSize 可以通过–oplogSize设置大小,对于linux 和windows 64位,oplog size默认为剩余磁盘空间的5%。

同步也并非只能从主节点同步,假设集群中3个节点,节点1是主节点在IDC1,节点2、节点3在IDC2,初始化节点2、节点3会从节点1同步数据。后面节点2、节点3会使用就近原则从当前IDC的副本集中进行复制,只要有一个节点从IDC1的节点1复制数据。

设置同步还要注意以下几点:

secondary不会从delayed和hidden成员上复制数据。

只要是需要同步,两个成员的buildindexes必须要相同无论是否是true和false。buildindexes主要用来设置是否这个节点的数据用于查询,默认为true。

如果同步操作30秒都没有反应,则会重新选择一个节点进行同步。

附:副本集不可用的应对之道:

当节点发生故障,或者因为网络原因失联,造成余下的节点小于等于副本集总节点数的一半,那么整个副本集中都不再存在主节点,原来的主节点会降级成为从节点!此时整个副本集呈现只读状态,也即不再可用。
当出现这种瘫痪情况,目前我还没找到将某个从节点切换为主节点的方法,也许本来就不存在这种方法。因为这和MongoDB的Primary选举策略有关:如果情况不是Secondary宕机,而是网络断开,那么可能出现位于不同IDC的节点各自选取自己为Primary。这样在网络恢复后就需要处理复杂的一致性问题。而且断开的时间越长,时间越复杂。所以MongoDB选择的策略是如果集群中存活节点数量不够,则不选取Primary。
所以
1) 一方面要极力避免出现这种存活节点不够半数的情况,在规划副本集的时候就注意:
设置仲裁节点。
节点总数为奇数,且主节点所在的IDC,拥有超过半数的节点数量
2) 注意对节点的备份,必要时可以对节点进行恢复
也可以按照相同配置建立一个全新的从节点,恢复副本集后,系统会自动同步数据。但猜测数据量比较大的情况下,耗时会比较长,所以平时对从节点进行备份,还是有必要。

MongoDB副本集

MongoDB的副本集不同于以往的主从模式。
在集群Master故障的时候,副本集可以自动投票,选举出新的Master,并引导其余的Slave服务器连接新的Master,
而这个过程对于应用是透明的。可以说MongoDB的副本集是自带故障转移功能的主从复制。

1.相对于传统主从模式的优势


传统的主从模式,需要手工指定集群中的Master。
如果Master发生故障,一般都是人工介入,指定新的Master。
这个过程对于应用一般不是透明的,往往伴随着应用重新修改配置文件,重启应用服务器等。
11
而MongoDB副本集,集群中的任何节点都可能成为Master节点。
一旦Master节点故障,则会在其余节点中选举出一个新的Master节点。
并引导剩余节点连接到新的Master节点。这个过程对于应用是透明的。
12

2. Bully选举算法


Bully算法是一种协调者(主节点)竞选算法,主要思想是集群的每个成员都可以声明它是主节点并通知其他节点。
别的节点可以选择接受这个声称或是拒绝并进入主节点竞争。被其他所有节点接受的节点才能成为主节点。
节点按照一些属性来判断谁应该胜出。这个属性可以是一个静态ID,也可以是更新的度量像最近一次事务ID(最新的节点会胜出)


他的选举过程大致如下:

1.得到每个服务器节点的最后操作时间戳。每个mongodb都有oplog机制会记录本机的操作,方便和主服务器进行对比数据是否同步还可以用于错误恢复。

2.如果集群中大部分服务器down机了,保留活着的节点都为 secondary状态并停止,不选举了。

3.如果集群中选举出来的主节点或者所有从节点最后一次同步时间看起来很旧了,停止选举等待人来操作。

4.如果上面都没有问题就选择最后操作时间戳最新(保证数据是最新的)的服务器节点作为主节点。
选举的触发条件
1.初始化一个副本集时。
2.副本集和主节点断开连接,可能是网络问题。
3.主节点挂掉。
4.人为介入,比如修改节点优先级等
5.选举还有个前提条件,参与选举的节点数量必须大于副本集总节点数量的一半,如果已经小于一半了所有节点保持只读状态。


3 .搭建副本集集群


每个虚拟机都使用如下的配置文件启动实例:
mongod --dbpath=/data/db --logpath=/var/log/mongodb.log --port 27017 --replSet mvbox --maxConns=2000 --logappend --fork

然后在任意一台虚拟机登陆mongo,输入如下设置
config = { _id:"mvbox", members:[
{_id:0,host:"192.168.1.1:27017"},
{_id:1,host:"192.168.1.2:27017"},
{_id:2,host:"192.168.1.3:27017"}]
}
rs.initiate(config);
可以看到副本集已经生效


2 可以使用rs.status()查看集群状态,或者rs.isMaster() 3

4. 更改节点优先级

修改节点的优先级可以触发重新选举,这样可以人工指定主节点。
使用如下命令,在主节点登录,将192.168.1.3提升为Master。
rs.conf();
cfg=rs.conf();
cfg.members[0].priority=1
cfg.members[1].priority=1
cfg.members[2].priority=10
rs.reconfig(cfg);

需要注意的是,修改节点优先级需要登录Master节点运行。否则报错。
4

再次查看集群状态,可以看到192.168.1.3已经作为Master运行
5

5 .节点类型


MongoDB的节点类型有主节点(Master),副本节点(Slave或者称为Secondary),仲裁节点,Secondary-Only节点,Hidden节点,Delayed节点和Non-Voting节点。

仲裁节点不存储数据,只是负责故障转移的群体投票,这样就少了数据复制的压力。

Secondary-Only:不能成为primary节点,只能作为secondary副本节点,防止一些性能不高的节点成为主节点。

Hidden:这类节点是不能够被客户端制定IP引用,也不能被设置为主节点,但是可以投票,一般用于备份数据。

Delayed:可以指定一个时间延迟从primary节点同步数据。主要用于备份数据,如果实时同步,误删除数据马上同步到从节点。所以延迟复制主要用于避免用户错误。

Non-Voting:没有选举权的secondary节点,纯粹的备份数据节点。

6 .设置隐藏节点(Hidden)


隐藏节点可以在选举中投票,但是不能被客户端引用,也不能成为主节点。也就是说这个节点不能用于读写分离的场景。
将192.168.1.3设置为隐藏节点。
注意,只有优先级为0的成员才能设置为隐藏节点。
如果设置优先级不为0的节点为隐藏节点,则报错如下
13

使用如下命令设置隐藏节点
cfg=rs.conf();
cfg.members[0].priority=10
cfg.members[1].priority=1
cfg.members[2].priority=0
cfg.members[2].hidden=1
rs.reconfig(cfg);
设置完成之后,使用rs.status()查看该节点还是SECONDARY状态。
但是通过rs.isMaster()和rs.conf()可以看到这个节点的变化。
rs.isMaster()的hosts中192.168.1.3节点已经不可见
14
并且rs.conf()显示该节点状态为hidden

15

7 .设置仲裁节点


仲裁节点不存储数据,只是用于投票。所以仲裁节点对于服务器负载很低。
节点一旦以仲裁者的身份加入集群,他就只能是仲裁者,无法将仲裁者配置为非仲裁者,反之也是一样。
另外一个集群最多只能使用一个仲裁者,额外的仲裁者拖累选举新Master节点的速度,同时也不能提供更好的数据安全性。
初始化集群时,设置仲裁者的配置如下
config = { _id:"mvbox", members:[
{_id:0,host:"192.168.1.1:27017"},
{_id:1,host:"192.168.1.2:27017",arbiterOnly:true},
{_id:2,host:"192.168.1.3:27017"}]
}
使用仲裁者主要是因为MongoDB副本集需要奇数成员,而又没有足够服务器的情况。在服务器充足的情况下,不应该使用仲裁者节点。

8 .设置延迟复制节点


MongoDB官方没有增量备份方案,只有一个导出的工具mongodump。
他不能像数据库一样,通过binlog或者归档日志将数据推到事故发生的前一刻。
假设每天凌晨2点使用mongodump备份,而下午5点发生事故,数据库损毁,则凌晨2点到下午5点的数据全部都会丢失。
虽然副本集可以一定程度避免这个问题,但是默认情况下不能避免人为的失误。
比如没有指定筛选条件删除了全部的数据。副本节点会应用这个命令,删除所有副本节点的数据。
在这个场景下,可以使用延迟节点,它会延迟应用复制。
如果主节点发生了人为的失误,而这个操作因为延迟的原因,还没有应用在延迟节点。
这个时候,修改延迟节点的优先级为最高级,使他成为新的Master服务器。

延迟节点的优先级必须为0.这个和hidden节点是一样的。
设置192.168.1.2为延迟节点
cfg=rs.conf();
cfg.members[1].priority=0
cfg.members[1].slaveDelay=3600
rs.reconfig(cfg);
slaveDelay的单位是秒
在192.168.1.1主节点删除一个集合所有数据,模拟人为失误。
16

在192.168.1.3查看,发现数据已经全部丢失。
17
而在192.168.1.2延迟节点,可以看到因为延迟复制的缘故,数据还在。
18
这个时候千万不要提升延迟节点的优先级。因为这样他会立即应用原主节点的所有操作,并成为新的主节点。这样误操作就同步到了延迟节点。
首先,关闭副本集中其他的成员,除了延迟节点。
删除其他成员数据目录中的所有数据。确保每个其他成员的数据目录都是空的(除了延迟节点)
重启其他成员,他们会自动从延迟节点中恢复数据。
9 .设置Secondary-Only节点

Priority为0的节点永远不能成为主节点,所以设置Secondary-only节点只需要将其priority设置为0.

10 .设置Non-Voting节点


假设设置192.168.1.1不能投票,则使用如下命令
cfg=rs.conf();
cfg.members[0].votes=0;
rs.reconfig(cfg);
11 .副本集成员状态

副本集成员状态指的是rs.status()的stateStr字段
19
STARTUP:刚加入到复制集中,配置还未加载

STARTUP2:配置已加载完,初始化状态

RECOVERING:正在恢复,不适用读

ARBITER: 仲裁者

DOWN:节点不可到达

UNKNOWN:未获取其他节点状态而不知是什么状态,一般发生在只有两个成员的架构,脑裂

REMOVED:移除复制集

ROLLBACK:数据回滚,在回滚结束时,转移到RECOVERING或SECONDARY状态

FATAL:出错。查看日志grep “replSet FATAL”找出错原因,重新做同步

PRIMARY:主节点

SECONDARY:备份节点

12. 读写分离

如果Master节点读写压力过大,可以考虑读写分离的方案。
20

不过需要考虑一种场景,就是主服务器的写入压力非常的大,所以副本节点复制的写入压力同样很大。
这时副本节点如果读取压力也很大的话,根据MongoDB库级别读写锁的机制,
很可能复制写入程序拿不到写锁,从而导致副本节点与主节点有较大延迟。

如果进行读写分离,首先需要在副本节点声明其为slave,

21
其中的ReadRreference有几种设置,

primary:默认参数,只从主节点上进行读取操作;

primaryPreferred:大部分从主节点上读取数据,只有主节点不可用时从secondary节点读取数据。

secondary:只从secondary节点上进行读取操作,存在的问题是secondary节点的数据会比primary节点数据“旧”。

secondaryPreferred:优先从secondary节点进行读取操作,secondary节点不可用时从主节点读取数据;

nearest:不管是主节点、secondary节点,从网络延迟最低的节点上读取数据。
参考:http://www.lanceyan.com/tech/mongodb/mongodb_repset1.html

MongoDB副本集实验

一、实验环境:

Vmware 10 + 32位CentOS_6.5 + mongodb-3.2(32位)
1

二、下载并安装mongodb:

1.下载:
mongodb-3.2:百度云盘下载

也可以根据自己的环境,到官网上下载

2.安装:
分别创建:/usr/local/mongodb /data/db目录及文件/var/log/mongodb.log
解压mongodb-linux-i686-3.2.11.tgz,将其文件拷贝到/usr/local/mongodb/

3.加入环境变量:
vi /etc/profile
export PATH=/usr/local/mongodb/bin:$PATH
执行:source /etc/profile使其立即生效

三、搭建副本集:

介绍一下mongod启动涉及到的参数

--dbpath           数据文件路径

--logpath           日志文件路径

--port        端口号,默认是27017.我这里使用的也是这个端口号.

--replSet          复制集的名字,一个replica sets中的每个节点的这个参                       数都要用一个复制集名字,这里是mvbox.

--maxConns        最大连接数

--fork       后台运行

--logappend       日志文件循环使用,如果日志文件已满,那么新日志覆盖最久日志。
1.分别在1,2,3机器上启动mongod:

 mongod --dbpath=/data/db --logpath=/var/log/mongodb.log --port 27017 --replSet mvbox --maxConns=2000 --logappend --fork
说明:启动前如果已有mongod.lock先删除:rm -rf /data/db/mongod.lock

2.在1,2,3任意节点上登陆mongo:
> mongo
> config = { _id:"mvbox", members:[
{_id:0,host:"192.168.1.1:27017"},
{_id:1,host:"192.168.1.2:27017"},
{_id:2,host:"192.168.1.3:27017"}]
}
rs.initiate(config);

2


可以使用rs.status()查看集群状态,或者rs.isMaster()
3

四、同步验证:

1.在主节点的机器上,插入一条数据:

> use test;
> db.my.insert({'name':zrp,'age':28});

2.在副本集的节点上,先开启同步:

> rs.slaveOk(true);

3.查看副本集节点是否已同步数据:

> use test;
> db.my.find();

ok,数据同步成功,实验宣告成功!

五、变更节点:

1.变更192.168.1.3为仲裁节点: 

(1)在主节点上执行:
PRIMARY> rs.remove("192.168.1.3:27017");//先删除其副节点的角色
PRIMARY> rs.addArb("192.168.1.3:27017");//再追加其仲裁节点的角色
PRIMARY> rs.status();//查看状态
(2)登陆192.168.1.3的mongo查看其角色是否变化

2.更改节点优先级:

修改节点的优先级可以触发重新选举,这样可以人工指定主节点。
使用如下命令,在主节点登录,将192.168.1.3提升为Master。
rs.conf();
cfg=rs.conf();
cfg.members[0].priority=1
cfg.members[1].priority=1
cfg.members[2].priority=10
rs.reconfig(cfg);
需要注意的是,修改节点优先级需要登录Master节点运行。否则报错。
4

再次查看集群状态,可以看到192.168.1.3已经作为Master运行
5

 

什么场景应该用 MongoDB ?

案例1
> 1. 用在应用服务器的日志记录,查找起来比文本灵活,导出也很方便。也是给应用练手,从外围系统开始使用MongoDB。
2. 用在一些第三方信息的获取或者抓取,因为MongoDB的schema-less,所有格式灵活,不用为了各种格式不一样的信息专门设计统一的格式,极大得减少开发的工作。
案例2
> mongodb之前有用过,主要用来存储一些监控数据,No schema 对开发人员来说,真的很方便,增加字段不用改表结构,而且学习成本极低。
案例3
> 使用MongoDB做了O2O快递应用,·将送快递骑手、快递商家的信息(包含位置信息)存储在 MongoDB,然后通过 MongoDB 的地理位置查询,这样很方便的实现了查找附近的商家、骑手等功能,使得快递骑手能就近接单,目前在使用MongoDB 上没遇到啥大的问题,官网的文档比较详细,很给力。

经常跟一些同学讨论 MongoDB 业务场景时,会听到类似『你这个场景 mysql 也能解决,没必要一定用 MongoDB』的声音,的确,并没有某个业务场景必须要使用 MongoDB才能解决,但使用 MongoDB 通常能让你以更低的成本解决问题(包括学习、开发、运维等成本),下面是 MongoDB 的主要特性,大家可以对照自己的业务需求看看,匹配的越多,用 MongoDB 就越合适。

MONGODB 特性 优势
事务支持 MongoDB 目前只支持单文档事务,需要复杂事务支持的场景暂时不适合
灵活的文档模型 JSON 格式存储最接近真实对象模型,对开发者友好,方便快速开发迭代
高可用复制集 满足数据高可靠、服务高可用的需求,运维简单,故障自动切换
可扩展分片集群 海量数据存储,服务能力水平扩展
高性能 mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求
强大的索引支持 地理位置索引可用于构建 各种 O2O 应用、文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求
Gridfs 解决文件存储的需求
aggregation & mapreduce 解决数据分析场景需求,用户可以自己写查询语句或脚本,将请求都分发到 MongoDB 上完成

从目前阿里云 MongoDB 云数据库上的用户看,MongoDB 的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例。

  • 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
  • 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
  • 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
  • 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
  • 视频直播,使用 MongoDB 存储用户信息、礼物信息等
  • ……

如果你还在为是否应该使用 MongoDB,不如来做几个选择题来辅助决策(注:以下内容改编自 MongoDB 公司 TJ 同学的某次公开技术分享)。

应用特征 YES / NO
应用不需要事务及复杂 join 支持 必须 Yes
新应用,需求会变,数据模型无法确定,想快速迭代开发
应用需要2000-3000以上的读写QPS(更高也可以)
应用需要TB甚至 PB 级别数据存储 ?
应用发展迅速,需要能快速水平扩展 ?
应用要求存储的数据不丢失 ?
应用需要99.999%高可用 ?
应用需要大量的地理位置查询、文本查询

如果上述有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择 MongoDB 绝不会后悔。

_2016_11_17_1_59_28