概述:
MongoDB 是一个基于分布式文件存储的Nosql数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。目前mongodb官网提供了三种集群的搭建方式:1、主从(官网已不推荐)2、副本集 3、分片。本章主要介绍分片+副本集+配置服务+路由节点的部署方式。
- 为何要分片?
对于大多数程序而言,在一台服务器上保存完整的数据集完全足够了。但是随着数据量的增长,以及应用程序对数据吞吐量的要求越来越高,普通服务器和数据库就显得捉襟见肘了。尤其这些服务器没法分配足够的内存,或者没有足够的CPU核数来有效处理工作负荷。除此之外,随着数据量的增长,要在一块磁盘或者一组RAID队列上保存和管理大规模的数据集也变得不现实。从节点压力在高并发大数据量的场景下存在很大挑战,同时考虑到后期mongodb集群的在数据压力巨大时的扩展性,应对海量数据引出了分片机制。
架构图:
从架构图从可以看出,mongoDB集群有mongos,replicat set,shard,config servers组成。
mongos:数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
replicat set:副本集,其实就是shard的备份,防止shard挂掉之后数据丢失。复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
shard:分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。
config servers:配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,防止数据丢失。
仲裁者(Arbiter),是复制集中的一个MongoDB实例,它并不保存数据。仲裁节点使用最小的资源并且不要求硬件设备,不能将Arbiter部署在同一个数据集节点中,可以部署在其他应用服务器或者监视服务器中,也可部署在单独的虚拟机中。为了确保复制集中有奇数的投票成员(包括primary),需要添加仲裁节点做为投票,否则primary不能运行时不会自动切换primary。
- 环境部署
- 基础环境 系统:centos6.5 服务器:192.168.149.193/192/185 安装包:mongodb-linux-x86_64-rhel62-3.4.19.tgz
主机名 IP 组件mongos 组件config Server 组件shard的副本集 shard名称 jshy193 192.168.149.193 端口:40000 端口:27019 主节点 端口:30001 shard-a 裁决者节点 端口: 30002 shard-b 副节点 端口: 30003 shard-c jshy192 192.168.149.192 端口:40000 端口:27019 副节点 端口:30001 shard-a 主节点 端口: 30002 shard-b 裁决者节点 端口: 30003 shard-c jshy185 192.168.149.185 端口:40000 端口:27019 裁决者节点 端口:30001 shard-a 副节点 端口: 30002 shard-b 主节点 端口: 30003 shard-c - 下载tar包mongodb-linux-x86_64-rhel62-3.4.19.tgz 并上传至/home/mongo目录 部署 3.1、配置mongo目录,并解压部署包
[root@jshy185 home]# mkdir mongo #创建目录 [root@jshy185 home]# cd mongo/ #进入mongo目录并上传tgz包 [root@jshy185 mongo]# tar -zxvf mongodb-linux-x86_64-rhel62-3.4.19.tgz #解压tgz包 [root@jshy185 mongo]# vim /etc/profile #添加 内容 export MONGODB_HOME=/home/mongo/mongodb-linux-x86_64-rhel62-3.4.19 export PATH=$MONGODB_HOME/bin:$PATH [root@jshy185 mongo]# source /etc/profile
3.2、创建mongos(路由)、shard(分片目录)、conf(配置文件存放目录)、config(配置服务)、log(日志目录)等目录
#创建config server 配置服务目录 [root@jshy192 mongo]# mkdir -p data/config #创建配置文件目录conf,日志文件目录log,进程ID文件目录pidfile [root@jshy192 mongo]# mkdir -p conf log pidfile #创建数据集存放分片的副本集目录(rs-a是主节点目录,rs-b父节点目录、rs-c是裁决者节点目录) [root@jshy192 mongo]# mkdir -p data/shard/rs-a data/shard/rs-b data/shard/rs-c
3.3、配置服务的配置及启动,先创建config.conf文件,192环境创建后,同步到193和185服务器
[root@jshy192 mongo]# vim conf/config.conf //创建一个文件,内容如下 [root@jshy192 mongo]# cat conf/config.conf //显示文件内容 #配置服务路径 dbpath=/home/mongo/data/config #配置服务日志输出 logpath=/home/mongo/log/config.log #日志追加 logappend=true directoryperdb=true rest=true #端口 port=27019 #配置服务设置为true configsvr=true #设置副本集名称 replSet=configset #进程ID输出到文件 pidfilepath=/home/mongo/pidfile/config.pid #是否以守护进程方式运行 fork=true
启动三台服务器的config server
[root@jshy193 mongo]# mongodb-linux-x86_64-rhel62-3.4.19/bin/mongod -f /home/mongo/conf/config.conf #//启动配置服务
登录任意一台配置服务器,初始化配置副本集
连接mongo mongo --port 27019 #初始化副本集,其中_id:"configset"是副本集名称,在config.conf文件中设置为replSet=configset;host是其他配置服务IP和端口 rs.initiate({ _id:"configset", members:[ {_id:0,host:"192.168.149.193:27019"}, {_id:1,host:"192.168.149.192:27019"}, {_id:2,host:"192.168.149.185:27019"}]}); #查看初始化状态 rs.status(); 其输出状态: { "set" : "configset", "date" : ISODate("2019-02-20T02:20:46.906Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "configsvr" : true, "heartbeatIntervalMillis" : NumberLong(2000), "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "readConcernMajorityOpTime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "appliedOpTime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) } }, "members" : [ { "_id" : 0, "name" : "192.168.149.193:27019", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 653, "optime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2019-02-20T02:20:37Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "electionTime" : Timestamp(1550628955, 1), "electionDate" : ISODate("2019-02-20T02:15:55Z"), "configVersion" : 1, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 1, "name" : "192.168.149.192:27019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 302, "optime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2019-02-20T02:20:37Z"), "optimeDurableDate" : ISODate("2019-02-20T02:20:37Z"), "lastHeartbeat" : ISODate("2019-02-20T02:20:46.125Z"), "lastHeartbeatRecv" : ISODate("2019-02-20T02:20:46.729Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "192.168.149.193:27019", "syncSourceHost" : "192.168.149.193:27019", "syncSourceId" : 0, "infoMessage" : "", "configVersion" : 1 }, { "_id" : 2, "name" : "192.168.149.185:27019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 302, "optime" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1550629237, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2019-02-20T02:20:37Z"), "optimeDurableDate" : ISODate("2019-02-20T02:20:37Z"), "lastHeartbeat" : ISODate("2019-02-20T02:20:46.089Z"), "lastHeartbeatRecv" : ISODate("2019-02-20T02:20:46.409Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "192.168.149.193:27019", "syncSourceHost" : "192.168.149.193:27019", "syncSourceId" : 0, "infoMessage" : "", "configVersion" : 1 } ], "ok" : 1 }
3.4、配置并启动分片副本集 3.4.1 设置第一个shard-a分片副本集 3.4.1.1 创建配置文件 shard-a.conf,并同步到其他2台服务器
[root@jshy192 conf]# vim shard-a.conf //创建分片副本集配置文件 [root@jshy192 conf]# cat shard-a.conf //显示 #配置分片数据存放路径 dbpath=/home/mongo/data/shard/shard-a #配置服务日志输出 logpath=/home/mongo/log/shard-a.log #日志追加 logappend=true directoryperdb=true #打开web监控 rest=true httpinterface=false #端口 port=30001 #declare this is a shard db of a cluster; shardsvr=true #副本集名称 replSet=shard-a #进程ID输出到文件 pidfilepath=/home/mongo/pidfile/shard-a.pid #是否以守护进程方式运行 fork=true
3.4.1.2 启动shard-a的三台服务器shard server
mongod -f /home/mongo/conf/shard-a.conf
3.4.1.3 登录任一台服务,初始化分片的副本集
#连接分片副本集 mongo --port 30001 #使用admin数据库 use admin; #初始化副本集 193服务器作为主节点,192服务器作为从节点,185服务器为裁决者节点 rs.initiate({ _id:"shard-a", members:[ {_id:0,host:"192.168.149.193:30001"}, {_id:1,host:"192.168.149.192:30001"}, {_id:2,host:"192.168.149.185:30001",arbiterOnly: true }] }); #查看初始化副本集 rs.status();
3.4.2 设置第二个shard-b分片副本集 3.4.2.1 创建配置文件 shard-b.conf,并同步到其他2台服务器
[root@jshy192 conf]# vim shard-b.conf //创建分片副本集配置文件 [root@jshy192 conf]# cat shard-b.conf //显示 #配置分片数据存放路径 dbpath=/home/mongo/data/shard/shard-b #配置服务日志输出 logpath=/home/mongo/log/shard-b.log #日志追加 logappend=true directoryperdb=true #打开web监控 rest=true httpinterface=false #端口 port=30002 #declare this is a shard db of a cluster; shardsvr=true #副本集名称 replSet=shard-b #进程ID输出到文件 pidfilepath=/home/mongo/pidfile/shard-b.pid #是否以守护进程方式运行 fork=true
3.4.2.2 启动shard-a的三台服务器shard server
mongod -f /home/mongo/conf/shard-b.conf
3.4.2.3 登录任一台服务,初始化分片的副本集
#连接分片副本集 mongo --port 30002 #使用admin数据库 use admin; #初始化副本集 192服务器作为主节点,185服务器作为从节点,193服务器为裁决者节点 rs.initiate({ _id:"shard-b", members:[ {_id:0,host:"192.168.149.192:30002"}, {_id:1,host:"192.168.149.185:30002" }, {_id:2,host:"192.168.149.193:30002",arbiterOnly: true} ]}); #查看初始化副本集 rs.status();
3.4.3 设置第三个shard-c分片副本集 3.4.3.1 创建配置文件 shard-c.conf,并同步到其他2台服务器
[root@jshy192 conf]# vim shard-c.conf //创建分片副本集配置文件 [root@jshy192 conf]# cat shard-c.conf //显示 #配置分片数据存放路径 dbpath=/home/mongo/data/shard/shard-c #配置服务日志输出 logpath=/home/mongo/log/shard-c.log #日志追加 logappend=true directoryperdb=true #打开web监控 rest=true httpinterface=false #端口 port=30003 #declare this is a shard db of a cluster; shardsvr=true #副本集名称 replSet=shard-c #进程ID输出到文件 pidfilepath=/home/mongo/pidfile/shard-c.pid #是否以守护进程方式运行 fork=true
3.4.3.2 启动shard-a的三台服务器shard server
mongod -f /home/mongo/conf/shard-c.conf
3.4.3.3 登录任一台服务,初始化分片的副本集
#连接分片副本集 mongo --port 30003 #使用admin数据库 use admin; #初始化副本集 185服务器作为主节点,193服务器作为从节点,192服务器为裁决者节点 rs.initiate({ _id:"shard-c", members:[ {_id:1,host:"192.168.149.193:30003"}, {_id:2,host:"192.168.149.192:30003",arbiterOnly: true}, {_id:0,host:"192.168.149.185:30003" } ] }); #查看初始化副本集 rs.status();
3.5 配置路由服务器mongos
3.5.1 配置mongos.conf文件在/home/mongo/conf目录下,同步到另两台服务器
[root@jshy193 mongo]# vim conf/mongos.conf
[root@jshy193 mongo]# cat conf/mongos.conf
#监听的配置服务器,只能有1个或者3个 configset为配置服务器的副本集名字
configdb=configset/192.168.149.193:27019,192.168.149.192:27019,192.168.149.185:27019
logpath=/home/mongo/log/mongos.log
logappend=true
port=40000
pidfilepath=/home/mongo/pidfile/mongos.pid
fork=true
3.5.2 启动三台服务器的mongos server
mongos -f /home/mongo/conf/mongos.conf
3.6 启用分片
目前搭建了mongodb配置服务器、路由服务器,各个分片服务器,不过应用程序连接到mongos路由服务器并不能使用分片机制,还需要在程序里设置分片配置,让分片生效。
3.6.1 登陆任意一台mongos
mongo --port 40000
#使用admin数据库
use admin
#串联路由服务器与分配副本集
sh.addShard("shard-a/192.168.149.193:30001,192.168.149.192:30001,192.168.149.185:30001");
sh.addShard("shard-b/192.168.149.193:30002,192.168.149.192:30002,192.168.149.185:30002");
sh.addShard("shard-c/192.168.149.193:30003,192.168.149.192:30003,192.168.149.185:30003");
#查看集群状态
sh.status()
3.7 测试分片功能
目前路由服务、配置服务、分片服务、副本集服务都已经串联起来了。但是本章目的是希望插入数据,数据能够自动分片。连接在mongos上,准备让指定的数据库、指定的集合分片生效。
mongo --port 40000
use admin
#指定data_collect分片进行生效
db.runCommand( { enablesharding :"data_collect"});
#指定数据库里需要分片的集合和片键
db.runCommand( { shardcollection : "data_collect.testTable",key : {id: 1} } )
我们设置data_collect的 testTable表需要分片,根据 id 自动分片到 shard-a ,shard-b,shard3-c上面去。要这样设置是因为不是所有mongodb 的数据库和表 都需要分片!
mongo --port 40000
#跳到data_collect数据库中
use data_collect;
#插入数据
for (var i = 1; i <= 100000; i++) db.testTable.save({id:i,"test1":"我的神呀"});
3.8 mongodb集群的启动和维护
启动顺序
mongod -f /home/mongo/conf/config.conf
mongod -f /home/mongo/conf/shard-a.conf
mongod -f /home/mongo/conf/shard-b.conf
mongod -f /home/mongo/conf/shard-c.conf
mongos -f /home/mongo/conf/mongos.conf
关闭
killall mongod
killall mongos