MongoDB 集群模式-副本集

MongoDB的集群模式有三种:

本章主要讲述副本集(Replica Set)

一、副本集介绍

1.1 什么是副本集

MongoDB 副本集是将数据同步在多个服务器的过程,复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性,同时还允许从硬件故障和服务中断中恢复数据。

1.2 什么是 Oplog

Oplog是MongoDB Primary(主节点)和Secondary(从节点)在副本集建立期间和建立完成之后的复制介质。Primary中所有的写入操作都会记录到Oplog中,然后从节点会来主节点拉取Oplog并应用到自己的节点上。这里的Oplog是MongoDB local数据库的一个集合,它是Capped collection,通俗意思就是它是固定大小,循环使用的。如下图:

Oplog 复制介质

Oplog中的内容如下:

{
    "ts" : Timestamp(1446011584, 2),
    "h" : NumberLong("1687359108795812092"),
    "v" : 2,
    "op" : "i",
    "ns" : "test.nosql",
    "o" : { "_id" : ObjectId("563062c0b085733f34ab4129"), "name" : "mongodb", "score" : "100" }
}
  • ts: 操作时间,当前timestamp + 计数器,计数器每秒都被重置
  • h:操作的全局唯一标识
  • v:oplog版本信息
  • op:操作类型
    • i:插入操作
    • u:更新操作
    • d:删除操作
    • c:执行命令(如createDatabase,dropDatabase)
  • n:空操作,特殊用途
  • ns:操作针对的集合
  • o:操作内容,如果是更新操作
  • o2:操作查询条件,仅update操作包含该字段

1.2 副本集的结构与原理

副本集结构

如上图所示,副本集由一组mongo实例组成,提供了数据冗余与高可用性。相对于主从模式,该模式可以在主节点挂掉的时候通过选举算法自动选举出新的主节点,保证服务的可用性。
该模式由三个角色组成:

  • primary: 主节点,是唯一能够接收写请求的节点。一旦主节点不可用,会选出新的主节点
  • secondaries: 从节点,提供数据备份和读功能,并且能在主节点挂掉的时候被选举为新的主节点。
  • arbiter: 投票节点或者叫仲裁节点。该角色是可选的,所以图上也没有画出来。投票节点其本身并不包含数据集,也无法被升级为主节点,但是,一旦当前的主节点不可用时,投票节点就会参与到新的主节点选举的投票中。投票节点仅在副本集成员为偶数个的时候需要,如果在拥有奇数个复制集成员的复制集中新增了一个投票节点,复制集可能会遇到选举僵局。

主节点上能够完成读写操作,从节点仅能用于读操作。主节点需要记录所有改变数据库状态的操作,这些记录保存在oplog中,各个从节点通过此oplog来复制数据并应用于本地,保持本地的数据与主节点的一致。oplog具有幂等性,即无论执行几次其结果一致。

集群中的各节点还会通过传递心跳信息来检测各自的健康状况。当主节点故障时,多个从节点会触发一次新的选举操作,并选举其中的一个成为新的主节点(通常谁的优先级更高,谁就是新的主节点),心跳信息默认每 2 秒传递一次。


心跳信息

客户端连接到副本集后,不关心具体哪一台机器是否挂掉。主服务器负责整个副本集的读写,副本集定期同步数据备份。一旦主节点挂掉,副本节点就会选举一个新的主服务器。这一切对于应用服务器不需要关心。


主节点挂掉

副本集中的副本节点在主节点挂掉后通过心跳机制检测到后,就会在集群内发起主节点的选举机制,自动选举出一位新的主服务器。

MongoDB官方建议副本集至少需要三个节点。3.0之前最多12个节点,3.0开始节点数量能够达到50个。限制副本节点的数量,主要是因为一个集群中过多的副本节点,增加了复制的成本,反而拖累了集群的整体性能。太多的副本节点参与选举,也会增加选举的时间。而官方建议奇数的节点,是为了避免选举僵局的发生(平局)。

1.3 副本集数据同步

Primary节点写入数据,Secondary通过读取Primary的oplog得到复制信息,开始复制数据并且将复制信息写入到自己的oplog。如果某个操作失败,则备份节点停止从当前数据源复制数据。如果某个备份节点由于某些原因挂掉了,当重新启动后,就会自动从oplog的最后一个操作开始同步,同步完成后,将信息写入自己的oplog,由于复制操作是先复制数据,复制完成后再写入oplog,有可能相同的操作会同步两份,不过MongoDB在设计之初就考虑到这个问题,将oplog的同一个操作
执行多次,与执行一次的效果是一样的。简单的说就是:

当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步:

  1. 检查自己local库的oplog.rs集合找出最近的时间戳。
  2. 检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录。
  3. 将找到的记录插入到自己的oplog.rs集合中,并执行这些操作。

副本集的同步和主从同步一样,都是异步同步的过程,不同的是副本集有个自动故障转移的功能。其原理是:Secondary端从primary端获取日志,然后在自己身上完全顺序的执行日志所记录的各种操作(该日志是不记录查询操作的),这个日志就是local数据 库中的oplog.rs表,默认在64位机器上这个表是比较大的,占磁盘大小的5%,oplog.rs的大小可以在启动参数中设定:--oplogSize 1000,单位是M。

1.4 何时触发选举

MongoDB 在下面几个条件触发之下进行选举:

  • 初始化副本集时;
  • 备份节点无法和主节点通讯时(可能主节点宕或网络原因);
  • Primary 手动降级,rs.stepDown(sec),默认 60s。

选举的步骤如下:

  1. 得到每个服务器节点的最后操作时间戳。每个 mongodb 都有 oplog 机制会记录本机的操作,方便和主服务器进行对比数据是否同步还可以用于错误恢复;
  2. 如果集群中大部分服务器宕机了,保留活着的节点都为 secondary 状态并停止选举;
  3. 如果集群中选举出来的主节点或者所有从节点最后一次同步时间看起来很旧了,停止选举等待人工操作;
  4. 如果上面都没有问题就选择最后操作时间戳最新(保证数据最新)的服务器节点作为主节点。

二、示例

副本集的启动,和从节点加入到副本集的操作,只能在主节点上完成,但是主节点随时可以转移到其他从节点。
启动一个副本集系统的基本步骤如下:

  • 在主节点启动 mongod 服务时,可以使用 --replSet 启动副本集,同时指定副本集名称;
  • 连接主节点,初始化新的副本集;
  • 启动各个从节点 mongod 服务,同时这些从节点也必须初始化副本集,使用同一个副本集 id;
  • 在主节点将这些从节点加入主节点副本集;

下面演示 3 个 mongodb 创建一个副本集系统:
1)主节点启动 mongod 服务

$ mongod --port 27017 --dbpath "/usr/local/mongodb/data" --replSet simon

simon 为 副本集ID
2) 2 个从节点分别启动 mongod 服务

$ mongod --port 27017 --dbpath "/usr/local/mongodb/data" --replSet simon

3)连接到主节点 mongodb,进行副本集的初始化和配置

$ mongo
> rs.initiate()      # 初始化的副本集
> rs.add("192.168.10.58:27107")   # 加入从节点,该节点为 192.168.10.58 主机 27107 端口上的 mongod 服务
> rs.add("192.168.10.138:27107")    # 加入从节点,该节点为 192.168.10.138 主机 27107 端口上的 mongod 服务

也可以这样设置

$ mongo
>rs.initiate({"_id":"simon","members":[
     {
       "_id":1,
       "host":"192.168.10.58:27017",
       "priority":1
     },
     {
       "_id":2,
       "host":"192.168.10.138:27017",
       "priority":1
     }
   ]
  }
)
  • _id: 副本集的名称
  • members: 副本集的服务器列表
  • _id: 服务器的唯一ID
  • host: 服务器主机
  • priority: 是优先级,默认为1,优先级0为被动节点,不能成为活跃节点。优先级不位0则按照有大到小选出活跃节点
  • arbiterOnly: 仲裁节点,只参与投票,不接收数据,也不能成为活跃节点。

此时一个副本系统已经完成,所有操作直接面向主节点,实际操作由整个副本集集群提供,默认是从主节点读取

查看副本集信息

> rs.conf()      # 查看副本集的配置
> rs.status()    # 查看副本集状态
> rs.isMaster()  # 查看该主机节点是否为副本集主节点

设置从节点读写策略

> rs.getMongo().setReadPref(STRATEGY)

具体策略如下:

  • Primary 从主节点读取;
  • secondary 从从节点读取;
  • nearest 从网络延迟最小的节点读取;
  • primaryPreferred 基本上从主节点读取,主节点不可用时,从从节点的读取;
  • secondaryPreferred 基本上从从节点读取,从节点不可用时,从主节点读取;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容