MongoDB集群解决方案-分片技术

MongoDB,NoSQL技术的实现,基于分布式文件存储的数据库,由C++语言编写。主要是解决海量数据的访问效率问题,为web应用提供可扩展的高性能数据库存储解决方案

MongoDB集群的实现方式:

1、Replica Set:也叫作副本集,简单来说就是集群中的服务器包含了多分数据,保证主节点挂掉了。备节点能够继续的提供服务,但是提供的前提就是数据必须要和主节点的一致,如下图:

MongoDB(M)表示主节点,MongoDB(S)表示从节点,MongoDB(A)表示仲裁节点;

M节点存储数据并提供所有的增擅长服务,S节点默认不提供服务,但是可以通过设置使备节点提供查询服务,这样可以减少主节点的压力。A节点是一个特殊的节点,不提供任何服务,只是起一个选举的作用,当有主节点宕机时,可通过A节点来选取出那个S节点来提升为主节点。

2、Master-Slave:类似于MySQL的主从模式,配置很简单,这里我就不多说了

3、Sharding:和Replica Set类似,也需要一个仲裁节点,但是Sharding还需要配置服务器和路由节点,如下图:

MongoDB(R)为路由节点(mongos),数据库集群请求的入口,所有的请求都通过mongos进行协调,它就是一个请求分发器,他负责把对应的数据请求转发到对应的shard服务器上。

MongoDB(C1)为配置服务器,存储了集群的元信息,元信息保存了集群的状态和组织结构,元信息包含每个分片保存的数据块信息以及每个数据块的范围,mongos会缓存这个信息用来做读写的路由分发!

本文主要是实现第三种Sharding方式,架构部署图如下

部署环境:

                           主机名                                  IP
                           node1                          192.168.1.109
                           node2                          192.168.1.107
                           node3                          192.168.1.110

一、规划每个服务对应的端口

config server:11000
路由:10000
shard:10001
shard:10002
shard:10003

二、在node1、node2、node3上创建相应的目录(以下操作均在mongodb用户下执行)

[[email protected] ~]# cat /etc/passwd | grep mongodb
mongodb:x:10001:10001::/data/mongodb:/bin/bash
[[email protected] ~]# su - mongodb
[[email protected] ~]$ pwd
/data/mongodb
[[email protected] ~]$ mkdir -p config/{data,log}   ##config server的数据、日志路径
[[email protected] ~]$ mkdir -p mongos/log          ##路由的日志路径
[[email protected] ~]$ mkdir -p shard1/{data,log}   ##副本集1的数据、日志路径
[[email protected] ~]$ mkdir -p shard2/{data,log}
[[email protected] ~]$ mkdir -p shard3/{data,log}
[[email protected] ~]$ tar -xf mongodb-linux-x86_64-rhel62-3.2.7.tgz   ##这里用的是3.2.7的版本,目前官网最新是3.2.9
[[email protected] ~]$ ll
drwxr-xr-x 4 mongodb dev     4096 Sep 30 20:50 config
drwxr-xr-x 3 mongodb dev     4096 Sep 30 20:55 mongodb-linux-x86_64-rhel62-3.2.7
-rw-r--r-- 1 mongodb dev 74938432 Sep 30 20:40 mongodb-linux-x86_64-rhel62-3.2.7.tgz
drwxr-xr-x 3 mongodb dev     4096 Sep 30 20:50 mongos
drwxr-xr-x 4 mongodb dev     4096 Sep 30 20:50 shard1
drwxr-xr-x 4 mongodb dev     4096 Sep 30 20:51 shard2
drwxr-xr-x 4 mongodb dev     4096 Sep 30 20:51 shard3
###node2、node3亦是如此

三、启动node1、node2、node3的配置服务器

[[email protected] bin]$ pwd     
/data/mongodb/mongodb-linux-x86_64-rhel62-3.2.7/bin
[[email protected] bin]$ ./mongod --configsvr --port 11000 --dbpath /data/mongodb/config/data/ --logpath /data/mongodb/config/log/config.log --fork   ##"--fork"在后台运行,在node1上执行
[[email protected] bin]$ ./mongod --configsvr --port 11000 --dbpath /data/mongodb/config/data/ --logpath /data/mongodb/config/log/config.log --fork   ##在node2上执行
[[email protected] bin]$ ./mongod --configsvr --port 11000 --dbpath /data/mongodb/config/data/ --logpath /data/mongodb/config/log/config.log --fork   ##在node3上执行

四、启动node1、node2、node3的路由

[[email protected] bin]$ ./mongos --configdb 192.168.1.109:11000,192.168.1.107:11000,192.168.1.110:11000 --port 10000 --logpath /data/mongodb/mongos/log/mongos.log --fork   ##node1启动路由
[[email protected] bin]$ ./mongos --configdb 192.168.1.109:11000,192.168.1.107:11000,192.168.1.110:11000 --port 10000 --logpath /data/mongodb/mongos/log/mongos.log --fork   ##node2启动路由
[[email protected] bin]$ ./mongos --configdb 192.168.1.109:11000,192.168.1.107:11000,192.168.1.110:11000 --port 10000 --logpath /data/mongodb/mongos/log/mongos.log --fork   ##node3启动路由

五、在node1、node2、node3上设置shard并启动

./mongod --shardsvr --replSet shard1 --port 11001 --dbpath /data/mongodb/shard1/data --logpath /data/mongodb/shard1/log/shard1.log --fork  --oplogSize 10240 --logappend   ##设置shard1
./mongod --shardsvr --replSet shard2 --port 11002 --dbpath /data/mongodb/shard2/data --logpath /data/mongodb/shard2/log/shard2.log --fork  --oplogSize 10240 --logappend   ##设置shard2
./mongod --shardsvr --replSet shard3 --port 11003 --dbpath /data/mongodb/shard3/data --logpath /data/mongodb/shard3/log/shard3.log --fork  --oplogSize 10240 --logappend   ##设置shard3
###node2、node3操作亦是如此

六、登录任意一台机器,在相应的端口对shard进行配置

1、对shard1进行配置

[[email protected] bin]$ ./mongo --port 11001   ##连接至副本集shard1
> use admin 
> config  = {_id:"shard1",members:[{_id:0,host:"192.168.1.109:11001"},{_id:1,host:"192.168.1.107:11001"},{_id:2,host:"192.168.1.110:11001",arbiterOnly:true}]}    ##"arbiterOnly"设定谁为仲裁节点
> rs.initiate(config);   ##对shard1进行初始化

2、对shard2进行配置

[[email protected] bin]$ ./mongo --port 11002   ##连接至副本集shard2
> use admin
> config2 = {_id:"shard2",members:[{_id:0,host:"192.168.1.109:11002"},{_id:1,host:"192.168.1.107:11002",arbiterOnly:true},{_id:2,host:"192.168.1.110:11002"}]}
> rs.initiate(config2);   ##对shard2进行初始化

3、对shard3进行配置

[[email protected] bin]$ ./mongo --port 11003   ##连接至副本集shard3
> use admin
> config3 = {_id:"shard3",members:[{_id:0,host:"192.168.1.109:11003",arbiterOnly:true},{_id:1,host:"192.168.1.107:11003"},{_id:2,host:"192.168.1.110:11003"}]}
> rs.initiate(config3);   ##对shard3进行初始化

###注意:本机配置shard时,不能把本机设置为"arbiter",否则会报错,必须要去其他节点设置。
###在配置shard1、shard2时都是在node1上配置的,因为仲裁节点分别是node3、node2。当node1为仲裁节点时,必须
要去node2或者是node3上去配置

七、配置好副本集后,还需要将路由与副本集串联起来,因为所有的请求都是经过路由,随后再到配置服务器的

[[email protected] bin]$ ./mongo --port 10000   ##连接至mongos
mongos> use admin
mongos> db.runCommand({addshard:"shard1/192.168.1.109:11001,192.168.1.107:11001,192.168.1.110:11001"});   ##将路由和副本集shard1串联起来
{ "shardAdded" : "shard1", "ok" : 1 }
mongos> db.runCommand({addshard:"shard2/192.168.1.109:11002,192.168.1.107:11002,192.168.1.110:11002"});   ##将路由和副本集shard2串联起来
{ "shardAdded" : "shard2", "ok" : 1 }
mongos> db.runCommand({addshard:"shard3/192.168.1.109:11003,192.168.1.107:11003,192.168.1.110:11003"});   ##将路由和副本集shard1串联起来  
{ "shardAdded" : "shard3", "ok" : 1 }

八、检测配置是否成

1、连接至mongos查看sh

[[email protected] bin]$ ./mongo --port 10000
mongos> use amdin
mongos> sh.status()
    shards:
    {  "_id" : "shard1",  "host" : "shard1/192.168.1.107:11001,192.168.1.109:11001" }
    {  "_id" : "shard2",  "host" : "shard2/192.168.1.109:11002,192.168.1.110:11002" }
    {  "_id" : "shard3",  "host" : "shard3/192.168.1.107:11003,192.168.1.110:11003" }

2、连接至各个shard的端口查看rs

[[email protected] bin]$ ./mongo --port 11001
shard1:PRIMARY> rs.status()
    "name" : "192.168.1.109:11001",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
    "name" : "192.168.1.107:11001",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
    "name" : "192.168.1.110:11001",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",

##其他节点查看方式相同

九、插入数据,测试数据能否进行自动分片

[[email protected] bin]$ ./mongo --port 10000
mongos> use admin
mongos> db.runCommand( { enablesharding :"testdb"});  ##创建数据库,指定数据库"testdb"进行分片生效
{ "ok" : 1 }
mongos> db.runCommand({shardcollection:"testdb.table1",key:{apId:1,_id:1}})  ##MongoDB具有很多片键,此处创建ID片键,指定"testdb"数据库中的"table1"表中的数据通过ID片键进行分片
{ "collectionsharded" : "testdb.table1", "ok" : 1 }
mongos> use testdb;
switched to db testdb
mongos> for(var i=1;i<100000;i++)db.table1.save({id:i,"test1":"testval1"});   ##在"testdb"中的表"table1"中插入10w个id

[[email protected] bin]$ ./mongo --port 11003   ##node2上连接至shard3
shard3:PRIMARY> use testdb
switched to db testdb
shard3:PRIMARY> db.table1.find()
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1ce"), "id" : 1, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1cf"), "id" : 2, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1d1"), "id" : 4, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1d2"), "id" : 5, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1d6"), "id" : 9, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1d9"), "id" : 12, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1db"), "id" : 14, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1dd"), "id" : 16, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1de"), "id" : 17, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1e0"), "id" : 19, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1e3"), "id" : 22, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1e4"), "id" : 23, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1e5"), "id" : 24, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1e8"), "id" : 27, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1ea"), "id" : 29, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1eb"), "id" : 30, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1ee"), "id" : 33, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1ef"), "id" : 34, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1f2"), "id" : 37, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1f4"), "id" : 39, "test1" : "testval1" }
 
[[email protected] bin]$ ./mongo --port 11002    ##node3上连接至shard2
shard2:PRIMARY> use testdb
switched to db testdb
shard2:PRIMARY> db.table1.find()
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1d4"), "id" : 7, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1d8"), "id" : 11, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1da"), "id" : 13, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1df"), "id" : 18, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2e4eec2b8ef67ad1e2"), "id" : 21, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1e9"), "id" : 28, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1f0"), "id" : 35, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1fa"), "id" : 45, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1fc"), "id" : 47, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad1fe"), "id" : 49, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad200"), "id" : 51, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad202"), "id" : 53, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad203"), "id" : 54, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad206"), "id" : 57, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad208"), "id" : 59, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad204"), "id" : 55, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad209"), "id" : 60, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad20c"), "id" : 63, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad20f"), "id" : 66, "test1" : "testval1" }
{ "_id" : ObjectId("57ef6d2f4eec2b8ef67ad210"), "id" : 67, "test1" : "testval1" }

###node1上查看方式亦是如此
###注意:查看数据,只能在主节点上进行

问题小结:

1、集群中的每台服务器时间必须要保持一致,否则启动mongos会出现"Error Number 5"

2、在配置Replica Set时,只能指明三个节点,官网明确指出。

3、在部署集群时,如果不想设置"arbitrate“,可以通过设定副本集中的优先级"priority"来定义主备备4、

时间: 2024-10-10 07:37:28

MongoDB集群解决方案-分片技术的相关文章

Mongodb集群与分片 2

前面我们介绍了简单的集群配置实例.在简单实例中,虽然MongoDB auto-Sharding解决了海量存储问题,和动态扩容问题,但是离我们在真实环境下面所需要的高可靠性和高可用性还有一定的距离. 下面我们就介绍一个接近实际的解决方案: Shard:使用Replica Sets,来确保数据的可靠性.通过这个方案,可以在每个节点有数据的备份.实现自动控制容错转移和自动恢复 Config:使用3个配置服务器,确保元数据完整性 Route:配合LVS,实现负载均衡,提高接入性能. 1.配置集群目录 数

Mongodb集群与分片 1

分片集群 Mongodb中数据分片叫做chunk,它是一个Collection中的一个连续的数据记录,但是它有一个大小限制,不可以超过200M,如果超出产生新的分片. 下面是一个简单的分片集群实例 分片集群的构成: Shard server:mongod实例,用于存储实际的数据块 Config server:mongod实例,用于存储整个Cluster Metadata,其中包括chunk信息. Route server:mongos实例,做为整个集群的前端路由,整个集群由此接入.从而让整个集群

Mongodb集群之分片存储

上节咱们遗留了两个问题还没解决: 从节点每个上面的数据都是对数据库全部拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候是否会自动扩展 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的.而mongodb主打的就是海量数据架构,"分片"就用这个来解决这个问题. 分片,是将一个逻辑数据拆分到不同的服务器.每个拆分的数据都是独立的, 分片好处: 1分片使得集群中每个切片操作数据量减少,同时集群的操作能力增加也提高了吞吐量

搭建高可用mongodb集群(分片)

MongoDB基础请参考:http://blog.51cto.com/kaliarch/2044423 MongoDB(replica set)请参考:http://blog.51cto.com/kaliarch/2044618 一.概述 1.1 背景 为解决mongodb在replica set每个从节点上面的数据库均是对数据库的全量拷贝,从节点压力在高并发大数据量的场景下存在很大挑战,同时考虑到后期mongodb集群的在数据压力巨大时的扩展性,应对海量数据引出了分片机制. 1.2 分片概念

mongodb集群方式-分片+副本集方式

分片就是水平的扩展,将数据分拆到不同的机器上,以达到存储更多的数据,处理更大的负载.可以选定将按照指定的文档键值进行分片. 配置 整体部署方案: 启动三个分片服务,两个做数据存储,另一个作为config, 配置分片的副本集,创建管理员用户,关闭mongod,打开keyfile,启动mongos,配置分片服务. 角色 分片一般有三个组成部分: 分片服务(Shard Server),mongod 实例,2个以上,负责存储实际的数据分片,生产环境中一个Shard Server可由几台服务器组成一个Re

搭建高可用mongodb集群—— 分片

从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的.而mongodb主打的就是海量数据架构,他不能解决海量数据怎么行!不行!“分片”就用这个来解决这个问题. 传统数据库怎么做海量数据读写?其实一句话概括:分而治之.上图看看就清楚了,如下 taobao岳旭强在infoq中提到的 架构图: 上图中有个TDDL,是taobao的一

搭建高可用mongodb集群(四)—— 分片

转载自LANCEYAN.COM 按照上一节中<搭建高可用mongodb集群(三)—— 深入副本集>搭建后还有两个问题没有解决: 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会出现一台机器硬件瓶颈问题的.而mongodb主打的就是海量数据架构,他不能解决海量数据怎么行!不行!“分片”就用这个来解决这个问题. 传统数据库怎么做海量数据读写?其实一句

搭建mongodb集群(副本集+分片)

完整的搭建mongodb集群(副本集+分片)的例子... 准备四台机器,分别是bluejoe1,bluejoe2,bluejoe3,以及bluejoe0 副本集及分片策略确定如下: 将创建3个副本集,命名为shard1,shard2,shard3: 以上3个副本集作为3个分片: 每个副本集包含2个副本(主.辅): 副本分开存储,即shard1存在bluejoe1和bluejoe2上各一份...以此类推 将创建3个配置库实例,一台机器一个 bluejoe0上配置一个mongos(mongos一般可

搭建高可用MongoDB集群 -分片-good

搭建高可用MongoDB集群(四):分片 http://blog.jobbole.com/72643/ Mongodb Replica Sets 副本集架构实战(架设.扩充.容灾.修复.客户端代码连入) http://snoopyxdy.blog.163.com/blog/static/60117440201241694254441/ 关于mongodb的shard集群动态添加分片 我在机器上建立起了分片集群,其中包含了四个分片,每个分片都是副本集构成,程序访问的时候可以将数据路由到各个分片上.