mongodb采用的分片原理,其实很简单,说白了就是,一个蛋糕特别大,需要非常非常大的盒子才能装下,就算装下了存储也不方便,所以把大蛋糕切成小蛋糕进行存储.这种思想在其他应用或数据库中也有应用.例如:
一,mongodb分片,常用的二种架构
1,每一个客户端系统上包含一个路由器mongos,
每个客户端都有一个路由
服务器的数量从十几台增长到几百台,mongos路由和mongod分片服务器之间建立了几百、有时候甚至是几千个连接,负载非常重。这意味着每当chunk平衡(MongoDB分片集群为了保持数据均匀分布所必须使用的平衡措施)发生的时候传送存储在配置数据库中的chunk位置信息都需要花费相当长的时间。这是因为每一个mongos路由都必须清楚地知道每一个chunk都存在于集群中的哪些位置.
2,路由器独立
路由服务器单独出来
路由独立就很好的解决了上面提到的问题,路由越少,拓扑图越简单.
这里的路由器,包含了连接池的功能.上面二张图片,来源于网络
二,服务器说明
1,mongodb 分片存储
Server1 二片:Shard1/Shard2 ip:192.168.10.103
Server2 二片:Shard1/Shard2 ip:192.168.10.219
2,路由
Server3 ip:192.168.10.209
从路由器分配置上面就可以看出,才用的是独立路由的方案.
三,mongodb replica sets shard 安装配置
1,mongodb安装
下载地址: http://www.mongodb.org/downloads
解压后就能使用
2,分别在三台服务器上创建目录
# mkdir /usr/local/mongodb26/configsvr/ -p
# mkdir /usr/local/mongodb26/log/ -p
# mkdir /usr/local/mongodb26/shard1/ -p
# mkdir /usr/local/mongodb26/shard2/ -p
# mkdir /usr/local/mongodb26/key/ -p
# mkdir /usr/local/mongodb26/conf/ -p
为什么要创建目录,因为解压后的mongodb就一个目录bin目录,太少了.
3,192.168.10.103和192.168.10.219创建分片配置文件
# cat /usr/local/mongodb26/conf/shard1.conf
dbpath = /usr/local/mongodb26/shard1 //数据库路径
directoryperdb = true //设置每个数据库将被保存在一个单独的目录
shardsvr = true //启动分片
replSet = shard1 //设置富本集的名字为shard1,replSet是让服务器知道在这个"shard1"副本集中还有别的机器
port = 20001 //端口号
oplogSize = 100 //复制日志大小 MB
pidfilepath = /usr/local/mongodb26/shard1/mongodb.pid //pid文件路径
logpath = /usr/local/mongodb26/log/shard1.log //日志路径
logappend = true //以追加方式写入
profile = 1 //数据库分析,1表示仅记录较慢的操作
slowms = 5 //认定为慢查询的时间设置,根mysql慢查询有点像
fork = true //以守护进程的方式运行,创建服务器进程
shard2根shard1基本一样
# cat /usr/local/mongodb26/conf/shard2.conf
dbpath = /usr/local/mongodb26/shard2
directoryperdb = true
shardsvr = true
replSet = shard2
port = 20002
oplogSize = 100
pidfilepath = /usr/local/mongodb26/shard2/mongodb.pid
logpath = /usr/local/mongodb26/log/shard2.log
logappend = true
profile = 1
slowms = 5
fork = true
分片存储的二台机器,分别创建这二个文件.
4,192.168.10.209路由服务器
路由有二个配置文件
# cat /usr/local/mongodb26/conf/configsvr.conf //路由配置,配置文件
pidfilepath = /usr/local/mongodb26/configsvr/mongodb.pid
dbpath = /usr/local/mongodb26/configsvr
directoryperdb = true
configsvr = true //声明这是一个集群的config服务,默认端口27019,默认目录/data/configdb
port = 20000
logpath =/usr/local/mongodb26/log/configsvr.log
logappend = true
fork = true
# cat /usr/local/mongodb26/conf/mongos.conf //路由配置,配置文件
configdb = 192.168.10.209:20000 //监听的配置服务器,只能有1个或者3个
port = 30000
chunkSize = 1 //单位 mb 生成环境请使用 100 或删除,删除后默认是64
logpath =/usr/local/mongodb26/log/mongos.log
logappend = true
fork = true
四,启动mongodb进程
1,192.168.10.103和192.168.10.219分片存储节点的启动
/usr/local/mongodb26/bin/mongod -f /usr/local/mongodb26/conf/shard1.conf
/usr/local/mongodb26/bin/mongod -f /usr/local/mongodb26/conf/shard2.conf
2,在192.168.10.209路由节点上的启动
/usr/local/mongodb26/bin/mongod -f /usr/local/mongodb26/conf/configsvr.conf
/usr/local/mongodb26/bin/mongos -f /usr/local/mongodb26/conf/mongos.conf
在这里如果报以下错误:
# /usr/local/mongodb26/bin/mongos -f /usr/local/mongodb26/conf/mongos.conf
BadValue need either 1 or 3 configdbs
try '/usr/local/mongodb26/bin/mongos --help' for more information
原因以及解决办法:
mongos.conf文件中configdb参数有误,在这里路由个数,只能为1或3。configdb = 192.168.10.209:20000
五,查看是否启动成功
1,192.168.10.103和192.168.10.219分片存储节点的启动
[root@localhost conf]# netstat -tpnl |grep mongod
tcp 0 0 0.0.0.0:20001 0.0.0.0:* LISTEN 21556/mongod
tcp 0 0 0.0.0.0:20002 0.0.0.0:* LISTEN 21976/mongod
2,在192.168.10.209路由节点上的启动
[root@localhost mongodb26]# netstat -tpnl |grep mon
tcp 0 0 0.0.0.0:30000 0.0.0.0:* LISTEN 3521/mongos
tcp 0 0 0.0.0.0:20000 0.0.0.0:* LISTEN 3946/mongod
如果监听的端口都已启动,说明已添加成功.
六,配置mongodb replica set节点
1,port 20001端口进行配置
# /usr/local/mongodb26/bin/mongo --port 20001
> use admin
> config = {_id:"shard1", members: [
{_id: 0, host:"192.168.10.103:20001"},
{_id: 1, host:"192.168.10.219:20001"}
]
};
{
"_id" : "shard1",
"members" : [
{
"_id" : 0,
"host" : "192.168.10.103:20001"
},
{
"_id" : 1,
"host" : "192.168.10.219:20001"
}
]
}
> rs.initiate(config);
> exit;
2,port 20002端口进行配置
# /usr/local/mongodb26/bin/mongo --port 20002
> use admin
> config = {_id:"shard2", members: [
{_id: 0, host:"192.168.10.103:20002"},
{_id: 1, host:"192.168.10.219:20002"}
]
};
{
"_id" : "shard2",
"members" : [
{
"_id" : 0,
"host" : "192.168.10.103:20002"
},
{
"_id" : 1,
"host" : "192.168.10.219:20002"
}
]
}
> rs.initiate(config);
> exit;
在分片,192.168.10.103和192.168.10.219任何一台机器上都行,二个端口各配置一次
七,mongos路由节配置
# /usr/local/mongodb26/bin/mongo --port 30000
mongos> use admin
mongos> db.runCommand({addshard:"shard1/192.168.10.103:20001,192.168.10.219:20001",name:"shard1", maxsize:20480} )
mongos> db.runCommand({addshard:"shard2/192.168.10.103:20002,192.168.10.219:20002",name:"shard2", maxsize:20480} );
mongos> db.runCommand( {listshards : 1 } )
{
"shards" : [
{
"_id" : "shard1",
"host" : "shard1/192.168.10.103:20001,192.168.10.219:20001"
},
{
"_id" : "shard2",
"host" : "shard2/192.168.10.103:20002,192.168.10.219:20002"
}
],
"ok" : 1
}
到这儿,replica set + shard功能就配置好了,注意:虽然配置好了,但是还要声明库和表要进行分片。
八,声明库和表要分片
mongos> use admin //切换到admin库
mongos> db.runCommand({enablesharding:"test2"}); //声明test2库允许分片
{ "ok" : 1 }
mongos> db.runCommand( { shardcollection : "test2.books", key : { id : 1 } } ); //声明books表要分片
{ "collectionsharded" : "test2.books", "ok" : 1 }
mongos> use test2 //切换到test2
mongos> db.stats(); //查看数据库状态
mongos> db.books.stats(); //查看表状态
如果报以下错误:
{ "ok" : 0, "errmsg" : "sharding not enabled for db" },原因是库还不允许分片
九,测试
1,测试脚本
mongos> for (var i = 1; i <= 20000; i++) db.books.save({id:i,name:"12345678",sex:"male",age:27,value:"test"});
2,测试结果
mongos> db.books.stats();
{
"sharded" : true,
"systemFlags" : 1,
"userFlags" : 1,
"ns" : "test2.books",
"count" : 20000,
"numExtents" : 10,
"size" : 2240000,
"storageSize" : 5586944,
"totalIndexSize" : 1267280,
"indexSizes" : {
"_id_" : 678608,
"id_1" : 588672
},
"avgObjSize" : 112,
"nindexes" : 2,
"nchunks" : 4,
"shards" : {
"shard1" : {
"ns" : "test2.books",
"count" : 5499,
"size" : 615888,
"avgObjSize" : 112,
"storageSize" : 2793472,
"numExtents" : 5,
"nindexes" : 2,
"lastExtentSize" : 2097152,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 1,
"totalIndexSize" : 367920,
"indexSizes" : {
"_id_" : 196224,
"id_1" : 171696
},
"ok" : 1
},
"shard2" : {
"ns" : "test2.books",
"count" : 14501,
"size" : 1624112,
"avgObjSize" : 112,
"storageSize" : 2793472,
"numExtents" : 5,
"nindexes" : 2,
"lastExtentSize" : 2097152,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 1,
"totalIndexSize" : 899360,
"indexSizes" : {
"_id_" : 482384,
"id_1" : 416976
},
"ok" : 1
}
},
"ok" : 1
}
3,测试结果,数据分析
1),2W条数据,全部插入到shard2
2),shard2数据不变,shard1的数据开始增加
3),shard1数据不变,shard2的数据开始减少
一次插入2W条数据,5秒左右才能平衡,你可以db.book.stats(); 重复这个命令,你会发现数据流的变化。