blog/linux/linux安装mongodb集群

linux安装mongodb集群

1、相关概念

img

从图中可以看到有四个组件: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

服务器规划

95108220242244
mongosmongos
config serverconfig serverconfig server
sshard1 servershard2 servershard3 servershard4 servershard5 server
shard5 servershard1 servershard2 servershard3 servershard4 server
shard4 servershard5 servershard1 servershard2 servershard3 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 <= 1000; 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:"useradmin",
pwd:"123456",
roles: [ { role: "userAdminAnyDatabase",db:"admin"},
{ role : "clusterAdmin", db : "admin" }
]
})
db.auth("useradmin","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

复制mongodb-keyfile文件到其他集群

scp /mnt/mongodb/key/mongodb-keyfile [email protected]:/mnt/mongodb/key/

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
mongos --config /mnt/mongodb/conf/mongos.conf

关闭时,直接killall杀掉所有进程

killall mongod
killall mongos

9、用户权限

9.1、创建用户

use admin
db.createUser({user:'superadmin',pwd:'123456', roles:[{role:'root', db:'admin'}]}) ---创建超级管理员用户

db.createUser({user:'useradmin',pwd:'123456', roles:[{role:'userAdminAnyDatabase', db:'admin'}]}) ---创建用户管理员账户(能查询其他库集合,但不能查询集合内容)

db.createUser({user:'admin',pwd:'123456', roles:[{role:'readWriteAnyDatabase', db:'admin'}]}) ---创建访问任意库读写的账户

db.createUser({user:'user1',pwd:'user1',roles:[{role:'readWrite',db:'test'}]}) ---创建只对test库有读写权限的用户

db.createUser({user:"bkuser2",pwd:"Bkuser2",roles:[{role:"backup",db:"admin"}]}) ---创建用于备份时的用户,如若是恢复权限,则将backup换为restore即可

9.2、用户查询

>use admin
>db.system.users.find().pretty() ---将所有用户信息查询出来

显示某一库下的所有用户
>use test
>show users ---显示在此库授权的用户信息

9.3、修改用户权限

db.updateUser("root",
{roles:[{role:"readWriteAnyDatabase",
db:"admin"}]
})

在原来权限上新增权限

db.grantRolesToUser("jianlong",[{role:'readWrite',db:'test'}])     ---不会覆盖原权限信息,只新增权限

9.4、修改用户密码

db.changeUserPassword("tuser","123456")

9.5、删除用户

db.system.users.remove({user:"tuser"});

10、mongodb常用数据库命令

10.1、数据库操作

show dbs;#查看数据库
use test;#如果没有就创建一个
db;#查看当前数据库
db.dropDatabase();#删除数据库

10.2、数据操作

插入

show collections;#查看集合
create collection;#创建集合
db.student.insert({"name":"张三","age":"22","sex":"男","class":"计算机2班"});#如果数据库中不存在集合,就创建并插入这些数据
db.student.insert({"name":"李四","age":"22","sex":"女","phone":"18513081650","class":"计算机1班"});#里面的key-value不用保持一致
db.student.insert([{"name":"王五","age":"22","sex":"男","class":"计算机2班"},{"name":"赵六","age":"22","sex":"女","phone":"18513081650","class":"计算机1班"}]);#同时插入多条数据

更新

db.student.update({"name":"张三"},{"name":"张三丰"});#如果有多条语句,只修改第一条,会覆盖原有数据
db.student.update({"22":"女"},{"name":"张三丰"});
db.student.update({"name":"张三"},{$set:{"name":"张无忌"}});#只想改某个key的value使用set
db.student.update({"name":"王五"},{$set:{"name":"张无忌"}},{multi:true});#把所有的记录都改了

查询

db.student.find();#查询全部
db.student.find({"name":"李四"});#查询指定记录,返回这一行结果
db.student.update({"name":"张三丰"},{"name":"张无忌","age":"28","sex":"男"});
db.student.find({"name":"张无忌","age":"28"});#and操作
db.student.find({$or:[{"name":"张无忌"},{"name":"李四"}]});#or操作
db.student.find().pretty();#格式化显示
db.student.find().count();#获取结果的行数
db.student.find().sort({"age":-1});#按照sort里面key的值排序,1为正序,-1为倒序

删除

db.student.remove();#删除所有数据
db.student.remove({"22":"女"});#按照条件删除
db.student.remove({"name":"张无忌"},2);#删除几条
本文总阅读量