MongoDB的分片(9)

时间:2022-03-22 14:17:23

什么是分片

分片是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡。通过一个名为mongos的路由进程操作,mongos通过配置服务器知道数据和片的对应关系。大部分使用场景都是解决磁盘空间的问题,对于写入有可能会变差,查询则尽量避免跨分片查询。

使用分片的时机:

1,机器的磁盘不够用了。使用分片解决磁盘空间的问题。

2,单个mongod已经不能满足写数据的性能要求。通过分片让写压力分散到各个分片上面,使用分片服务器自身的资源。

3,想把大量数据放到内存里提高性能。和上面一样,通过分片使用分片服务器自身的资源。

在搭建分片之前,先了解下分片中各个角色的作用。

配置服务器。是一个独立的mongod进程,保存集群和分片的元数据,即各分片包含了哪些数据的信息。最先开始建立,启用日志功能。像启动普通的mongod一样启动配置服务器,指定configsvr选项。不需要太多的空间和资源,配置服务器的1KB空间相当于真实数据的200MB。保存的只是数据的分布表。当服务不可用,则变成只读,无法分块、迁移数据。

路由服务器。即mongos,起到一个路由的功能,供程序连接。本身不保存数据,在启动时从配置服务器加载集群信息,开启mongos进程需要知道配置服务器的地址,指定configdb选项。

分片服务器。是一个独立普通的mongod进程,保存数据信息。可以是一个副本集也可以是单独的一台服务器。

1.新建文件夹

data/config20  配置服务器configsvr 27020端口

data/shard17   分片服务器 27017端口

data/shard18   分片服务器 27018端口

2.启动配置服务器

mongod --dbpath C:\Users\yuxl\Desktop\mongodb\data\config20 --port 27020

3. 建立mongos进程,以供应用程序连接

mongos --port 30000 --configdb 127.0.0.1:27020

4.启动分片服务器

mongod --dbpath C:\Users\yuxl\Desktop\mongodb\data\shard17 --port 27017

mongod --dbpath C:\Users\yuxl\Desktop\mongodb\data\shard18 --port 27018

5.添加分片

连接mongos进程mongo 127.0.0.1:30000/admin

添加分片

sh.addShard("127.0.0.1:27017")

sh.addShard("127.0.0.1:27018")

查看状态sh.status(),我们发现两个分片

shards:

{  "_id" : "shard0000",  "host" : "127.0.0.1:27017" }

{  "_id" : "shard0001",  "host" : "127.0.0.1:27018" }

6.添加待分片的库

sh.enableSharding(databaseName);

sh.enableSharding(“shop”);

7: 添加待分片的表

sh.shardCollection(‘dbName.collectionName’,{field:1});

field是collection的一个字段,系统将会利用filed的值,来计算应该分到哪一个片上.

这个filed叫”片键”, shard key

sh.shardCollection(“shop.goods”,{goodsid:1});

接下来插入数据进行测试,为了便于查看效果,使用一下操作

use config

db.settings.update({"_id":"chunksize"},{$set:{"value":1}})

use shop

for(var i=1;i<=10000;i++)

{

db.goods.insert({“goodsid”:i,”goodsname”:”abddsdfsdfsdfsdfsddddddddddddd”})

}

然后我们分别连接两个分片服务器上发现都有数据,但是不是很均匀

原因:

mongodb不是从单篇文档的级别,绝对平均的散落在各个片上, 而是N篇文档,形成一个块"chunk",优先放在某个片上, 当这片上的chunk,比另一个片的chunk,区别比较大时, (>=3) ,会把本片上的chunk,移到另一个片上, 以chunk为单位,维护片之间的数据均衡

问: 为什么插入了10万条数据,才2个chunk?

答: 说明chunk比较大(默认是64M)

在config数据库中,修改chunksize的值.

问: 既然优先往某个片上插入,当chunk失衡时,再移动chunk,

自然,随着数据的增多,shard的实例之间,有chunk来回移动的现象,这将带来什么问题?

答: 服务器之间IO的增加,

问: 能否我定义一个规则, 某N条数据形成1个块,预告分配M个chunk,

M个chunk预告分配在不同片上.

以后的数据直接入各自预分配好的chunk,不再来回移动?

答: 能, 手动预先分片! 注意: 预先分片的collection得是空的

以shop.user表为例

1: sh.shardCollection(‘shop.user’,{userid:1}); //user表用userid做shard key

2: for(var i=1;i<=40;i++) { sh.splitAt('shop.user',{userid:i*1000}) } // 预先在1K 2K...40K这样的界限切好chunk(虽然chunk是空的), 这些chunk将会均匀移动到各片上.

3: 通过mongos添加user数据. 数据会添加到预先分配好的chunk上, chunk就不会来回移动了.

在生成环境中我们使用replcation set与shard分片结合使用

1:在3*立服务器上,分别运行 27017,27018,27019实例, 互为副本集,形成3套repl set

2: 在3台服务器上,各配置config server, 运行27020端口上

3: 配置mongos

./bin/mongos --port 30000 \

--dbconfig 192.168.1.201:27020,192.168.1.202:27020,192.168.1.203:27020

4:连接路由器

./bin/mongo --port 30000

5: 添加repl set为片

>sh.addShard(‘192.168.1.201:27017’);

>sh.addShard(‘192.168.1.202:27017’);

>sh.addShard(‘192.168.1.203:27017’);

6: 添加待分片的库

>sh.enableSharding(databaseName);

7: 添加待分片的表

>sh.shardCollection(‘dbName.collectionName’,{field:1});