- Published on
MongoDB 集群架构详解:副本集、分片与高可用策略
- Authors
- Name
- Liant
介绍MongoDB的集群相关知识
MongoDB运行的三种模式
standard (标准模式/单机模式)
replica (副本模式/副本集)
shard (分片模式)
架构
副本集 Replica set
一组Mongodb复制集,就是一组mongod进程,这些进程维护同一个数据集合。复制集提供了数据冗余和高等级的可靠性,这是生产部署的基础。
节点中的角色
Primary 主节点
读写
Secondary 从节点
正常情况下,复制集的Seconary会参与Primary选举(自身也可能会被选为Primary),并从Primary同步最新写入的数据,以保证与Primary存储相同的数据。
Secondary可以提供读服务,增加Secondary节点可以提供复制集的读服务能力,同时提升复制集的可用性。另外,Mongodb支持对复制集的Secondary节点进行灵活的配置,以适应多种场景的需求。
Arbiter 仲裁节点
Arbiter节点只参与投票,不能被选为Primary,并且不从Primary同步数据。
比如你部署了一个2个节点的复制集,1个Primary,1个Secondary,任意节点宕机,复制集将不能提供服务了(无法选出Primary),这时可以给复制集添加一个Arbiter节点,即使有节点宕机,仍能选出Primary。
Arbiter本身不存储数据,是非常轻量级的服务,当复制集成员为偶数时,最好加入一个Arbiter节点,以提升复制集可用性。
下面配置配合使用,组成不同策略
Priority=0 不能选为primary
Priority0节点的选举优先级为0,不会被选举为Primary
比如你跨机房A、B部署了一个复制集,并且想指定Primary必须在A机房,这时可以将B机房的复制集成员Priority设置为0,这样Primary就一定会是A机房的成员。
(注意:如果这样部署,最好将『大多数』节点部署在A机房,否则网络分区时可能无法选出Primary)
Vote=0 不可投票
Mongodb 3.0里,复制集成员最多50个,参与Primary选举投票的成员最多7个,其他成员(Vote0)的vote属性必须设置为0,即不参与投票。
Hidden 隐藏节点
Hidden节点不能被选为主(Priority为0),并且对Driver不可见。因Hidden节点不会接受Driver的请求,可使用Hidden节点做一些数据备份、离线计算的任务,不会影响复制集的服务。
Delayed 延迟节点
Delayed节点必须是Hidden节点,并且其数据落后与Primary一段时间(可配置,比如1个小时)。
因Delayed节点的数据比Primary落后一段时间,当错误或者无效的数据写入Primary时,可通过Delayed节点的数据来恢复到之前的时间点。
关于oplog
oplog(操作日志)保存了数据的操作记录,oplog主要用于副本,secondary复制oplog并把里面的操作在secondary执行一遍。但是oplog也是保存在local.oplog.rs
里。
实操
添加副本集/仲裁节点
// 查看当前状态
rs.status()
// self:只会出现在执行rs.status()命令的成员里
// uptime:从本节点 网络可达到当前所经历的时间
// lastHeartbeat:当前服务器最后一次收到其心中的时间
// Optime & optimeDate:命令发出时oplog所记录的操作时间戳
// pingMs: 网络延迟
// syncingTo: 复制源
// stateStr:
// 可提供服务的状态:primary, secondary, arbiter
// 即将提供服务的状态:startup, startup2, recovering
// 不可提供服务状态:down, unknow, removed, rollback, fatal
// 查看当前配置信息
rs.config()
// 移除一个节点
rs.remove("192.168.10.220:27000")
// 重新设置节点/或者新增多个节点
config = {_id:"repmore",members:[{_id:0,host:'192.168.10.220:27017', priority :2}]};
rs.reconfig(config);
// 添加一个节点/实际也是修改配置文件
rs.add("192.168.10.220:27000")
// 启用Arbiter节点/仲裁节点
rs.add({host:"192.168.10.220:27000",arbiterOnly:true})
// 或者
rs.addArb("192.168.10.220:27000")
工具
mongostat
mongostat -h 192.168.10.220:27017 --discover
mongostop
分片集群架构 (Sharded Cluster)
高数据量和吞吐量的数据库应用会对单机的性能造成较大压力.分片则将单机的压力转移到多台机器上.
组件 | 说明 |
---|---|
Config Server | 存储集群所有节点、分片数据路由信息。默认需要配置3个Config Server节点。 |
Mongos | 提供对外应用访问,所有操作均通过mongos执行。一般有多个mongos节点。数据迁移和数据自动平衡。 |
Mongod | 存储应用数据记录。一般有多个Mongod节点,达到数据分片目的。 |
(1)mongos :数据路由,和客户端打交道的模块。mongos本身没有任何数据,他也不知道该怎么处理这数据,去找config server
(2)config server:所有存、取数据的方式,所有shard节点的信息,分片功能的一些配置信息。可以理解为真实数据的元数据。
(3)shard:真正的数据存储位置,以chunk为单位存数据。
Chunk
数据存储,在shard server内部,保存具体数据的是 Chunk
(1)使用chunk来存储数据
(2)集群搭建完成之后,默认开启一个chunk,大小是64M,
(3)存储需求超过64M,chunk会进行分裂,如果单位时间存储需求很大,设置更大的chunk
(4)chunk会被自动均衡迁移。
数据分布(分片键 shard key)
对于数据在集群中具体存储位置指标为分片键(shard key)
.MongoDB根据分片键(shard key)
将数据存储到指定分片中. 常见的为三种:
递增的sharding key
数据文件挪动小。(优势)
因为数据文件递增,所以会把insert的写IO永久放在最后一片上,造成最后一片的写热点。同时,随着最后一片的数据量增大,将不断的发生迁移至之前的片上。
随机的sharding key
数据分布均匀,insert的写IO均匀分布在多个片上。(优势)
大量的随机IO,磁盘不堪重荷。
混合型key
大方向随机递增,小范围随机分布。
为了防止出现大量的chunk均衡迁移,可能造成的IO压力。我们需要设置合理分片使用策略(片键的选择、分片算法(range、hash)
操作
- 指定集群中的片键
- balance操作,可以指定chunk的迁移策略等
其他
Priority 优先级
Priority=0
被动成员
- 此节点丧失了当选Primary的机会。永远不会上位。
- 此节点正常参与Primary产生的oplog的读取,进行数据备份和命令执行。
- 此节点正常参与客户端对于数据的读取,进行担当负载均衡的工作。
- 此节点虽然不能当选Primary但是却可以投票。
只有 Primary 节点接收 Writes 操作 取值范围为 0 ~ 100
Priority=0
类似于Standby(被动成员),可投票不可参选,又干活又负载。
Vote 投票节点
- 投票节点不保存数据副本,不可能成为主节点。
- Mongodb 3.0里,复制集成员最多50个,参与Primary选举投票的成员最多7个。
- 对于超出7个的其他成员(Vote0)的vote属性必须设置为0,即不参与投票。
Hidden 节点
- 此节点丧失了当选Primary的机会。永远不会上位。
- 此节点正常参与Primary产生的oplog的读取,进行数据备份和命令执行。
- 此节点正常参与客户端对于数据的读取,进行担当负载均衡的工作。
- 此节点不参与客户端对于数据的读取,不进行负载均衡。
- 此节点虽然不能当选Primary但是却可以投票。
Priority=0
为必须的前置条件
如果设置了Secondary数据可读取,Hidden节点数据对客户端不可读取,对于集群可见
mongos不会同隐藏节点交互
一般应用于备份场景
Delayed 节点
- 此节点必须是一个
Priority=0
且为Hidden的节点,因为Hidden必须是Priority=0
的,所以此节点必须是Hidden的。 - 此节点虽然又迟延又Hidden但是还是可以投票。
不可及状态:Delay时间范围超过oplog的范围
cfg = rs.conf()
cfg.members[2].priority = 0
cfg.members[2].hidden = true
cfg.members[2].slaveDelay = 3600
rs.reconfig(cfg)
仲裁者
仲裁者唯一的作用就是参与选举,仲裁者并不保存数据,也不会为客户端提供服务。
成员一旦以仲裁者的身份加入副本集中,它就永远只能是仲裁者。
无法将仲裁者重新配置为非仲裁者,反之亦然。最多只能有一个仲裁者每个副本集中。
ReadPreferred 读偏好设置
读取偏好是指选择从哪个复制集成员读取数据的方式。可以为驱动指定5中模式来设置读取偏好。
readPreference=primary
readPreference=primaryPreferred
readPreference=secondary
readPreference=secondaryPreferred
readPreference=nearest
setReadPreferred()命令设置读取偏好。
primary
:只从主服务器上读取数据。如果用户显式指定使用标签读取偏好,该读取偏好将被阻塞。这也是默认的读取偏好。primaryPreferred
:读取将被重定向至主服务器;如果没有可用的主服务器,那么读取将被重定向至某个辅助服务器;secondary
:读取将被重定向至辅助服务器节点。如果没有辅助服务器节点,该选项将会产生异常;secondaryPreferred
:读取将被重定向至辅助服务器;如果没有辅助服务器,那么读取将被重定向至主服务器。该选项对应旧的slaveOK
方法;nearest
:从最近的节点读取数据,不论它是主服务器还是辅助服务器。该选项通过网络延迟决定使用哪个节点服务器。
primary
设置slaveok=ok
时,secondary
可读取.
Write-Concern 写顾虑设置
写顾虑类似读取偏好,通过写顾虑选项可以指定在写操作被确认完成前,数据必须被安全提交到多少个节点。
写顾虑的模式决定了写操作时如何持久化数据。参数w
会强制getLastError
等待,一直到给定数据的成员都执行完了最后的写入操作。w
的值是包含主节点的。
写顾虑的5中模式:
w=0
或不确定:单向写操作。写操作执行后,不需要确认提交状态。w=1
或确认:写操作必须等到主服务器的确认。这是默认行为。w=n
或复制集确认:主服务器必须确认该写操作。并且n-1个成员必须从主服务器复制该写入操作。该选项更强大,但是会引起延迟。w=majority
:写操作必须被主服务器确认,同时也需要集合中的大多数成员都确认该操作。而w=n可能会因为系统中断或复制延迟引起问题。j=true
日志:可以与w=写顾虑一起共同指定写入操作必须被写入到日志中,只有这样才算是确认完成。
另外:
wtimeout
:避免getLastError一直等待下去,该值是命令的超时时间值,如果超过这个时间还没有返回,就会返回失败。该值的单位是毫秒。如果返回失败,值在规定的时间内没有将写入操作复制到"w"个成员。 该操作只对该连接起作用,其他连接不受该连接的"w"值限制。
db.products.insert(
{ item : "envelopes" , qty : 100 , type : "Clasp" },
{ writeConcern : { w : 2 , wtimeout : 5000 } }
)
// wtimeout 代表5秒超时
// 修改默认写顾虑
cfg = rs.conf()
cfg.settings = {}
cfg.settings.getLastErrorDefaults = { w: "majority" , wtimeout: 5000 }
rs.reconfig(cfg)
// 或者
db.runCommand({"getLastError":1,"w":"majority","wtimeout":10000})
tags (读取偏好和写顾虑中使用标签)
选举机制
- 自身是否能够与主节点连通;
- 希望被选件为主节点的备份节点的数据是否最新;
- 有没有其他更高优先级的成员可以被选举为主节点;
- 如果被选举为主节点的成员能够得到副本集中“大多数”成员的投票,则它会成为主节点,如果“大多数”成员中只有一个否决了本次选举,则本次选举 失败即就会取消。一张否决票相当于10000张赞成票。
- 希望成为主节点的成员必须使用复制将自己的数据更新为最新;