什么是分片
分片是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡。通过一个名为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:UsersyuxlDesktopmongodbdataconfig20 --port 27020
3. 建立mongos进程,以供应用程序连接
mongos --port 30000 --configdb 127.0.0.1:27020
4.启动分片服务器
mongod --dbpath C:UsersyuxlDesktopmongodbdatashard17 --port 27017
mongod --dbpath C:UsersyuxlDesktopmongodbdatashard18 --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});