内容一览
- MongoDB的副本集:操作、主要概念、故障转移、选举规则
- MongoDB的分片集群:概念、优点、操作、分片策略、故障转移
- MongoDB的安全认证
一.副本集—Replica Sets
1.1 简介
MongoDB中的副本集是一组维护相同数据集的mongod服务。副本集可提供冗余和高可用性,是所有生产部署的基础。
即副本集类似于有自动故障恢复功能的主从集群。并且当主库当掉时在不需要用户干预的情况下自动切换其他备份服务器做主库。还可以利用副本服务器做只读服务器,实现读写分离,提高负载。
副本集包含多个数据承载结点和可选的一个仲裁结点,在承载数据的结点中,一个且仅一个成员被视为主结点,而其他结点被视为次要结点。
MongoDB有主从复制和副本集两种主从复制模式,主从复制最大的问题就是无法自动故障转移,MongoDB副本集解决了主从模式无法自动故障转义的特点,因此是复制的首选。
对于简单的主从复制无法自动故障转移的缺陷,各个数据库都在改进,MySQL推出的MGR,Redis的哨兵,Mongodb的复制集。
1.2 副本集中的角色
副本集中有两种类型三种角色
两种类型:
- 主结点类型:数据操作的主要结点,可读写。
- 次要(从)结点类型:数据冗余备份结点,可以读和选举。
三种角色:
- 主要成员:主要接收所有写操作,就是主结点。
- 副本成员:从结点通过复制操作以维护相同数据集,即备份诗句,不可写操作,但可读操作(需要配置)。是默认的从节点类型。
- 仲裁者:不保留任何数据的副本,只具有投票选举的作用。当然也可以使副本成员同时也可以是仲裁者,也是从结点类型。
1.3 副本集配置
(1)配置文件中增加配置
replication:
replSetName: 副本集名称
(2)初始化副本集
没初始化之前,很多命令无法使用,比如show dbs等,必须初始化副本集才行。
rs.initiate(configuration)
输入命令后,提示ok,说明创建成功。然后命令行提示符发生变化,变成了一个从结点角色,此时默认不能读写。稍等片刻,回车,变成主节点。
rs.conf() 查看副本集配置
rs.status() 查看副本集的状态
(3)添加副本从结点
rs.add(host,arbiterOnly)
host, 类型为string or document,要添加到副本集的新成员,指定为字符串或配置文档。如果是字符串,则需要指定新成员的主机名和可选端口号。如果是一个文档,请指定在members数组中找到的副本集成员配置文档。
arbiterOnly,类型为boolean,可选。仅在host值为字符串时适用。如果为true,则添加的主机时仲裁者。
当前从节点只是作为备份,无法读取数据。需要登录到从节点中,
rs.slaveOk() 或rs.slaveOk(true)
(4)添加仲裁结点
rs.addArb(host,arbiterOnly)
(5)修改副本集ip
var config = rs.config();
config.members[0].host = "ip:port";
rs.reconfig(config)
1.4 主节点的选举原则
MongoDB主节点选举的触发条件:
- 主节点故障
- 主节点网络不可达(默认心跳信息为10s)
- 人工干预(rs.stepDpwn(600))
一旦触发选举,就要根据一定规则来选主节点,选举规则是根据票数来决定谁获胜:
- 票数最高,且获得了大多数成员的投票支持的结点获胜。
大多数的定义为:假设副本集内投票的成员数量为n,则大多数为n/2+1.例如:3个投票成员,则大多数的值是2,当副本集内存活成员数量不足大多数时,整个副本集将无法选举出primary,复制集将无法提供写服务,处于只读状态。
- 若票数相同,且都获得大多数成员的投票支持,数据新的结点获胜。数据的新旧是通过操作日志oplog来对比的。
- 在获得票数的时候,优先级参数影响重大。
1.5 服务降级
当存活结点小于n/2+1时,副本集中的主结点降级为从结点,整个副本集只提供读服务。
1.6 java连接副本集
之前spring的配置文件中使用host,port,database连接的mongodb。现在使用uri连接副本集。
spring:
data:
mongodb:
uri:mongodb://ip1:port1,ip2:port2,ip3:port3/数据库名?connect=replicaSet&slaveOk=true&replicaSet=myrs
connect=replicaSet:自动到副本集中选择读写的主机。
二.分片集群—Sharded Cluster
2.1 简介
分片是一种跨多台机器分布数据的方法,MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署
2.2 分片集群包含的组件
- 分片(存储):每个分片包含分片数据的子集,每个分片都可以部署为副本集。
- mongos(路由):mongos充当查询路由器,在客户端应用程序和分片集群之间提供接口
- config servers(调度的配置):配置服务器存储集群的元数据和配置设置,从MongoDB3.4开始,必须将配置服务器配置为副本集(csrs)
2.3 分片集群架构目标
两个分片节点副本集(3+3) + 一个配置节点副本集(3)+两个路由节点(2),共11个服务节点。
2.4 分片集群的配置
(1)分片节点和配置节点的配置文件
增加如下配置
sharding:
clusterRole: shardsvr
sharding.clusterRole只有两个选项,configsvr(配置服务)或者 shardsvr(分片)
(2)路由节点配置
创建一个log目录,不需要data目录。
创建配置文件:
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/Users/didi/xzy/sharded_cluster/mymongos_27017/log/mongod.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
logAppend: true
storage:
#mongod实例存储其数据的目录,storage.dbPath设置仅适用于mongod。
dbPath: "/Users/didi/xzy/sharded_cluster/mymongos_27017/data/db"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/Users/didi/xzy/sharded_cluster/mymongos_27017/log/mongod.pid"
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll:true
#服务实例绑定的IP
bindIp: localhost
#bindIp
#绑定的端口
port: 27017
sharding:
#指定配置节点副本集
configDB: 副本集名称/localhost:27019,localhost:27119,localhost:27219
启动时用mongos启动。此时路由还不能找到分片,所要要添加分片到路由中。
(3)添加分片节点
连接到路由节点。通过如下命令添加分片节点:
sh.addShard("IP:Port") // 非副本集
sh.addShard(”副本集名称/副本集中各ip:port“) // 副本集
(4)开启分片功能
sh.enableSharding("库名")、sh.shardCollection("库名.集合名",{"key":1})
对集合分片,必须使用sh.shardCollection()方法指定集合和分片键
sh.shardCollection(namespace,key,unique)
Parameter | Type | Description |
---|---|---|
namespace | string | 要(分片)共享对目标集合对命名空间 |
key | document | 用作分片键对所以规则文档。shard键决定MongoDB如何在shard之间分法文档。除非集合为空,否则索引必须在shard collection命令之前存在。如果集合为空,则MongoDB在对集合进行分片之前创建索引,前提是支持分片键的索引不存在。简单来说:由包含字段和该字段的索引遍历方向的文档组成。 |
unique | boolean | 当值为true,片键字段上会限制为确保是唯一索引,哈希策略片键不支持唯一索引,默认为false |
例如在articled库中的comment集合中,以nickname为键,以哈希策略来分片:
sh.enableSharding("articledb")
sh.shardCollection("articledb.comment",{"nickname":"hashed"})
(5)再增加一个路由节点
第二个路由无需配置,应为分片配置都保存到了配置服务器中了。
(6)springdata连接路由节点
spring:
data:
mongodb:
uri:mongodb://ip1:port1,ip2:port2,ip3:port3/数据库名
默认有负载均衡策略访问多个路由节点
三.安全认证
3.1介绍
默认情况下,MongoDB实例启动运行时没有启用用户访问权限控制,也就是说,可以随意连接进行操作,mongodb不会对连接的客户端进行严重。
mongodb官网上说,为了能保障mongodb的安全可以做一下几个步骤:
- 使用新的端口号,不使用默认的27017。
- 设置mongodb网络环境,只能内网访问。
- 开启安全认证。认证要同时设置服务器之间的内部认证方式,同时要设置客户端连接到集群的账号密码认证方式。
开启用户访问控制(用户验证),需要再MongoDB实例启动时使用选项–auth或在指定启动配置文件中添加选项auth=true。
3.2 常用内置角色
read 可以读取指定数据库中任何数据。
readWrite 可以读写指定数据库中任何数据,包括创建、重命名、删除集合
readAnyDatabase 可以读取所有数据库中任何数据(除了数据库config和local之外)
readWriteAnyDatabase 可以读写所有数据库中任何数据(除了数据库config和local之外)
userAdminAnyDatabase 可以在指定数据库创建和修改用户(除了数据库config和local之外)
dbAdminAnyDatabase 可以读取任何数据库以及数据库进行清理、修改、压缩、获取统计信息、执行检查等操作(除了数据库config和local之外)。
dbAdmin 可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。
userAdmin 可以指定数据库创建和修改用户
clusterAdmin 可以对整个集群或数据库系统进行管理操作
backup 备份MongoDB数据最小的权限
restore 从备份文件中还原恢复MongoDB数据(处理system.profile集合)的权限
root 超级账号,超级权限
3.3 相关命令
db.system.users.find() //查看已经创建了的用户的情况
db.createUser({user:"用户名",pwd:"密码",roles:["角色"]}) //新增用户,默认当前数据库权限
db.createUser({user:"用户名",pwd:"密码",roles:[{“role”:"角色","db":"数据库名"}]}) //新增用户,如果db:“”则对所有数据库有效
db.dropUser("用户名")
db.changeUserPassword("用户名",“密码”)
db.auth("用户名","密码") // 认证某一账号是否正确,登录某一账户