虽然mongoDB的复制集应用的场景比较多,但是也存在很多问题,比如当数据量比较大的时候,复制集是所有的数据都放在主节点,然后同步到从节点上,也就是说每个节点上都是放了所有数据的,当然也就意味着,如果数据量特别大的时候,特别是存储问题及性能问题,虽然复制集可以提可供所谓的高可用,主节点提供写操作,从节点可以分担读操作的负荷,但是写操作只能发生在主节点上,这样的话写操作的性能瓶颈是没有办法解决的,所以需要采用分片集群,分片集群即数据的分布式管理,在之前的redis cluster已经实现过,redis cluster集群就是把数据切割成16384个槽位平均分配到各个主节点上,每个节点只承担了其中一部分的数据量,最终每个节点的访问量也只是承担了一部分,从而提升系统的整体性能,在mongoDB中也有这种思想的体现,即分片集群。
实现mongoDB的分片集群就redis cluste而言更为复杂一点,不是较为简单的主从架构及数据分片。
分片集群的目标就是提升系统性能,可以把数据分散在多个分片节点上,每个节点只是存放了其中一部分数据,采用水平切割的方式,实现了整体性能上的扩展。
当然每个架构都不是完美的,它的缺点就是分片会额外的增加一些消耗,虽然可以使每个主节点承担一部分数据及请求,但是它的单机性能会下降,相当于原来的单机性能70%左右,三种角色,管理也偏复杂,在大型网络环境中才会应用这种架构形式。
分成多个节点之后,每个节点虽然存放的只是一部分数据,但是跟用户是没有关系的,MongoDB自带了一个叫做mongos的专有路由进程,mongos就是掌握统一路口的路由器,会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发送到客户端。
用户不是直接访问节点,而是通过mongos来访问的,用户发请求到mongos,mongos收到请求之后再把它转发到相应的分片节点上,用户并不知道背后是集群架构,和单机访问的体验感受是一样的,较这一点而言和redis cluster还是有一定区别的。
Mongos是个无状态代理,收到访问请求之后mongos是无法直接精准的把请求发到相应节点上的,需要config server,可以认为它是个索引数据库,存放了所有数据的元数据,记录了哪个数据在哪个分片上,这样的话mongos收到用户请求之后,对config server发起请求,config server把查询结果返回给mongos,mongos再把用户请求转发到相应的分片节点上,集群的分片节点,mongos节点,config server共同协作,相辅相成,三者缺一不可。
注意:Mongos和config server通常消耗很少的资源,可以选择低规格的虚拟机,资源的重点在于shard服务器,实际测试是最好的检验,来看你的资源设置是否完备,即使项目初期已经具备了足够的资源,仍然需要考虑在合适的时候扩展,建议监控各项资源的使用情况,无论哪一项达到60%以上,基于以下原因开始考虑扩展:
分片集群架构
分片集群部署
Shard1
10.0.0.8
10.0.0.18
10.0.0.28
Shard2
10.0.0.38
10.0.0.48
10.0.0.58
Config server
10.0.0.68
10.0.0.78
10.0.0.88
Mongos
10.0.0.98
搭建分片,创建复制集,配置shard1(三台shard1同样配置)
注意:配置文件为yaml格式,注意缩进,不然服务会启动失败
[16:34:04 root@shard1 ~]$vim /mongodb/conf/mongo.conf
开机启动并立即启动mongodb服务
[16:34:47 root@shard1 ~]$systemctl enable --now mongod.service
[16:36:26 root@shard1 ~]$systemctl enable --now mongod.service
[16:37:41 root@shard1 ~]$systemctl enable --now mongod.service
打开shard1中的任意节点mongo服务配置复制集
初始化
查看shard1复制集
配置shard2复制集,六个节点配置相同,只是同上个复制集群名称不同
[17:34:03 root@shard2 ~]$vim /mongodb/conf/mongo.conf
开机启动并立即启动mongodb服务
[17:41:36 root@shard2 ~]$systemctl enable --now mongod.service
打开shard2中的任意节点mongo服务配置复制集
初始化
查看shard2复制集群
配置config server节点
三个节点配置相同,也是复制集群
[18:22:03 root@config-server ~]$vim /mongodb/conf/mongo.conf
重新启动并立即启动mongod服务
[18:25:00 root@config-server ~]$systemctl enable --now mongod.service
[18:25:57 root@config-server ~]$systemctl enable --now mongod.service
[18:27:26 root@config-server ~]$systemctl enable --now mongod.service
Config server的端口号为:27019
登录mongo config server
[18:35:55 root@config-server ~]$mongo --port 27019
配置config server复制集,注意端口号发生改变
初始化
查看config server复制集群
配置mongos节点
其他节点的程序都是mongod,而mongos的程序不是mongod,而是mongos
[18:57:07 root@mongos ~]$vim /mongodb/conf/mongo.conf
先停止mongod服务,mongod和mongos的端口号都是27017,必须关掉mongod服务,不然会冲突
[19:04:41 root@mongos ~]$systemctl stop mongod
启动mongos,注意不是mongod
[19:05:22 root@mongos ~]$mongos -f /mongodb/conf/mongo.conf
登录mongos,在mongos添加shard1和shard2分片集群
[19:10:57 root@mongos ~]$mongo admin
两组集群选取一个集群中任意一个节点作为代表就可以,因为他是一个集群整体,添加一个节点作为代表其他两个节点也就自动加入进来了
mongos> sh.addShard("shard1/10.0.0.8:27017")
mongos> sh.addShard("shard2/10.0.0.38:27017")
查看分片状态
mongos> sh.status()
启用range分片规则
启用数据库分片
mongos> sh.enableSharding("test")
创建索引
mongos> db.vast.createIndex({id: 1})
在vast表上根据id字段从小到大创建索引
开启range分片规则,定义分片
在test数据库里的vast表上id字段创建分片索引,1表示范围分片
mongos> sh.shardCollection("test.vast", {id: 1})
查看状态,可以看到已经有分片了,但是还没有数据
mongos> sh.status()
添加数据
mongos> for (i=0;i<1000000 ;i++){ db.vast.insert ( { "id" :i, "name" : "wang" , "age" : 20,"date" : new Date()})}
利用hash分片规则创建分片
mongos> sh.enableSharding("magedu")
创建索引
mongos> db.vast.createIndex({id: "hashed"})
基于hash规则指定表分片
mongos> sh.shardCollection("magedu.vast", {id: 'hashed'})
插入数据(插入足够量大的数据才会分片)
mongos> use magedu
mongos> for (i=0;i<100000 ;i++){ db.vast.insert ( { "id" :i, "name" : "wang" , "age" : 20,"date" : new Date()})}
查看分片
mongos> db.adminCommand({listShards: 1})
mongos> db.adminCommand({listShards: 2})
mongos> sh.status()
mongos> use config
mongos> db.databases.find()
验证数据(由于时间原因,数据没有写完,但是可以看出两个分片的数据还是很均衡的)