前置文章:
MongoDB-基础使用(一),该文主要介绍MongoDB概念、安装、库/集合(表)/文档(行)操作;
MongoDB-基础使用(二),该文主要介绍了MongoDB索引、基本API操作;
零、本文纲要
一、MongoDB 复制(副本集)
- 角色
- 数据复制
- 副本集特点
- 创建副本集
- 副本集数据读写操作
- 副本集选举原则
二、分片集群-Sharded Cluster
- 分片集群组成
- 分片集群架构
- 分片集群的创建
三、安全认证
- 保障MongoDB安全
- MongoDB安全认证-单实例环境
- MongoDB安全认证-副本集环境
- MongoDB安全认证-分片集群环境
一、MongoDB 复制(副本集)
1. 角色
主要成员(Primary) / 副本成员(Replicate) / 仲裁者(Arbiter)
① 数据承载节点(主 | 从);
② 仲裁节点(可选)。
仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用。
当然也可以将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。
2. 数据复制
主节点:记录在其上的所有操作 oplog
;
从节点:定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
3. 副本集特点
a、N 个节点的集群;
b、任何节点可作为主节点;
c、所有写入操作都在主节点上;
d、自动故障转移;
e、自动恢复。
4. 创建副本集
① 创建主节点
Ⅰ 建立存放数据和日志的目录
mkdir -p /mongodb/replica_sets/myrs_27017/log
mkdir -p /mongodb/replica_sets/myrs_27017/data/db
Ⅱ 新建或修改配置文件
vim /mongodb/replica_sets/myrs_27017/mongod.conf
与单机MongoDB配置文件不同的地方是新增了 replication.replSetName
属性的配置,如下:
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/mongodb/replica_sets/myrs_27017/log/mongod.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
logAppend: true
storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
dbPath: "/mongodb/replica_sets/myrs_27017/data/db"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/mongodb/replica_sets/myrs_27017/log/mongod.pid"
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP
bindIp: localhost,192.168.0.2
#bindIp
#绑定的端口
port: 27017
replication:
#副本集的名称
replSetName: myrs
Ⅲ 启动节点服务
bin/mongod -f replica_sets/myrs_27017/mongod.conf
② 创建副本节点
Ⅰ 建立存放数据和日志的目录
mkdir -p /mongodb/replica_sets/myrs_27018/log
mkdir -p /mongodb/replica_sets/myrs_27018/data/db
Ⅱ 新建或修改配置文件
vim /mongodb/replica_sets/myrs_27018/mongod.conf
只要将对应的日志/数据存放目录,端口号修改成副本节点的即可。具体内容此处省略。
Ⅲ 启动节点服务
bin/mongod -f replica_sets/myrs_27018/mongod.conf
③ 创建仲裁节点
Ⅰ 建立存放数据和日志的目录
mkdir -p /mongodb/replica_sets/myrs_27019/log
mkdir -p /mongodb/replica_sets/myrs_27019/data/db
Ⅱ 新建或修改配置文件
vim /mongodb/replica_sets/myrs_27019/mongod.conf
只要将对应的日志/数据存放目录,端口号修改成副本节点的即可。具体内容此处省略。
Ⅲ 启动节点服务
bin/mongod -f replica_sets/myrs_27019/mongod.conf
④ 初始化配置副本集和主节点
连接至主节点客户端:
bin/mongo --host=180.76.159.126 --port=27017
初始化新的副本集:
rs.initiate()
myrs:SECONDARY> #此处键入 enter 即可
myrs:PRIMARY>
⑤ 查看副本集的配置内容 & 状态
rs.config() #查看配置内容
rs.status() #查看状态
⑥ 添加副本从节点 & 仲裁节点
分别是 rs.add("IP:PORT")
和 rs.addArb("IP:PORT")
# 添加副本集从节点
rs.add("180.76.159.126:27018")
# 添加副本集仲裁节点
rs.addArb("180.76.159.126:27019")
5. 副本集数据读写操作
① 各节点特点
Ⅰ 主节点
可读可写。
Ⅱ 从节点
默认未配置不可读,需先配置,如下:
# 登录至从节点
bin/mongo --host 180.76.159.126 --port
# 配置读权限
rs.slaveOk()
# 也可以是 rs.slaveOk(true)
# 或者 db.getMongo().setSlaveOk()
# 取消读权限
rs.slaveOk(false)
Ⅲ 仲裁节点
不存放业务数据,仅存放副本集配置等数据。
② SpringDataMongoDB连接副本集
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
配置文件application.yml,如下:
spring:
#数据源配置
data:
mongodb:
# 主机地址
# host: 180.76.159.126
# 数据库
# database: articledb
# 默认端口是27017
# port: 27017
#也可以使用uri连接
#uri: mongodb://192.168.40.134:27017/articledb
# 副本集的连接字符串
uri: mongodb://180.76.159.126:27017,180.76.159.126:27018,180.76.159.126:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
6. 副本集选举原则
① 主节点选举的触发条件
a、主节点故障;
b、主节点网络不可达(默认心跳信息为10秒);
c、人工干预(rs.stepDown(600))。
② 选举原则
a、票数最高,且获得"大多数"投票(N / 2 + 1);
b、满足一,则取操作日志 oplog
数据最新。
③ 优先级
可以通过设置优先级(priority)来设置获取更多投票的可能性。
优先级即权重,取值为0-1000。
从节点操作:
#先将配置导入cfg变量
cfg=rs.conf()
#然后修改值(ID号默认从0开始,从rs.conf()结果查看当前节点的"_id")
cfg.members[1].priority=2
#重新加载配置
rs.reconfig(cfg)
注意:当副本集不能满足"大多数"的情况,将不对外提供写服务,已经是故障状态了。
二、分片集群-Sharded Cluster
1. 分片集群组成
a、Shard:用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障;
b、Query Routers:mongos充当查询路由器,在客户端应用程序和分片群集之间提供接口;
c、Config Server:mongod实例,存储了整个 ClusterMetadata,其中包括 chunk信息;
注意:从MongoDB 3.4开始,必须将Config Server配置服务器部署为副本集(CSRS)。
2. 分片集群架构
① 两个分片节点副本集
a、副本集1
Primary:27018;
Secondary:27118;
Arbiter:27218。
b、副本集2
Primary:27318;
Secondary:27418;
Arbiter:27518。
② 一个配置节点副本集
Primary:27019;
Secondary:27119;
Secondary:27219。
③ 两个路由节点
Router1:27017;
Router2:27018。
3. 分片集群的创建
① 创建副本集
具体过程同上,配置文件略有不同,增加了 sharding.clusterRole
的配置,如下:
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/mongodb/sharded_cluster/myshardrs01_27018/log/mongod.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
logAppend: true
storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
dbPath: "/mongodb/sharded_cluster/myshardrs01_27018/data/db"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/mongodb/sharded_cluster/myshardrs01_27018/log/mongod.pid"
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP
bindIp: localhost,192.168.0.2
#bindIp
#绑定的端口
port: 27018
replication:
#副本集的名称
replSetName: myshardrs01
sharding:
#分片角色
clusterRole: shardsvr
② 创建配置节点副本集
具体过程同副本集创建,增加了 sharding.clusterRole
的配置,如下:
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/mongodb/sharded_cluster/myconfigrs_27019/log/mongod.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
logAppend: true
storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
dbPath: "/mongodb/sharded_cluster/myconfigrs_27019/data/db"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/mongodb/sharded_cluster/myconfigrs_27019/log/mongod.pid"
net:
#服务实例绑定所有IP
#bindIpAll: true
#服务实例绑定的IP
bindIp: localhost,192.168.0.2
#绑定的端口
port: 27019
replication:
replSetName: myconfigrs
sharding:
clusterRole: configsvr
③ 创建路由节点
Ⅰ 准备存放数据和日志的目录
mkdir -p /mongodb/sharded_cluster/mymongos_27017/log
Ⅱ 新建或修改配置文件
vi /mongodb/sharded_cluster/mymongos_27017/mongos.conf
mongos.conf 如下:
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/mongodb/sharded_cluster/mymongos_27017/log/mongod.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
logAppend: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: /mongodb/sharded_cluster/mymongos_27017/log/mongod.pid"
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP
bindIp: localhost,192.168.0.2
#bindIp
#绑定的端口
port: 27017
sharding:
#指定配置节点副本集
configDB: myconfigrs/180.76.159.126:27019,180.76.159.126:27119,180.76.159.126:27219
Ⅲ 启动登录mongos
#启动
bin/mongos -f sharded_cluster/mymongos_27017/mongos.conf
#登录
bin/mongo --host 180.76.159.126 --port 27017
Ⅳ 在路由节点上进行分片配置操作
# 添加分片
sh.addShard("myshardrs01/192.168.0.2:27018,180.76.159.126:27118,180.76.159.126:27218")
sh.addShard("myshardrs02/192.168.0.2:27318,180.76.159.126:27418,180.76.159.126:27518")
# 查看分片状态
sh.status()
# 开启分片功能
sh.enableSharding("db_name[.collection_name]"[,{"key": order_value}]")
sh.enableSharding("articledb")
# 集合分片
# 分片规则一:哈希策略(推荐使用)
# 使用nickname作为片键,根据其值的哈希值进行数据分片
sh.shardCollection("articledb.comment",{"nickname":"hashed"})
# 分片规则二:范围策略
# 使用作者年龄字段作为片键,按照年龄的值进行分片
# sh.shardCollection("articledb.author",{"age":1})
# 显示集群的详细信息
db.printShardingStatus()
# 查看均衡器是否工作(需要重新均衡时系统才会自动启动)
sh.isBalancerRunning()
# 查看当前Balancer状态
sh.getBalancerState()
注意:如果添加分片失败,需要先移除,再进行添加
# 使用管理员账户
use admin
# 移除添加失败的分片
db.runCommand( { removeShard: "myshardrs02" } )
注意:
a、一个集合只能指定一个片键,否则报错;
b、一旦对一个集合分片,分片键和分片值就不可改变;
④ 添加第二个路由节点
注意:第二个路由节点配置好配置文件,直接启动即可使用。无需再执行添加分片操作,其可以通过Config Server配置服务器得到对应的信息。
⑤ SpringDataMongDB连接分片集群
application.yml如下:
spring:
#数据源配置
data:
mongodb:
# 主机地址
# host: 180.76.159.126
# 数据库
# database: articledb
# 默认端口是27017
# port: 27017
#也可以使用uri连接
# uri: mongodb://192.168.40.134:28017/articledb
# 连接副本集字符串
# uri: mongodb://180.76.159.126:27017,180.76.159.126:27018,180.76.159.126:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
#连接路由字符串
uri: mongodb://180.76.159.126:27017,180.76.159.126:27117/articledb
三、安全认证
1. 保障MongoDB安全
a、使用新端口,默认端口为27017;
b、设置mongodb的网络环境,部署至内网;
c、开启安全认证;
2. MongoDB安全认证-单实例环境
① 启用访问控制
a、实例启动添加 --auth
;
bin/mongod -f single/mongod.conf --auth
b、在mongod.conf配置文件中加入如下内容:
security:
#开启授权认证
authorization: enabled
这样配置启动时可以不加 --auth
。
启用访问控制后登录方式:
# 【方式一】 先连接再认证
bin/mongo --host 180.76.159.126 --port 27017
# 使用有权限的库
use db_name
# 认证账户
db.auth("role_name","password")
# 【方式二】 连接时直接认证
bin/mongo --host 180.76.159.126 --port 27017 --authenticationDatabase db_name -u role_name -p password
② 配置角色权限
// 查询所有角色权限(仅用户自定义角色)
> db.runCommand({ rolesInfo: 1 })
// 查询所有角色权限(包含内置角色)
> db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })
// 查询当前数据库中的某角色的权限
> db.runCommand({ rolesInfo: "<rolename>" })
// 查询其它数据库中指定的角色权限
> db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } }
// 查询多个角色权限
> db.runCommand(
{
rolesInfo: [
"<rolename>",
{ role: "<rolename>", db: "<database>" },
...
]
}
)
Ⅰ 管理员角色相关操作
# 切换至admin库
use admin
# 【一】 创建角色
# 创建myRoot用户
# 系统的超级管理员 myRoot
db.createUser(
{
user: "myRoot",
pwd: "123456",
roles: [ { role: "root", db: "admin" } ]
}
)
# 创建myUserAdmin用户
# 专门用来管理admin库的账号 myUserAdmin ,只用来作为用户权限的管理
db.createUser(
{
user: "myUserAdmin",
pwd: "123456",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
# 【二】 查询角色
# 查看已经创建了的用户的情况:
db.system.users.find()
# 【三】 删除角色
db.dropUser("myUserAdmin")
# 【四】 修改角色密码
db.changeUserPassword("myRoot", "56789")
# 登录认证
use admin
db.auth("myRoot","123456")
db.auth("myRoot","56789")
Ⅱ 普通用户角色相关操作
# 切换至对应库
use db_name
# 创建普通角色
db.createUser(
{
user: "stone",
pwd: "123456",
roles: [ { role: "readWrite", db: "db_name" } ]
}
)
# 测试是否可用
db.auth("stone","123456")
角色 | 权限说明 |
---|---|
read | 可以读取指定数据库中任何数据。 |
readWrite | 可以读写指定数据库中任何数据,包括创建、重命名、删除集合。 |
readAnyDatabase | 可以读取所有数据库中任何数据(除了数据库config和local之外)。 |
readWriteAnyDatabase | 可以读写所有数据库中任何数据(除了数据库config和local之外)。 |
userAdminAnyDatabase | 可以在指定数据库创建和修改用户(除了数据库config和local之外)。 |
dbAdminAnyDatabase | 可以读取任何数据库以及对数据库进行清理、修改、压缩、 获取统计信息、执行检查等操作(除了数据库config和local之外)。 |
dbAdmin | 可以读取指定数据库以及对数据库进行清理、修改、压缩、 获取统计信息、执行检查等操作。 |
userAdmin | 可以在指定数据库创建和修改用户。 |
clusterAdmin | 可以对整个集群或数据库系统进行管理操作。 |
backup | 备份MongoDB数据最小的权限。 |
restore | 从备份文件中还原恢复MongoDB数据(除了system.profile集合)的权限。 |
root | 超级账号,超级权限。 |
③ SpringDataMongoDB连接认证
application.yml
spring:
#数据源配置
data:
mongodb:
# 主机地址
# host: 180.76.159.126
# 数据库
# database: articledb
# 默认端口是27017
# port: 27017
#帐号
# username: stone
#密码
# password: 123456
#单机有认证的情况下,也使用字符串连接
uri: mongodb://stone:123456@180.76.159.126:27017/articledb
3. MongoDB安全认证-副本集环境
① 对副本集执行访问控制需要的配置
a、副本集和共享集群的各个节点成员之间使用内部身份验证,可以使用密钥文件或x.509证书;
b、使用客户端连接到mongodb集群时,开启访问授权。
在keyfile身份验证中,副本集中的每个mongod实例都使用keyfile的内容作为共享密码,只有具有正确密钥文件的mongod或者mongos实例可以连接到副本集。
密钥文件的内容必须在6到1024个字符之间,并且在unix/linux系统中文件所有者必须有对文件至少有读的权限。
② 通过主节点添加一个管理员帐号
# 切换至admin库
use admin
# 【一】 创建角色
# 创建myRoot用户
# 系统的超级管理员 myRoot
db.createUser(
{
user: "myRoot",
pwd: "123456",
roles: [ { role: "root", db: "admin" } ]
}
)
③ 创建副本集认证的key文件
[root@bobohost ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@bobohost ~]# chmod 400 ./mongo.keyfile
[root@bobohost ~]# ll mongo.keyfile
注意:所有副本集节点都必须要用同一份keyfile,一般是在一台机器上生成,然后拷贝到其他机器上。且必须有读的权限,否则将来会报错。
④ 修改配置文件指定keyfile
副本集的各个配置文件都需要修改,添加如下内容:
# /mongodb/replica_sets/myrs_27017/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/replica_sets/myrs_27017/mongo.keyfile
#开启认证方式运行
authorization: enabled
⑤ 启动副本集在主节点上添加普通账号
#先用管理员账号登录
#切换到admin库
use admin
#管理员账号认证
db.auth("myRoot","123456")
#切换到要认证的库
use articledb
#添加普通用户
db.createUser(
{
user: "stone",
pwd: "123456",
roles: [ { role: "readWrite" } ]
}
)
⑥ SpringDataMongoDB连接副本集
application.yml如下配置:
spring:
#数据源配置
data:
mongodb:
#副本集有认证的情况下,字符串连接
uri: mongodb://bobo:123456@180.76.159.126:27017,180.76.159.126:27018,180.76.159.126:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
4. MongoDB安全认证-分片集群环境
① 创建副本集认证的key文件
[root@bobohost ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@bobohost ~]# chmod 400 ./mongo.keyfile
[root@bobohost ~]# ll mongo.keyfile
将该文件分别拷贝到多个目录中:
echo '/mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
/mongodb/sharded_cluster/myshardrs01_27118/mongo.keyfile
/mongodb/sharded_cluster/myshardrs01_27218/mongo.keyfile
/mongodb/sharded_cluster/myshardrs02_27318/mongo.keyfile
/mongodb/sharded_cluster/myshardrs02_27418/mongo.keyfile
/mongodb/sharded_cluster/myshardrs02_27518/mongo.keyfile
/mongodb/sharded_cluster/myconfigrs_27019/mongo.keyfile
/mongodb/sharded_cluster/myconfigrs_27119/mongo.keyfile
/mongodb/sharded_cluster/myconfigrs_27219/mongo.keyfile
/mongodb/sharded_cluster/mymongos_27017/mongo.keyfile
/mongodb/sharded_cluster/mymongos_27117/mongo.keyfile' | xargs -n 1 cp -v /root/mongo.keyfile
echo指令将前面的参数传递到后面指令,-n 1
每次传递一个参数值。
拼凑成:cp -v /root/mongo.keyfile /mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
。
② 修改配置文件指定keyfile
/mongodb/sharded_cluster/myshardrs01_27018/mongod.conf
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
#开启认证方式运行
authorization: enabled
此处注意mongos的配置稍有不同,如下:
security:
#KeyFile鉴权文件
keyFile: /mongodb/sharded_cluster/mymongos_27017/mongo.keyfile
③ 创建帐号和认证
# 通过localhost登录任意一个mongos路由
[root@bobohost db]# /usr/local/mongodb/bin/mongo --port 27017
# 使用admin库
use admin
# 创建一个管理员帐号
db.createUser(
{
user: "myRoot",
pwd: "123456",
roles: [ { role: "root", db: "admin" } ]
}
)
# 使用admin库
use admin
# 认证管理账户
db.auth("myRoot","123456")
# 使用要授权用户使用的库
use db_name
# 创建一个普通权限帐号
db.createUser(
{
user: "stone",
pwd: "123456",
roles: [ { role: "readWrite" } ]
}
)
# 认证普通用户
db.auth("stone","123456")
④ SpringDataMongoDB连接认证
'username:password@hostname/dbname' 格式,application.yml配置文件如下:
spring:
#数据源配置
data:
mongodb:
# 分片集群有认证的情况下,字符串连接
uri: mongodb://bobo:123456@180.76.159.126:27017,180.76.159.126:27117/articledb
四、结尾
以上即为MongoDB-基础使用(三)的全部内容,感谢阅读。
网友评论