1、相关概念
从图中可以看到有四个组件:mongos、config server、shard、replica set。
mongos,数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
config server,配置服务器,存储所有数据库元信息(路由、分片)的配置。mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。mongos第一次启动或者关掉重启就会从 config server 加载配置信息,以后如果配置服务器信息变化会通知到所有的 mongos 更新自己的状态,这样 mongos 就能继续准确路由。在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,防止数据丢失!
shard,分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程。将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。
replica set,中文翻译副本集,其实就是shard的备份,防止shard挂掉之后数据丢失。复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。
仲裁者(Arbiter),是复制集中的一个MongoDB实例,它并不保存数据。仲裁节点使用最小的资源并且不要求硬件设备,不能将Arbiter部署在同一个数据集节点中,可以部署在其他应用服务器或者监视服务器中,也可部署在单独的虚拟机中。为了确保复制集中有奇数的投票成员(包括primary),需要添加仲裁节点做为投票,否则primary不能运行时不会自动切换primary。
简单了解之后,我们可以这样总结一下,应用请求mongos来操作mongodb的增删改查,配置服务器存储数据库元信息,并且和mongos做同步,数据最终存入在shard(分片)上,为了防止数据丢失同步在副本集中存储了一份,仲裁在数据存储到分片的时候决定存储到哪个节点。
2、环境准备
系统系统 centos7
五台服务器:10.253.173.95、10.253.173.108、10.253.164.220、10.253.164.242、10.253.164.244
安装包: mongodb-linux-x86_64-3.4.6.tgz
服务器规划
95 | 108 | 220 | 242 | 244 |
---|---|---|---|---|
mongos | mongos | mongos | ||
config server | config server | config server | ||
shard1 server | shard2 server | shard3 server | shard4 server | shard5 server |
shard5 server | shard1 server | shard2 server | shard3 server | shard4 server |
shard4 server | shard5 server | shard1 server | shard2 server | shard3 server |
端口分配:
mongos:20000
config:21000
shard1:27001
shard2:27002
shard3:27003
shard4:27004
shard5:27005
3、集群搭建
3.1、安装mongodb
下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.6.tgz
#解压
tar -xzvf mongodb-linux-x86_64-3.4.6.tgz -C /opt/
#重命名
mv mongodb-linux-x86_64-3.4.6 mongodb
分别在每台机器建立conf、mongos、config、shard1、shard2、shard3六个目录,因为mongos不存储数据,只需要建立日志文件目录即可。
mkdir -p /mnt/mongodb/conf
mkdir -p /mnt/mongodb/mongos/log
mkdir -p /mnt/mongodb/config/data
mkdir -p /mnt/mongodb/config/log
mkdir -p /mnt/mongodb/shard1/data
mkdir -p /mnt/mongodb/shard1/log
mkdir -p /mnt/mongodb/shard2/data
mkdir -p /mnt/mongodb/shard2/log
mkdir -p /mnt/mongodb/shard3/data
mkdir -p /mnt/mongodb/shard3/log
mkdir -p /mnt/mongodb/shard4/data
mkdir -p /mnt/mongodb/shard4/log
mkdir -p /mnt/mongodb/shard5/data
mkdir -p /mnt/mongodb/shard5/log
配置环境变量vim /etc/profile
export MONGODB_HOME=/opt/mongodb
export PATH=$MONGODB_HOME/bin:$PATH
环境变量生效
source /etc/profile
3.2、config server配置服务器
mongodb3.4以后要求配置服务器也创建副本集,不然集群搭建不成功。
添加配置文件vi /mnt/mongodb/conf/config.conf,其中bindIp替换为对应机器的ip
# 系统日志
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/config/log/config.log #日志存储位置
# 文件存储
storage:
dbPath: /mnt/mongodb/config/
journal:
enabled: true
directoryPerDB: true #是否一个库一个文件夹
engine: wiredTiger #数据引擎
wiredTiger: #WT引擎配置
engineConfig:
cacheSizeGB: 4 #设置为4G,默认为物理内存的一半
directoryForIndexes: true #是否将索引也按数据库名单独存储
journalCompressor: zlib
collectionConfig: #表压缩配置
blockCompressor: zlib
indexConfig: #索引配置
prefixCompression: true
# 配置启动管理方式
processManagement:
fork: true
pidFilePath: /mnt/mongodb/config/log/configsrv.pid
# 网络接口
net:
port: 21000
bindIp: 10.253.173.95
# 副本集
replication:
replSetName: config
sharding:
clusterRole: configsvr
启动三台服务器的config server
mongod -f /mnt/mongodb/conf/config.conf
登录任意一台配置服务器,初始化配置副本集
#连接
mongo 10.253.173.95:21000
#config变量
config = {
_id : "config",
members : [
{_id : 0, host : "10.253.173.95:21000" },
{_id : 1, host : "10.253.173.108:21000" },
{_id : 2, host : "10.253.164.220:21000" }
]
}
#初始化副本集
rs.initiate(config)
#查看分区状态
rs.status();
3.3、配置分片副本集
3.1、设置第一个分片副本集
在服务器上,10.253.173.95、10.253.173.108、10.253.164.220
配置文件:vi /mnt/mongodb/conf/shard1.conf,其中bindIp换成对应机器的ip
## 配置文件内容
# 系统日志
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/shard1/log/shard1.log
# 文件存储
storage:
dbPath: /mnt/mongodb/shard1/data
journal:
enabled: true
wiredTiger: #WT引擎配置
engineConfig:
cacheSizeGB: 4 #设置为4G,默认为物理内存的一半
directoryForIndexes: true #是否将索引也按数据库名单独存储
journalCompressor: zlib
collectionConfig: #表压缩配置
blockCompressor: zlib
indexConfig: #索引配置
prefixCompression: true
# 进程
processManagement:
fork: true
pidFilePath: /mnt/mongodb/shard1/log/shard1.pid
# 网络接口
net:
port: 27001
bindIp: 10.253.173.95
# 副本集
replication:
replSetName: shard1
sharding:
clusterRole: shardsvr
启动三台服务器的shard1 server
mongod -f /mnt/mongodb/conf/shard1.conf
登陆任意一台服务器,初始化副本集
mongo 10.253.173.95:27001
#使用admin数据库
use admin
#定义副本集配置
config = {
_id : "shard1",
members : [
{_id : 0, host : "10.253.173.95:27001" },
{_id : 1, host : "10.253.173.108:27001" },
{_id : 2, host : "10.253.164.220:27001" }
]
}
#初始化副本集配置
rs.initiate(config);
#查看分区状态
rs.status();
3.2、设置第二个分片副本集
在服务器上,10.253.173.108、10.253.164.220、10.253.164.242
配置文件:vi /mnt/mongodb/conf/shard2.conf,其中bindIp换成对应机器的ip
## 配置文件内容
# 系统日志
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/shard2/log/shard2.log
# 文件存储
storage:
dbPath: /mnt/mongodb/shard2/data
journal:
enabled: true
wiredTiger: #WT引擎配置
engineConfig:
cacheSizeGB: 4 #设置为4G,默认为物理内存的一半
directoryForIndexes: true #是否将索引也按数据库名单独存储
journalCompressor: zlib
collectionConfig: #表压缩配置
blockCompressor: zlib
indexConfig: #索引配置
prefixCompression: true
# 进程
processManagement:
fork: true
pidFilePath: /mnt/mongodb/shard2/log/shard2.pid
# 网络接口
net:
port: 27002
bindIp: 10.253.173.108
# 副本集
replication:
replSetName: shard2
sharding:
clusterRole: shardsvr
启动三台服务器的shard2 server
mongod -f /mnt/mongodb/conf/shard2.conf
登陆任意一台服务器,初始化副本集
mongo 10.253.173.108:27002
#使用admin数据库
use admin
#定义副本集配置
config = {
_id : "shard2",
members : [
{_id : 0, host : "10.253.173.108:27002" },
{_id : 1, host : "10.253.164.220:27002" },
{_id : 2, host : "10.253.164.242:27002" }
]
}
#初始化副本集配置
rs.initiate(config);
#查看分区状态
rs.status();
3.3、设置第三个分片副本集
在服务器上,10.253.164.220、10.253.164.242、10.253.164.244
配置文件:vi /mnt/mongodb/conf/shard3.conf,其中bindIp换成对应机器的ip
## 配置文件内容
# 系统日志
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/shard3/log/shard3.log
# 文件存储
storage:
dbPath: /mnt/mongodb/shard3/data
journal:
enabled: true
wiredTiger: #WT引擎配置
engineConfig:
cacheSizeGB: 4 #设置为4G,默认为物理内存的一半
directoryForIndexes: true #是否将索引也按数据库名单独存储
journalCompressor: zlib
collectionConfig: #表压缩配置
blockCompressor: zlib
indexConfig: #索引配置
prefixCompression: true
# 进程
processManagement:
fork: true
pidFilePath: /mnt/mongodb/shard3/log/shard3.pid
# 网络接口
net:
port: 27003
bindIp: 10.253.164.220
# 副本集
replication:
replSetName: shard3
sharding:
clusterRole: shardsvr
启动三台服务器的shard3 server
mongod -f /mnt/mongodb/conf/shard3.conf
登陆任意一台服务器,初始化副本集
mongo 10.253.164.220:27003
#使用admin数据库
use admin
#定义副本集配置
config = {
_id : "shard3",
members : [
{_id : 0, host : "10.253.164.220:27003" },
{_id : 1, host : "10.253.164.242:27003" },
{_id : 2, host : "10.253.164.244:27003" }
]
}
#初始化副本集配置
rs.initiate(config);
#查看分区状态
rs.status();
3.4、设置第四个分片副本集
在服务器上,10.253.164.242、10.253.164.244、10.253.173.95
配置文件:vi /mnt/mongodb/conf/shard4.conf,其中bindIp换成对应机器的ip
## 配置文件内容
# 系统日志
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/shard4/log/shard4.log
# 文件存储
storage:
dbPath: /mnt/mongodb/shard4/data
journal:
enabled: true
wiredTiger: #WT引擎配置
engineConfig:
cacheSizeGB: 4 #设置为4G,默认为物理内存的一半
directoryForIndexes: true #是否将索引也按数据库名单独存储
journalCompressor: zlib
collectionConfig: #表压缩配置
blockCompressor: zlib
indexConfig: #索引配置
prefixCompression: true
# 进程
processManagement:
fork: true
pidFilePath: /mnt/mongodb/shard4/log/shard4.pid
# 网络接口
net:
port: 27004
bindIp: 10.253.164.242
# 副本集
replication:
replSetName: shard4
sharding:
clusterRole: shardsvr
启动三台服务器的shard4 server
mongod -f /mnt/mongodb/conf/shard4.conf
登陆任意一台服务器,初始化副本集
mongo 10.253.164.242:27004
#使用admin数据库
use admin
#定义副本集配置
config = {
_id : "shard4",
members : [
{_id : 0, host : "10.253.164.242:27004" },
{_id : 1, host : "10.253.164.244:27004" },
{_id : 2, host : "10.253.173.95:27004" }
]
}
#初始化副本集配置
rs.initiate(config);
#查看分区状态
rs.status();
3.5、设置第五个分片副本集
在服务器上,10.253.164.244、10.253.173.95、10.253.173.108
配置文件:vi /mnt/mongodb/conf/shard5.conf,其中bindIp换成对应机器的ip
## 配置文件内容
# 系统日志
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/shard5/log/shard5.log
# 文件存储
storage:
dbPath: /mnt/mongodb/shard5/data
journal:
enabled: true
wiredTiger: #WT引擎配置
engineConfig:
cacheSizeGB: 4 #设置为4G,默认为物理内存的一半
directoryForIndexes: true #是否将索引也按数据库名单独存储
journalCompressor: zlib
collectionConfig: #表压缩配置
blockCompressor: zlib
indexConfig: #索引配置
prefixCompression: true
# 进程
processManagement:
fork: true
pidFilePath: /mnt/mongodb/shard5/log/shard5.pid
# 网络接口
net:
port: 27005
bindIp: 10.253.164.244
# 副本集
replication:
replSetName: shard5
sharding:
clusterRole: shardsvr
启动三台服务器的shard5 server
mongod -f /mnt/mongodb/conf/shard5.conf
登陆任意一台服务器,初始化副本集
mongo 10.253.164.244:27005
#使用admin数据库
use admin
#定义副本集配置
config = {
_id : "shard5",
members : [
{_id : 0, host : "10.253.164.244:27005" },
{_id : 1, host : "10.253.173.95:27005" },
{_id : 2, host : "10.253.173.108:27005" }
]
}
#初始化副本集配置
rs.initiate(config);
#查看分区状态
rs.status();
4、配置路由服务器 mongos
先启动配置服务器和分片服务器,后启动路由实例启动路由实例:10.253.173.95、10.253.173.108
配置路由服务器:vi /mnt/mongodb/conf/mongos.conf
systemLog:
destination: file
logAppend: true
path: /mnt/mongodb/mongos/log/mongos.log
processManagement:
fork: true
net:
port: 20000
bindIp: 10.253.164.220
#监听的配置服务器,只能有1个或者3个 configs为配置服务器的副本集名字
sharding:
configDB: config/10.253.173.95:21000,10.253.173.108:21000,10.253.164.220:21000
启动二台服务器的mongos server
mongos --config /mnt/mongodb/conf/mongos.conf
5、启用分片
目前搭建了mongodb配置服务器、路由服务器,各个分片服务器,不过应用程序连接到mongos路由服务器并不能使用分片机制,还需要在程序里设置分片配置,让分片生效。
登陆任意一台mongos
mongo 10.253.173.95:20000
#使用admin数据库
use admin
#串联路由服务器与分配副本集
sh.addShard("shard1/10.253.173.95:27001,10.253.173.108:27001,10.253.164.220:27001")
sh.addShard("shard2/10.253.173.108:27002,10.253.164.220:27002,10.253.164.242:27002")
sh.addShard("shard3/10.253.164.220:27003,10.253.164.242:27003,10.253.164.244:27003")
sh.addShard("shard4/10.253.164.242:27004,10.253.164.244:27004,10.253.173.95:27004")
sh.addShard("shard5/10.253.164.244:27005,10.253.173.95:27005,10.253.173.108:27005")
#查看集群状态
sh.status()
6、测试
目前配置服务、路由服务、分片服务、副本集服务都已经串联起来了,但我们的目的是希望插入数据,数据能够自动分片。连接在mongos上,准备让指定的数据库、指定的集合分片生效。
mongo 10.253.173.95:20000
#使用admin
use admin;
#指定testdb分片生效
db.runCommand( { enablesharding :"userinfodb"});
#指定数据库里需要分片的集合和片键
db.runCommand({shardcollection : "userinfodb.authinfo",key : {id:1}})
我们设置testdb的 table1 表需要分片,根据 id 自动分片到 shard1 ,shard2,shard3,shard4,shard5 上面去。要这样设置是因为不是所有mongodb 的数据库和表 都需要分片!
测试分片配置结果
mongo 10.253.173.95:20000
#使用userinfodb
use userinfodb;
#插入测试数据
for (var i = 1; i <= 2; i++)db.authinfo.save({id:i,"test1":"testval1"})
#查看分片情况如下,部分无关信息省掉了
db.authinfo.stats();
{
"sharded" : true,
"ns" : "testdb.table1",
"count" : 100000,
"numExtents" : 13,
"size" : 5600000,
"storageSize" : 22372352,
"totalIndexSize" : 6213760,
"indexSizes" : {
"_id_" : 3335808,
"id_1" : 2877952
},
"avgObjSize" : 56,
"nindexes" : 2,
"nchunks" : 3,
"shards" : {
"shard1" : {
"ns" : "testdb.table1",
"count" : 42183,
"size" : 0,
...
"ok" : 1
},
"shard2" : {
"ns" : "testdb.table1",
"count" : 38937,
"size" : 2180472,
...
"ok" : 1
},
"shard3" : {
"ns" : "testdb.table1",
"count" :18880,
"size" : 3419528,
...
"ok" : 1
}
},
"ok" : 1
}
可以看到数据分到3个分片,各自分片数量为: shard1 “count” : 42183,shard2 “count” : 38937,shard3 “count” : 18880。已经成功了!
7、创建认证用户
7.1 首先建立一个拥有添加删除用户权限的账号
db.createUser({
user:"admin",
pwd:"123456",
roles: [ { role: "userAdminAnyDatabase",db:"admin"}]
})
db.auth("admin","123456")//认证该用户
这里就添加了一个useradmin这么一个用户,他可以进行所有数据库的用户管理。在添加这个用户后,我们连接mongodb时仍然不需要进行登录,这是因为我们未在配置中开启权限验证。
7.2.开启分片集群的权限验证
7.2.1 首先生成一个添加keyFile文件----->用于认证使用
openssl rand -base64 753 >mongodb-keyfile
mkdir -p /mnt/mongodb/key/
cp mongodb-keyfile /mnt/mongodb/key/
chmod 600 /mnt/mongodb/key/mongodb-keyfile
7.2.2 在各个分片以及configserver的配置文件中加上如下语句
#开启权限验证
security:
authorization: enabled
keyFile: /mnt/mongodb/key/mongodb-keyfile
7.2.3 在每台机器上的mongos配置文件中加入下面一段配置
#开启权限验证
security:
keyFile: /mnt/mongodb/key/mongodb-keyfile
8、启动关闭
mongodb的启动顺序是,先启动配置服务器,在启动分片,最后启动mongos.
mongod -f /mnt/mongodb/conf/config.conf
mongod -f /mnt/mongodb/conf/shard1.conf
mongod -f /mnt/mongodb/conf/shard2.conf
mongod -f /mnt/mongodb/conf/shard3.conf
mongod -f /mnt/mongodb/conf/mongos.conf
关闭时,直接killall杀掉所有进程
killall mongod
killall mongos