Published on

MongoDB 集群架构详解:副本集、分片与高可用策略

Authors
  • avatar
    Name
    Liant
    Twitter

介绍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 被动成员

  1. 此节点丧失了当选Primary的机会。永远不会上位。
  2. 此节点正常参与Primary产生的oplog的读取,进行数据备份和命令执行。
  3. 此节点正常参与客户端对于数据的读取,进行担当负载均衡的工作。
  4. 此节点虽然不能当选Primary但是却可以投票。

只有 Primary 节点接收 Writes 操作 取值范围为 0 ~ 100
Priority=0 类似于Standby(被动成员),可投票不可参选,又干活又负载。

Vote 投票节点

  1. 投票节点不保存数据副本,不可能成为主节点。
  2. Mongodb 3.0里,复制集成员最多50个,参与Primary选举投票的成员最多7个。
  3. 对于超出7个的其他成员(Vote0)的vote属性必须设置为0,即不参与投票。

Hidden 节点

  1. 此节点丧失了当选Primary的机会。永远不会上位。
  2. 此节点正常参与Primary产生的oplog的读取,进行数据备份和命令执行。
  3. 此节点正常参与客户端对于数据的读取,进行担当负载均衡的工作。
  4. 此节点不参与客户端对于数据的读取,不进行负载均衡。
  5. 此节点虽然不能当选Primary但是却可以投票。

Priority=0 为必须的前置条件
如果设置了Secondary数据可读取,Hidden节点数据对客户端不可读取,对于集群可见
mongos不会同隐藏节点交互
一般应用于备份场景

Delayed 节点

  1. 此节点必须是一个Priority=0且为Hidden的节点,因为Hidden必须是Priority=0的,所以此节点必须是Hidden的。
  2. 此节点虽然又迟延又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 (读取偏好和写顾虑中使用标签)

选举机制

  1. 自身是否能够与主节点连通;
  2. 希望被选件为主节点的备份节点的数据是否最新;
  3. 有没有其他更高优先级的成员可以被选举为主节点;
  4. 如果被选举为主节点的成员能够得到副本集中“大多数”成员的投票,则它会成为主节点,如果“大多数”成员中只有一个否决了本次选举,则本次选举 失败即就会取消。一张否决票相当于10000张赞成票。
  5. 希望成为主节点的成员必须使用复制将自己的数据更新为最新;

参考资料

MongoDB集群运维笔记

最全面的 MongoDB 高可用架构剖析来啦