mongodb的集群搭建
对于当前的环境下,针对大数据量存储的处理,我们往往会选择分片或者集群方案。这两个方案具有数据库的可靠性和高可读性。可靠性是指对数据库的访问不会因为单点故障而导致用户无法操作;高可读性则是用户的读取服务器和写入服务器在不同的地方,而且,由不同的服务器为不同的用户提供 服务,提高整个系统的负载。
mongodb的集群和分片方案和其他数据库不太一样,列如mysql,如果要实现其主从复制,我们获取会借助mycat组件来实现。而mongodb就不需要其他组件,它的集群分片方案几乎是全自动的。
一、mongodb集群--复制集
复制集是指:一组复制集就是一组mongod实例掌管同一个数据集,实例可以在不同的机器上面。实例中包含一个主数据库(Primary),接受客户端所有的写入操作,其他都是副数据库(Secondary),从主服务器上获得数据并保持同步。
1.1 复制集中的成员
在了解复制集的架构前,我们需要先了解里面所有的成员
在上面中所说的选举,它的主要过程是:复制集通过replSetInitiate命令(或mongo shell的rs.initiate())进行初始化,初始化后各个成员间开始发送心跳消 息,并发起Priamry选举操作,获得『大多数』成员投票支持的节点,会成为Primary,其余节点成为Secondary。
假设复制集内投票成员数量为N,则大多数为 N/2 + 1,当复制集内存活成员数量不足大多数时,整个复制集将无法 选举出Primary,复制集将无法提供写服务,处于只读状态。
1.2 复制集的架构
根据mongodb中设计的成员,我们大概可以列出以下几种
(1)一主两从
这种就是我们最常见的一种架构,由一个主数据库和两个从数据库组成。主数据库负责用户写的操作,从数据库负责同步主数据库的数据,并且提供读操作。
其次当主机意外宕机时,两个从机会自动选择一个作为主机。当原来的主机恢复后,会自动加入集群并成为一个从机。
(2)一主一从一选举
这个架构是在mongodb中独有的一种,它是由一个主机、一个从机和一个arbiter节点组成。由于arbiter节点的特殊性,可以复制集的成本压缩最小。arbiter节点只负责投票,不负责存数据,也不能当主机,因此我们可以在从机服务器上添加,这样如果主机意外宕机后,从机变成主机,复制集依然能够使用。
1.3 集群搭建
本文集群搭建的环境是linux下搭建的,用的mongodb版本为4.0.3,使用docker服务的方式进行集群搭建。
第一步:创建3个mongodb容器。本文是根据上面介绍的架构,只用三个作为示例。
docker create --name mg1 -p 27017:27017 -v mongo-data-01:/data/db mongo:4.0.3 --replSet "colony" --bind_ip_all
docker create --name mg2 -p 27018:27017 -v mongo-data-02:/data/db mongo:4.0.3 --replSet "colony" --bind_ip_all
docker create --name mg3 -p 27019:27017 -v mongo-data-03:/data/db mongo:4.0.3 --replSet "colony" --bind_ip_all
第二步:启动容器
docker start mg1 mg2 mg3
第三步:在配置好容器后,我们需要进入连接mongodb服务,配置集群
docker exec -it mg1/bin/bash
第四步:登录到一个mongodb
mongo 182.159.31.76:27017
第五步:配置集群
rs.initiate( {
_id : "colony",
members: [
{ _id: 0, host: "182.159.31.76:27017" },
{ _id: 1, host: "182.159.31.76:27018" },
{ _id: 2, host: "182.159.31.76:27019" }
]
})
以上mongodb的复制集就已经搭建完成,搭建完成后它会自动选择一个数据库作为主机。
二、mongodb分片集群
分片是MongoDB用来将大型集合分割到不同服务器(或者说一个集群)上所采用的方法。尽管分片起 源于关系型数据库分区,但MongoDB分片完全又是另一回事。
和MySQL分区方案相比,MongoDB的最大区别在于它几乎能自动完成所有事情,只要告诉MongoDB要分配数据,它就能自动维护数据在不同服务器之间的均衡。
2.1 mongodb分片的好处
(1)能够保证集群不可见,通过一个路由进程保证用户访问的是统一的入口。
(2)当分片和集群同时使用时,能够保证集群总是可以读写的(故障转移的功能)。
(3)使集群易于扩展,当系统需要更多的空间和资源的时候,MongoDB使我们可以按需方便的扩充系统容量。
2.2 mongodb的分片架构
架构中的成员是:
根据架构图可以看见,Mongos本身并不持久化数据,Sharded cluster所有的元数据都会存储到Config Server,而用户的数据会分散存储 到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的分 片。
当数据写入时,MongoDB Cluster根据分片键设计写入数据。当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。
2.3 mongodb的数据分片原理
mongodb的分片逻辑主要是在Shard中体现的,在一个shard server内部,MongoDB会把数据分为chunks,每个chunk代表这个shard server内部一部分数据。
chunk主要有两个用途:
(1)分裂(spliting):
当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分成更小的chunk,从而避免chunk过大的情况。
(2)迁移(Balancing):
在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载,系统初始1个chunk,chunk size默认值64M,生产库上选择适合业务的chunk size是最好的。mongoDB会自动拆分和迁移chunks。
2.4 chunk分裂的影响
chunk有一个特点:只会分裂,不会合并。
根据这个特点和上面mongodb的分片原理来看,设置chunk size的大小能够影响整个集群的性能。
当设置chunk size较小时,数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。
当设置chunk size较大时,数据分裂少,数据块移动集中消耗IO资源
2.5 搭建mongodb分片
第一步:创建config server节点,按照要求我们创建三个
docker create --name configserver1 -p 2500:27019 -v mongoconfigserver1:/data/configdb mongo:4.0.3 --configsvr --replSet "colonyconfigserver" --bind_ip_all
docker create --name configserver2 -p 2501:27019 -v mongoconfigserver2:/data/configdb mongo:4.0.3 --configsvr --replSet "colonyconfigserver" --bind_ip_all
docker create --name configserver3 -p 2502:27019 -v mongoconfigserver3:/data/configdb mongo:4.0.3 --configsvr --replSet "colonyconfigserver" --bind_ip_all
第二步:启动服务
docker start configserver1 configserver2 configserver3
第三步:进入mongodb容器,对集群初始化
docker exec -it configserver1 /bin/bash
mongo 182.159.31.76:2500
rs.initiate(
{
_id: "colonyconfigserver",
#设置集群为congfig server集群
configsvr: true,
members: [
{ _id : 0, host : "182.159.31.76:2500" },
{ _id : 1, host : "182.159.31.76:2501" },
{ _id : 2, host : "182.159.31.76:2502" }
]
}
)
第四步:在创建好configserver节点后,我们接下来创建shard节点,在这么我们采用复制集的方式创建
创建两个shard复制集,每个集群有3个节点
#集群一
docker create --name shardsvr01 -p 37000:27018 -v mongoshardsvr-data-01:/data/db
mongo:4.0.3 --replSet "rs_shardsvr1" --bind_ip_all --shardsvr
docker create --name shardsvr02 -p 37001:27018 -v mongoshardsvr-data-02:/data/db
mongo:4.0.3 --replSet "rs_shardsvr1" --bind_ip_all --shardsvr
docker create --name shardsvr03 -p 37002:27018 -v mongoshardsvr-data-03:/data/db
mongo:4.0.3 --replSet "rs_shardsvr1" --bind_ip_all --shardsvr
#集群二
docker create --name shardsvr04 -p 37003:27018 -v mongoshardsvr-data-04:/data/db
mongo:4.0.3 --replSet "rs_shardsvr2" --bind_ip_all --shardsvr
docker create --name shardsvr05 -p 37004:27018 -v mongoshardsvr-data-05:/data/db
mongo:4.0.3 --replSet "rs_shardsvr2" --bind_ip_all --shardsvr
docker create --name shardsvr06 -p 37005:27018 -v mongoshardsvr-data-06:/data/db
mongo:4.0.3 --replSet "rs_shardsvr2" --bind_ip_all --shardsvr
第五步:启动容器
docker start shardsvr01 shardsvr02 shardsvr03
docker start shardsvr04 shardsvr05 shardsvr06
第六步:初始化集群
docker exec -it shardsvr01 /bin/bash
mongo 182.159.31.76:37000
#初始化集群
rs.initiate(
{
_id: "rs_shardsvr1",
members: [
{ _id : 0, host : "182.159.31.76:37000" },
{ _id : 1, host : "182.159.31.76:37001" },
{ _id : 2, host : "182.159.31.76:37002" }
]
}
)
#初始化集群二
mongo 182.159.31.76:37003
rs.initiate(
{
_id: "rs_shardsvr2",
members: [
{ _id : 0, host : "182.159.31.76:37003" },
{ _id : 1, host : "182.159.31.76:37004" },
{ _id : 2, host : "182.159.31.76:37005" }
]
}
)
第七步:配置好configserver和shard后,就该配置mongos了。需要注意的是mongos在构建容器时要添加configsever的所有节点。
docker create --name mongos -p 2400:27017 --entrypoint "mongos" mongo:4.0.3 --configdb colonyconfigserver/182.159.31.76:2500,182.159.31.76:2501,182.159.31.76:2502--
bind_ip_all
第八步:在mongos中添加shard节点
docker start mongos
#进入容器执行
docker exec -it mongos bash
mongo 182.159.31.76:2400
#添加shard节点
sh.addShard("rs_shardsvr1/182.159.31.76:37000,182.159.31.76:37001,182.159.31.76:37002
")
sh.addShard("rs_shardsvr2/182.159.31.76:37003,182.159.31.76:37004,182.159.31.76:37005
")
这样我们的分片集群就搭建好了,接下来就是启用和设置我们的分片
2.6 分片设置
第一步:对usertest数据库启用分片
sh.enableSharding("usertest")
第二步:设置分片规则,常用的有两种,第一种是hash分片,hash分片非常简单,直接设置即可
#设置分片规则,按照_id的hash进行区分,第一个参数是指定mongodb中的collection
sh.shardCollection("test.user", {"_id": "hashed" })
第二种是根据索引进行分片,因此设置分片时,需要先添加索引
#对userId创建索引
db.col.createIndex({"userid":1})
#创建索引后,就能进行分片
sh.shardCollection(“test.user” , "userid" : 1)
至此,mongodb的分片就设置完成了。