(10)mongodb 分片

  share分片就是将不同数据放在不同节点里。与复制集相比稍微复杂。它除了存储数据的节点外还有一个路由节点 mongos,一个中心配置节点 configsvr,configsvr 不存储数据,存储meta信息,即某条数据在哪个片上的信息。mongos 查询数据时先要找 configsvr ,询问该数据在哪个节点上。

  分片有4个要素:

  (1) 要有N个节点,N>=2

  (2) 要有 configsvr 维护 meta 信息

  (3) 要启动 mongos 做路由

  (4) 要设定好数据的分片规则(设定好规则 configsvr 才能维护)

数据的访问如下图所示:

记录share分片的简单步骤如下: 

(1)建立4个启动服务的配置文件,位置在mongodb的跟路径下。

  smongodb1.conf

dbpath=/var/smongodb/mdata17
logpath=/var/smongodb/mlog/mongolog17.log   
smallfiles=true
logappend=true
bind_ip=0.0.0.0
fork=true
port=27017
View Code

  smongodb2.conf

logpath=/var/smongodb/mlog/mongolog18.log   
smallfiles=true
logappend=true
bind_ip=0.0.0.0
fork=true
port=27018
View Code

  smongodbConfigsvr.conf

dbpath=/var/smongodb/mdata20
logpath=/var/smongodb/mlog/mongolog20.log   
smallfiles=true
logappend=true
bind_ip=0.0.0.0
fork=true
configsvr=true
port=27020
View Code

  smongodb.conf

logpath=/var/smongodb/mlog/mongolog30.log   
logappend=true
bind_ip=0.0.0.0
fork=true
port=30000
configdb=192.168.31.151:27020
View Code

(2)依次执行如下操作

  清空历史数据  

  rm -rf /var/smongodb/

  创建数据、日志存放路径

  mkdir -p /var/smongodb/mdata17 /var/smongodb/mdata18 /var/smongodb/mdata20 /var/smongodb/mlog

  启动27017、27018端口的服务 (两个实例)

  /usr/local/mongodb245/bin/mongod -f /usr/local/mongodb245/smongodb1.conf

  /usr/local/mongodb245/bin/mongod -f /usr/local/mongodb245/smongodb2.conf

  启动 configsvr服务

  /usr/local/mongodb245/bin/mongod -f /usr/local/mongodb245/smongodbConfigsvr.conf

  启动路由 mongos服务

  /usr/local/mongodb245/bin/mongos -f /usr/local/mongodb245/smongodb.conf

  增加两个片节点

  /usr/local/mongodb245/bin/mongo --port 30000

  sh.addShard('192.168.31.151:27017')

  sh.addShard('192.168.31.151:27018')

  执行完上述操作,搭建步骤就完成了,可以用 登录路由节点,查看分片状态:

  /usr/local/mongodb245/bin/mongo --port 30000  登录路由节点的客户端,执行sh.status() 查看分片后的状态

 可以看出192.168.31.151.27017 节点对应的分片是shard0000,192.168.31.151.27018 节点对应的分片是shard0001。配置完的分片中有一个admin数据库。由于没有配置分片规则,所以现在并不能实现数据的分片功能,测试如下:

mongos> db.goods.insert({name:'电动牙刷1'})
mongos> db.goods.insert({name:'电动牙刷2'})
mongos> db.goods.insert({name:'电动牙刷3'})
mongos> db.goods.insert({name:'电动牙刷4'})
View Code

 登录27017节点可以查询到数据,登录27018节点不能查询到数据,并且没有shop库,此时在执行一下sh.statsu(),截图如下:

框起来的红色部分 partitioned:false 说明没有设置数据的分片规则,primary:shard0000 是说插入数据的首选片区是 shard0000,所以数据通过192.168.31.151.27017服务写入。下面配置分片规则:

mongos> db.goods.remove({});  为了测试,先清除所有数据

mongos> sh.enableSharding('shop')  指定分片的库是 shop

mongos> sh.shardCollection('shop.goods',{goods_id:1});  指定给 shop 库的 goods 表分片,根据字段 goods_id 分片

指定完规则,再次执行 sh.statsu(),截图如下:

可以看到 shop 库的 partitioned 变成了 true, shard key 是 goods_id。片键是collection的一个字段,系统将会利用该字段的值来计算数据分到哪个片上,该字段叫片键 field key,mongodb 不是从单篇文档的级别绝对平均的散落在各个片上,而是N篇文档,形成一个块 "chunk",优先放在某个片上,当这片上的 chunk 比另一个片的chunk差别比较大(>=3)时,会把本片上的 chunk 移到另一个片上,mongodb 以 chunk为单位,维护片之间的数据平衡。简单的说就是一个片上有多个 chunk,chunk里保存了数据。chunk 的默认大小是 64M,可以修改。下面插入30万条数据查看数据是否分片存储,为了测试现将 chunk 大小改为1M

mongos> db.settings.find();
{ "_id" : "chunksize", "value" : 64 }

mongos> db.settings.save({_id:'chunksize',value:'1'});
mongos> db.settings.find();
{ "_id" : "chunksize", "value" : "1" }

mongos> for(var i=1;i<=300000;i++){ db.goods.insert({goods_id:i,goods_name:'aaaaaaaaaaaaa sddddddddddd fsddddddddddd fgggggggggggggggg hhhhhhhhhhhhhhh kkkkkkkkkkkkkk'});}

mongos> db.goods.find().count();
300000

登录27017

> db.goods.find().count();
3891

登录27018

> db.goods.find().count();
296109

两个片上都写入了数据,说明分片成功,再看一下截图 sh.status(); 

图中可以清楚的看到shard0000片有2个chunk,shard0001片有3个chuck,根据goods_id的范围可以看到数据是怎样在不同片上分布的。

  这样配置有个问题,由于数据优先往某个片上插入,不同片上 chunk 的量会不同,导致失衡,为求平衡shard的实例之间有chunk来回移动的现象。这样增加了服务器之间的IO。下一篇解决这个问题。

原文地址:https://www.cnblogs.com/javasl/p/11297296.html