【文章内容输出来源:拉勾教育Java高薪训练营】
--- 所有脑图均本人制作,未经允许请勿滥用 ---
MongoDB是一款高性能的NoSQL(Not Only SQL 不仅仅SQL)数据库
花开花落,云卷云舒
MongoDB是一款高性能额NoSQL(Not Only SQL)数据库
官网
中文文档
五、 MongoDB 架构
part - 1 MongoDB 逻辑结构
MongoDB 与 MySQL 中的架构相差不多,底层都使用了可插拔的存储引擎以满足用户的不同需要。
用户可以根据程序的数据特征选择不同的存储引擎,在最新版本的 MongoDB 中使用了 WiredTiger 作为默认的存储引擎,WiredTiger 提供了不同粒度的并发控制和压缩机制,能够为不同种类的应用提供了最好的性能和存储率。
在存储引擎 上层的就是 MongoDB 的数据模型和查询语言了,由于 MongoDB 对数据的存储与 RDBMS 有较大的差异,所以它创建了一套不同的数据模型和查询语言。
part - 2 MongoDB的数据模型
- 内嵌:把相关联的数据保存在同一个文档结构之中。MongoDB的文档结构允许一个字段或者一个数组内的值作为一个嵌套的文档
- 引用:通过存储数据引用信息来实现两个不同文档之间的关联,应用程序可以通过解析这些数据引用来访问相关数据
part - 3 MongoDB 存储引擎
- v3.2之前 => MMAPv1
- v3.2之后 => WiredTiger
- InMemory存储:引擎用于将数据只存储在内存中,只将少量的元数据 (meta-data)和诊断日志(Diagnostic)存储到硬盘文件中,由于不需要Disk的IO操作,就能获取所需 的数据,InMemory存储引擎大幅度降低了数据查询的延迟(Latency)
- mongodb4.x 版本不再支持MMAPv1存储引擎
【WiredTiger优势】:
- WiredTiger 使用的是BTree存储 | MMAPV1 线性存储 需要Padding
- WiredTiger 文档级别锁 | MMAPV1引擎使用表级锁
- snappy (默认) 和 zlib ,相比MMAPV1(无压缩) 空间节省数倍
- WiredTiger 可以指定内存的使用大小。
- 使用了二阶缓存 WiredTiger Cache、 File System Cache 来保证Disk上的数据的最终一 致性。而MMAPv1 只有 journal 日志。
【WiredTiger引擎包含的文件和作用】
【WiredTiger原理】
【checkpoint流程】
- 对所有的table进行一次checkpoint,每个table的checkpoint的元数据更新至WiredTiger.wt
- 对WiredTiger.wt进行checkpoint,将该table checkpoint的元数据更新至临时文件 WiredTiger.turtle.set
- 将WiredTiger.turtle.set 重命名为 WiredTiger.turtle
- 上述过程如果中间失败,WiredTiger 在下次连接初始化时,首先将数据恢复至最新的快照状态,然后根据 WAL 恢复数据,以保证存储可靠性
六、 MongoDB 高可用集群
part - 1 MongoDB 主从复制架构原理和缺陷
master-slave架构中master节点负责数据的读写,slave没有写入权限只负责读取数据。
在主从结构中,主节点的操作记录成为 oplog(operation log)。oplog 存储在系统数据库local的 oplog.$main 集合中,这个集合的每个文档都代表主节点上执行的一个操作。从服务器会定期从主服务器中获取oplog记录,然后在本机上执行!对于存储oplog的集合,MongoDB采用的是固定集合,也就是说随着操作过多,新的操作会覆盖旧的操作!
mongodb4.0后不再支持主从复制!(官方不推荐了)
part - 2 复制集 replica sets
「何为复制集」
复制集是由一组拥有相同数据集的mongod实例做组成的集群。
复制集是一个集群,它是2台及2台以上的服务器组成,以及复制集成员包括 Primary主节点, secondary从节点 和 投票节点。
复制集提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,保证数据的安全性。
「为何要使用复制集」
- 高可用
- 防止设备(服务器、网络)故障。
- 提供自动 failover 功能。
- 技术来保证高可用
- 灾难恢复
- 当发生故障时,可以从其他节点恢复 用于备份。
- 功能隔离
- 我们可以在备节点上执行读操作,减少主节点的压力
比如:用于分析、报表,数据挖掘,系统任务等。
「复制集集群架构原理」
一个复制集中 Primary节点上能够完成读写操作, Secondary节点仅能用于读操作。
Primary节点需要记录所有改变数据库状态的操作,这些记录保存在 oplog 中,这个文件存储在 local 数据库,各个Secondary节点通过此 oplog 来复制数据并应用于本地,保持本地的数据与主节点的一致。
oplog 具有幂等性,即无论执行几次其结果一致,这个比 mysql 的二进制日志更好用。
{
"ts": Timestamp(1446011584, 2),
"h": NumberLong("1687359108795812092"),
"v": 2,
"op": "i",
"ns": "test.nosql",
"o":
{
"_id": ObjectId("563062c0b085733f34ab4129"),
"name": "mongodb",
"score": "10"
}
}
/*
ts: 操作时间, 当前timestamp + 计数器, 计数器每秒都被重置
h: 操作的全局唯一标识
v: oplog版本信息
op: 操作类型
i: 插入操作
u: 更新操作
d: 删除操作
c: 执行命令( 如createDatabase, dropDatabase)
n: 空操作, 特殊用途
ns: 操作针对的集合
o: 操作内容
o2: 更新查询条件, 仅update操作包含该字段
*/
- 复制集数据同步
- 初始化同步:
全量从主节点同步数据,如果Primary节点数据量比较大同步时间会比较长- 触发时机1 ==> Secondary第一次加入
- 触发时机2 ==> Secondary落后的数据量超过了oplog的大小,这样也会被全量复制
- keep复制同步:
初始化同步过后,节点之间的实时同步一般是增量同步
- 初始化同步:
MongoDB的Primary节点选举基于心跳触发。
心跳检测:
整个集群需要保持一定的通信才能知道哪些节点活着哪些节点挂掉。mongodb节点会向副本集中的其他节点 每2秒就会发送一次pings包,如果其他节点在10秒钟之内没有返回就标示为不能访问。每个节点内部都会 维护一个状态映射表,表明当前每个节点是什么角色、日志时间戳等关键信息。如果主节点发现自己无法与大部分节点通讯 则把自己降级为secondary只读节点。
主节点选举触发的时机:
- 第一次初始化一个复制集
- Secondary节点权重比Primary节点高时,发起替换选举
- Secondary节点发现集群中没有Primary时,发起选举
- Primary节点不能访问到大部分(Majority)成员时主动降级
选举过程:(二阶段过程+多数派协议)
- 第一阶段
检测自身是否有被选举的资格 如果符合资格会向其它节点发起本节点是否有选举资格的 FreshnessCheck,进行同僚仲裁- 第二阶段
发起者向集群中存活节点发送Elect(选举)请求,仲裁者收到请求的节点会执行一系列合法性检查,如果检 查通过,则仲裁者(一个复制集中最多50个节点 其中只有7个具有投票权)给发起者投一票。
- 多数派协议
发起者如果获得超过半数的投票,则选举通过,自身成为Primary节点。获得低于半数选票的原因,除了常 见的网络问题外,相同优先级的节点同时通过第一阶段的同僚仲裁并进入第二阶段也是一个原因。
因此,当选票不足时,会sleep[0,1]秒内的随机时间,之后再次尝试选举。
「复制集搭建 ☆」
因为服务器资源有限,以下笔者通过在一台机器上根据不同的端口号区分的方式 搭建不同的Mongo实例,从而达到不同节点的效果:
- 主节点*1 :37017
- 从节点*3 :37018 + 37019 + 37020(后期定位为仲裁节点)
- 配置文件如下:(比以前多了
replSet属性)- 主节点37017 配置:
# 确保data/mongo/data/server1/ 存在 dbpath=/data/mongo/data/server1 port=37017 bind_ip=0.0.0.0 fork=true # 确保data/mongo/data/logs/ 存在 logpath = /data/mongo/logs/server1.log replSet=lagouCluster- 从节点37018 配置:
# 确保data/mongo/data/server2/ 存在 dbpath=/data/mongo/data/server2 port=37018 bind_ip=0.0.0.0 fork=true # 确保data/mongo/data/logs/ 存在 logpath = /data/mongo/logs/server2.log replSet=lagouCluster- 从节点37019 配置:
# 确保data/mongo/data/server3/ 存在 dbpath=/data/mongo/data/server3 port=37019 bind_ip=0.0.0.0 fork=true # 确保data/mongo/data/logs/ 存在 logpath = /data/mongo/logs/server3.log replSet=lagouCluster- 从节点37020 配置:
# 确保data/mongo/data/server4/ 存在 dbpath=/data/mongo/data/server4 port=37020 bind_ip=0.0.0.0 fork=true # 确保data/mongo/data/logs/ 存在 logpath = /data/mongo/logs/server4.log replSet=lagouCluster
使用shell进入任意一个节点 , 顺序运行如下命令:
var cfg = {
"_id":"lagouCluster",
"protocolVersion":1,
"members":[{
"_id":1,"host":"106.75.60.49:37017","priority":10
},{
"_id":2,"host":"106.75.60.49:37018"
},{
"_id":3,"host":"106.75.60.49:37019"
}]
// ... 37020 稍后使用动态加入
};
rs.initiate(cfg);
可以使用
rs.status();检查复制集信息
// 增加节点
rs.add("192.168.211.133:XXXXX")
// 删除slave 节点
rs.remove("192.168.211.133:XXXXX")
-------复制集操作演示-------
「复制集成员的配置参数」
- _id : 复制集中的标识 (整数)
- 举例:
_id:0
- 举例:
- host : 节点主机名 (字符串)
- 举例:
host:"主机:端口"
- 举例:
- arbiterOnly : 是否为仲裁(裁判)节点 (布尔值)
- 举例:
arbiterOnly:true
- 举例:
- priority(权重) : 默认1,是否有资格变成主节点. 取值范围 [0-1000]; 0 --> 永远不会变成主节点 (整数)
- 举例:
priority=0|1
- 举例:
- hidden : 是否隐藏;权重必须为0,才可以设置 (布尔值)
- 举例:
hidden=true|false,0|1
- 举例:
- votes : 是否为投票节点,0 --> 不投票,1 --> 投票 (整数)
- 举例:
votes= 0|1
- 举例:
- slaveDelay : 从库的延迟多少秒 (整数)
- 举例:
slaveDelay=3600
- 举例:
- buildIndexes : 主库的索引,从库也创建,_id索引无效 (布尔值)
- 举例:
buildIndexes=true|false,0|1
- 举例:
rs.reconfig(cfg)// 重新装载配置,并重新生成集群节点。
「有仲裁节点的复制集搭建」
将原本37020节点移除,并通过 rs.addArb("IP:端口"); 命令加入为仲裁节点
part - 3 分片集群 Shard Cluster
「何为分片」
分片(sharding)是MongoDB用来将大型集合水平分割到不同服务器(或者复制集)上所采用的方法。
不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。
「为何要分片」
- 存储容量需求超出单机磁盘容量。
- 活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能。
- IOPS超出单个MongoDB节点的服务能力,随着数据的增长,单机实例的瓶颈会越来越明显。
- 副本集具有节点数量限制。
垂直扩展:增加更多的CPU和存储资源来扩展容量。
水平扩展:将数据集分布在多个服务器上。水平扩展即分片。
「分片的工作原理」
- 分片集群由以下3个服务组成:
- Shards Server: 每个 shard 由一个或多个 mongod 进程组成,用于存储数据。
- Router Server: 数据库集群的请求入口,所有请求都通过 Router(mongos) 进行协调,不需要在应用程 序添加一个路由选择器,Router(mongos) 就是一个请求分发中心它负责把应用程序的请求转发到对应的 Shard 服务器上。
- Config Server: 配置服务器。存储所有数据库元信息(路由、分片)的配置。
- 片键:为了在数据集合中分配文档,MongoDB 使用分片主键分割集合
- 区块(chunk):在一个 shard server 内部,MongoDB 还是会把数据分为
chunks,每个 chunk 代表这个 shard server 内部一部分数据。MongoDB 分割分片数据到区块,每一个区块包含基于分片主键的左闭右开的区间范围。 - 分片策略:
- 范围分片(Range based sharding)
基于分片主键的值切分数据,每一个区块将会分配到一个范围
范围分片适合满足在一定范围内的查找,例如查找X的值在[20,30)之间的数据,mongo 路由根据Config server中存储的元数据,可以直接定位到指定的shard的Chunk中。 - hash分片(Hash based sharding)
Hash分片是计算一个分片主键的hash值,每一个区块将分配一个范围的hash值。
Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,缺点是不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档。
- 范围分片(Range based sharding)
合理的选择shard key:
无非从两个方面考虑,数据的查询和写入, 最好的效果就是:
数据查询时能命中更少的分片,数据写入时能够随机的写入每个分片,关键在于如何权衡性能和负载
「分片集群的搭建过程 ☆」
接下来,我们按照下述情形进行分片集群搭建:
- 路由节点
27017 - 分片节点1 - 复制集群
37017~37019 - 分片节点2 - 复制集群
47017~47019 - 配置节点 - 复制集群
17017~17019
1. 配置 并启动config 节点集群
节点1 config-17017.conf
# 数据库文件位置
dbpath=data/mongo/data/config1
# 日志文件位置
logpath=data/mongo/data/logs/config1.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=17017
# 绑定主机
bind_ip=0.0.0.0
# 是否是配置服务器
configsvr=true
# 配置服务器复制集名称
replSet=configsvr
节点2 config-17018.conf
# 数据库文件位置
dbpath=data/mongo/data/config2
# 日志文件位置
logpath=data/mongo/data/logs/config2.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=17018
# 绑定主机
bind_ip=0.0.0.0
# 是否是配置服务器
configsvr=true
# 配置服务器复制集名称
replSet=configsvr
节点3 config-17019.conf
# 数据库文件位置
dbpath=data/mongo/data/config3
# 日志文件位置
logpath=data/mongo/data/logs/config3.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=17019
# 绑定主机
bind_ip=0.0.0.0
# 是否是配置服务器
configsvr=true
# 配置服务器复制集名称
replSet=configsvr
启动配置节点
./bin/mongod -f config-17017.conf
./bin/mongod -f config-17018.conf
./bin/mongod -f config-17019.conf
进入任意节点的 mongo shell 并添加配置节点集群 !注意 use admin
./bin/mongo --port=17017
> use admin
> var cfg ={
"_id":"configsvr",
"members":[ {
"_id":1,"host":"106.75.60.49:17017"
}, {
"_id":2,"host":"106.75.60.49:17018"
}, {
"_id":3,"host":"106.75.60.49:17019"
}]
};
> rs.initiate(cfg)
2. 配置 shard 集群1
节点1 shard1-37017.conf
# 数据库文件位置
dbpath=data/mongo/data/shard1/shard1-37017
# 日志文件位置
logpath=data/mongo/data/shard1/shard1-37017.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=37017
# 绑定主机
bind_ip=0.0.0.0
# 是否是分片服务器
shardsvr=true
# 分片服务器复制集名称
replSet=shard1
节点2 shard1-37018.conf
# 数据库文件位置
dbpath=data/mongo/data/shard1/shard1-37018
# 日志文件位置
logpath=data/mongo/data/shard1/shard1-37018.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=37018
# 绑定主机
bind_ip=0.0.0.0
# 是否是分片服务器
shardsvr=true
# 分片服务器复制集名称
replSet=shard1
节点1 shard1-37017.conf
# 数据库文件位置
dbpath=data/mongo/data/shard1/shard1-37019
# 日志文件位置
logpath=data/mongo/data/shard1/shard1-37019.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=37019
# 绑定主机
bind_ip=0.0.0.0
# 是否是分片服务器
shardsvr=true
# 分片服务器复制集名称
replSet=shard1
启动配置节点
./bin/mongod -f shard1-37017.conf
./bin/mongod -f config-37018.conf
./bin/mongod -f config-37019.conf
进入任意节点的 mongo shell 并添加分片节点集群
./bin/mongo --port=37017
> var cfg ={
"_id":"shard1",
"protocolVersion":1,
"members":[ {
"_id":1,"host":"106.75.60.49:37017"
}, {
"_id":2,"host":"106.75.60.49:37018"
}, {
"_id":3,"host":"106.75.60.49:37019"
}]
};
> rs.initiate(cfg)
3. 配置 shard 集群2
节点1 shard1-47017.conf
# 数据库文件位置
dbpath=data/mongo/data/shard2/shard2-47017
# 日志文件位置
logpath=data/mongo/data/shard2/shard2-47017.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=47017
# 绑定主机
bind_ip=0.0.0.0
# 是否是分片服务器
shardsvr=true
# 分片服务器复制集名称
replSet=shard2
节点2 shard1-47018.conf
# 数据库文件位置
dbpath=data/mongo/data/shard2/shard2-47018
# 日志文件位置
logpath=data/mongo/data/shard2/shard2-47018.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=47018
# 绑定主机
bind_ip=0.0.0.0
# 是否是分片服务器
shardsvr=true
# 分片服务器复制集名称
replSet=shard2
节点1 shard1-47017.conf
# 数据库文件位置
dbpath=data/mongo/data/shard2/shard2-47019
# 日志文件位置
logpath=data/mongo/data/shard2/shard2-47019.log
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=47019
# 绑定主机
bind_ip=0.0.0.0
# 是否是分片服务器
shardsvr=true
# 分片服务器复制集名称
replSet=shard2
启动配置节点
./bin/mongod -f shard1-47017.conf
./bin/mongod -f config-47018.conf
./bin/mongod -f config-47019.conf
进入任意节点的 mongo shell 并添加分片节点集群
./bin/mongo --port=47017
> var cfg ={
"_id":"shard2",
"protocolVersion":1,
"members":[ {
"_id":1,"host":"106.75.60.49:47017"
}, {
"_id":2,"host":"106.75.60.49:47018"
}, {
"_id":3,"host":"106.75.60.49:47019"
}]
};
> rs.initiate(cfg)
4. 配置和启动 路由节点
- route-27017.conf
# 日志文件位置
logpath=/data/mongo/data/route/logs/route.log
# 配置节点标记
configdb=configsvr/106.75.60.49:17017,106.75.60.49:17018,106.75.60.49:17019
# 以追加方式写入日志
logappend=true
# 是否以守护线程方式运行
fork=true
# 端口号
port=27017
# 绑定主机
bind_ip=0.0.0.0
- 使用
mongos启动路由节点 ! 不是之前的mongod
./bin/monogs -f route-27017.conf
5. mongos(路由)中添加分片节点
./bin/mongo --port=27017
sh.status(); // 检查状态
sh.addShard("shard1/106.75.60.49:37017,106.75.60.49:37018,106.75.60.49:37019");
sh.addShard("shard2/106.75.60.49:47017,106.75.60.49:47018,106.75.60.49:47019");
6. 开启数据库和集合分片(指定片键)
// 为数据库开启分片功能
sh.enableSharding("users") /* 此处的users数据库不存在也行,会识别后创建 */
// 为指定集合开启分片功能
sh.shardCollection("users.user_info",{"name":"hashed"}) /* 使用哈希分片 */
7. 向集合中插入数据测试
use users;
for (var i = 0; i <= 1000; i ++) {
db.user_info.insert({
"name":"User" + i,
"salary": (Math.random()*20000).toFixed(2)
});
}
8. 验证分片效果
分别进入 shard1 和 shard2 中的数据库 进行验证
七、 MongoDB 安全认证
part - 1 安全认证概述
MongoDB 默认是没有账号的,可以直接连接,无须身份验证。
实际项目中肯定是要权限验证的,否则后果不堪设想。从2016年开始 发生了多起 MongoDB 黑客赎金事件,大部分MongoDB安全问题 暴露出 了安全问题的短板其实是用户,首先用户对于数据库的安全不重视,其次用户在使用过程中可能没有养成定期备份的好习惯,最后是企业可能缺乏有经验和技术的专业人员。
所以对 MongoDB 进行安全认证是必须要做的。
part - 2 用户相关操作
「切换到 admin 库对用户的添加」
use admin;
// 语法:db.createUser(userDocument); // 用于创建 MongoDB 登录用户以及分配权限的方法
db.createUser({
user:"账号",
pwd:"密码",
roles:[{
{role:"需要绑定的角色1", db:"被安全认证的数据库A"},
{role:"需要绑定的角色2", db:"被安全认证的数据库B"},
......
}]
});
- user:创建的用户名称,如 admin、root 、lagou
- pwd:用户登录的密码
- roles:为用户分配的角色,不同的角色拥有不同的权限,参数是数组,可以同时设置多个
- role:角色,MonngoDB 已经约定好的角色,不同的角色对应不同的权限 后面会对role做详细解释
- db:数据库实例名称,如 MongoDB 4.0.2 默认自带的有 admin、local、config、test 等,即为哪个数据库实例 设置用户
修改密码
db.changeUserPassword( 'root' , 'rootNew' );
用户添加角色
db.grantRolesToUser( '用户名' , [{ role: '角色名' , db: '数据库名'}])
以 auth 方向启动 mongod
./bin/mongod -f conf/mongo.conf --auth
// 也可以在mongo.conf 中添加auth=true 参数
验证用户
db.auth("账号","密码")
删除用户
db.dropUser("用户名")
part - 3 角色
「数据库内置的角色」
- read:允许用户读取指定数据库
- readWrite:允许用户读写指定数据库
- dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问 system.profile
- userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
- clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
- readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
- readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
- userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
- dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
- root:只在admin数据库中可用。超级账号,超级权限
- dbOwner:库拥有者权限,即readWrite、dbAdmin、userAdmin角色的合体
「各个类型用户对应的角色」
- 数据库用户角色:read、readWrite
- 数据库管理角色:dbAdmin、dbOwner、userAdmin
- 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
- 备份恢复角色:backup、restore;
- 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、 dbAdminAnyDatabase
- 超级用户角色:root
这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、 userAdminAnyDatabase)
part - 4 单机安全认证实现流程
「创建管理员」
use admin
db.createUser({
"user":"root",
"pwd":"123456",
"roles":[{"role":"root","db":"admin"}]
});
「创建普通用户」
use mydb
// 读写权限的用户——张三
db.createUser({
"user":"zhangsan",
"pwd":"123456",
"roles":[{"role":"readWrite","db":"mydb1"}]
});
// 只读权限的用户——李四
db.createUser({
"user":"lisi",
"pwd":"123456",
"roles":[{"role":"read","db":"mydb1"}]
});
「MongoDB 安全认证方式」
mongod --dbpath=数据库路径 --port=端口 --auth- 在配置文件中 加入 auth=true
「普通用户登录验证权限」
use target_DB 后使用 db.auth("账号","密码") 方法进行安全认证,认证通过,才能进行权限范围内的操作
use mydb1;
db.auth("zhangsan","123456");
show dbs; // √
show tables; // √
... // 可以对 mydb1 进行权限内操作
「管理员用户登录验证权限」
use admin
db.auth("root","123456");
show dbs; // √
show tables; // √
... // 可以对 admin 进行权限内操作
part - 5 分片集群安全认证
- 开启安全认证前,进入路由创建管理员和普通用户
use admin
db.createUser({
"user":"root",
"pwd":"123456",
"roles":[{"role":"root","db":"admin"}]
});
use users
// 读写权限的用户——大梁
db.createUser({
"user":"daliang",
"pwd":"123456",
"roles":[{"role":"readWrite","db":"users"}]
});
- 关闭所有的 配置节点/分片节点/路由节点
因为进程过多,可以使用 psmisc 组件批量关闭线程
yum install psmisc // 安装 psmisc
killall -2 mongod // 使用killall 命令 快速关闭多个进程
- 生成密钥文件 并修改权限
# 确保存在 相对路径 data/mongodb/ 目录
openssl rand -base64 756 > data/mongodb/testKeyFile.file
chmod 600 data/mongodb/keyfile/testKeyFile.file
- 配置节点集群和分片节点集群,开启安全认证和指定密钥文件
auth=true
keyFile=data/mongodb/testKeyFile.file
在 分片集群1(37017~37019)、分片集群2(47017~47019)、配置集群(27017~27019) 中都要加上这部分配置
- 在路由配置文件中 设置密钥文件
keyFile=data/mongodb/testKeyFile.file
- 启动所有的配置节点 分片节点 和 路由节点 使用路由进行权限验证
./bin/mongod -f config/config-17017.conf
./bin/mongod -f config/config-17018.conf
./bin/mongod -f config/config-17019.conf
./bin/mongod -f shard/shard1/shard1-37017.conf
./bin/mongod -f shard/shard1/shard1-37018.conf
./bin/mongod -f shard/shard1/shard1-37019.conf
./bin/mongod -f shard/shard2/shard2-47017.conf
./bin/mongod -f shard/shard2/shard2-47018.conf
./bin/mongod -f shard/shard2/shard2-47019.conf
./bin/mongos -f route/route-27017.conf
建议编写一个shell脚本 批量启动
- Spring boot 连接安全认证的分片集群
spring.data.mongodb.username=账号
spring.data.mongodb.password=密码
# spring.data.mongodb.uri=mongodb://账号:密码@IP:端口/数据库名