一、分片集群简介:
关于MongoDB的复制集,复制集主要用来实现自动故障转移从而达到高可用的目的,然而,随着业务规模的增长和时间的推移,业务数据量会越来越大,当前业务数据可能只有几百GB不到,一台DB服务器足以搞定所有的工作,而一旦业务数据量扩充大几个TB几百个TB时,就会产生一台服务器无法存储的情况,此时,需要将数据按照一定的规则分配到不同的服务器进行存储、查询等,即为分片集群。分片集群要做到的事情就是数据分布式存储。
二、集群示意图及相关概念:
从图中可以看到有四个组件:mongos、config server、shard、replica set;
- mongos,数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
- config server,顾名思义为配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,这个可不能丢失!就算挂掉其中一台,只要还有存货, mongodb集群就不会挂掉。
shard,这就是传说中的分片了。上面提到一个机器就算能力再大也有天花板,就像军队打仗一样,一个人再厉害喝血瓶也拼不过对方的一个师。俗话说三个臭皮匠顶个诸葛亮,这个时候团队的力量就凸显出来了。在互联网也是这样,一台普通的机器做不了的多台机器来做,如下图:
一台机器的一个数据表 Collection1 存储了 1T 数据,压力太大了!在分给4个机器后,每个机器都是256G,则分摊了集中在一台机器的压力。也许有人问一台机器硬盘加大一点不就可以了,为什么要分给四台机器呢?不要光想到存储空间,实际运行的数据库还有硬盘的读写、网络的IO、CPU和内存的瓶颈。在mongodb集群只要设置好了分片规则,通过mongos操作数据库就能自动把对应的数据操作请求转发到对应的分片机器上。在生产环境中分片的片键可要好好设置,这个影响到了怎么把数据均匀分到多个分片机器上,不要出现其中一台机器分了1T,其他机器没有分到的情况,这样还不如不分片!
- replica set,上两节已经详细讲过了这个东东,怎么这里又来凑热闹!其实上图4个分片如果没有 replica set 是个不完整架构,假设其中的一个分片挂掉那四分之一的数据就丢失了,所以在高可用性的分片架构还需要对于每一个分片构建 replica set 副本集保证分片的可靠性。
三、集群环境搭建:
- 集群架构:如图:
(仲裁节点暂时不要)
- 系统环境:Centos7.5、MongoDB4.0.12、关闭防火墙
三台机器的配置服务(27018)形成复制集,分片1、2、3也在各机器都部署一个实例,它们之间形成复制集,客户端直接连接3个路由服务与之交互,配置服务和分片服务对客户端是透明的。
- 环境准备好了,准备安装:
- 防火墙关闭并重启服务器: 1>systemctl stop firewalld//临时关闭 ;systemctl disable firewalld//禁止开机启动;
2>重启linux服务器命令:reboot; 确保服务器互通;
- 分别在每台机器新建mongo目录 (sudo -s ) -->(cd /usr/local/softs)--> (mkdir mongo) ;切换到mongo目录 (cd mongo);
- 下载解压mongodb至mongo目录,我用的是 mongodb-linux-x86_64-4.0.12.tgz;(tar xvzf mongodb-linux-x86_64-4.0.12.tgz)
- 分别在每台机器的mongo目录下建立完整目录:
#配置、节点1、2、3的数据库存放目录mkdir -p data/config
mkdir -p data/shard1
mkdir -p data/shard2
mkdir -p data/shard3#配置、路由、节点1、2、3的日志存放目录
touch log/config.log
touch log/mongos.log
touch log/shard1.log
touch log/shard2.log
touch log/shard3.log#配置、路由、节点1、2、3的配置文件存放目录
touch conf/config.conf
touch conf/mongos.conf
touch conf/shard1.conf
touch conf/shard2.conf
touch conf/shard3.conf - chmod -R 777 /usr/local/softs/mongo/ 目录文件夹授权命令,如:chmod -R 777 /usr/local/softs/mongo/ 为mongo文件夹下的文件可见,可编辑
- config服务器部署:(3台服务器执行相同操作) 打开conf/config.conf文件(若没权限执行授权命令)将如下数据拷贝:dbpath=/usr/local/softs/mongo/data/config
logpath=/usr/local/softs/mongo/log/config.log
port=27018
logappend=true
fork=true
maxConns=5000
#复制集名称
replSet=configs
#置参数为true
configsvr=true
#允许任意机器连接
bind_ip=0.0.0.0 - mongos服务器部署:(3台服务器执行相同操作)打开conf/mongos.conf文件(若没权限执行授权命令)将如下数据拷贝: systemLog:
destination: file
logAppend: true
path: /usr/local/softs/mongo/log/mongos.log
processManagement:
fork: true
# pidFilePath: /var/log/nginx/mongodbmongos.pid
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
#监听的配置服务器,只能有1个或者3个 configs为配置服务器的副本集名字
sharding:
configDB: configs/10.238.220.135:27018,10.238.220.208:27018,10.238.220.237:27018 - 配置各分片服务器的副本集:(3台服务器执行相同操作)打开conf/shard1(shard2、shard3).conf文件(若没权限执行授权命令)将如下数据拷贝: dbpath=/usr/local/softs /mongo/data/shard1 #其他2个分片对应修改为shard2、shard3文件夹
logpath=/usr/local/softs/mongo/log/shard1.log #其他2个分片对应修改为shard2.log、shard3.log
port=27001 #其他2个分片对应修改为27002、27003
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
shardsvr=true
replSet=shard1 #其他2个分片对应修改为shard2、shard3
bind_ip=0.0.0.0 - 目前为止,各服务器的mongos、config、shard1、shard2、shard3都已配置完成,接下来我们需要一一启动,初始化顺序 shard1->shard2->shard3->config->mongos
分别启动三台服务器的分片1(shard1)服务:
mongodb-linux-x86_64-4.0.12/bin/mongod -f conf/shard1.conf
连接mongo,只需在任意一台机器执行即可:
mongodb-linux-x86_64-4.0.12/bin/mongo --port 27001
使用admin数据库:use admin
其他2个分片对应修改为shard2、shard3;
config = { _id:"shard1", members:[
{_id:0,host:"10.238.220.135:27001"},
{_id:1,host:"10.238.220.208:27001"},
{_id:2,host:"10.238.220.237:27001"}
]
}
#初始化副本集配置 rs.initiate(config);
#查看j状态:rs.status()
分别启动三台服务器的配置(config)服务:
mongodb-linux-x86_64-4.0.12/bin/mongod -f conf/config.conf
mongodb-linux-x86_64-4.0.12/bin/mongo --port 27018
config = { _id:"configs", members:[
{_id:0,host:"10.238.220.135:27018"},
{_id:1,host:"10.238.220.208:27018"},
{_id:2,host:"10.238.220.237:27018"}
]
}
rs.initiate(config);rs.status()
分别启动三台服务器的路由(mongos)服务:
mongodb-linux-x86_64-4.0.12/bin/mongos -f conf/mongos.conf
mongodb-linux-x86_64-4.0.12/bin/mongo --port 27017
config = { _id:"shard1", members:[
{_id:0,host:"10.238.220.135:27018"},
{_id:1,host:"10.238.220.208:27018"},
{_id:2,host:"10.238.220.237:27018"}
]
}
rs.initiate(config);rs.status()
#在任意一台路由服务器执行:
sh.addShard("shard1/10.238.220.135:27001,10.238.220.208:27001,10.238.220.237:27001")
sh.addShard("shard2/10.238.220.135:27002,10.238.220.208:27002,10.238.220.237:27002")
sh.addShard("shard3/10.238.220.135:27003,10.238.220.208:27003,10.238.220.237:27003")
sh.status();
测试:
use ycsb
sh.enableSharding("ycsb");
sh.shardCollection("ycsb.usertable",{"_id":"hashed"});
for(i=1;i<=50000;i++){db.usertable.insert({"id":i})}
db.stats();
问题总结:
数据库集合的片键必须预置,集合有数据之后在设置片键会出现不自动分片的问题