关于云计算:MongoDB复制集集群原理详解及部署

32次阅读

共计 12434 个字符,预计需要花费 32 分钟才能阅读完成。

参考文献:https://docs.mongodb.com/manu…

复制集介绍

MongoDB 中的复制集 (也被称为正本) 是一组保护雷同数据集的 mongod 过程。正本集提供冗余性及和高可用,是所有生产部署的根底。
简略来说,复制集有多台 MongoDB 组成的一个集群,集群中有一个主节点 (Primary) 和 N 个正本节点 (Secondary) 等,它们有雷同的数据库,如果主 MongoDB 服务器或者 MongoDB 实例 Down 机之后,其它的正本服务器能够持续提供服务,实现数据的高可用及可靠性。

复制集群架构

术语介绍:

术语 类型 形容
Primary 主节点 负责整个集群的读写操作,蕴含了所有扭转操作的日志
Secondary 备节点 同步主服务器所有的数据,负责集群的读取申请,主服务器宕机能够称为主节点
Arbiter 仲裁者 在主节点宕机后只进行投票,不参加选举,不同步主节点数据

此架构由一个 Primary 节点和两个 Secondary 节点组成

1)Primary 节点为主节点,所有的写操作或者更改操作都只能从 Primary 节点中操作(复制集内的所有成员都能够接管读操作,然而,默认状况下,应用程序将其读操作指向主成员),主节点上所有的更改及写操作都会记录到 oplog 日志中。

2)两台 Secondary 节点复制 Primary 节点的 oplog 日志,通过异步的形式去执行 oplog 日志中的记录来和 Primary 节点达到数据一致性。

3)oplog 作用次要是记录主节点的写入操作,充当复制源。

4)如果 Primary 节点无端 Down 机之后,复制集集群会通过投票机制在两台 Secondary 中选举一台降级为 Primary 节点。

投票选举机制

MongoDB 节点之间保护心跳查看,主节点选举由心跳触发。

心跳查看
MongoDB 复制集成员会向本人之外的所有成员发送心跳并解决响应信息,因而每个节点都保护着该节点看到的其它所有节点的状态信息,节点依据本人的集群状态判断是否须要更新新的 Primary。
在实现的时候次要由两个异步的过程别离解决心跳响应和超时,每个复制集成员都会在后盾运行与复制集所有节点的心跳线程,在以下几种状况下会触发状态检测过程:

  • Secondary 节点权重 (Priority) 比 Primary 节点高时,发动替换选举;
  • Secondary 节点发现集群中没有 Primary 时,发动选举;
  • Primary 节点不能拜访到大部分成员时被动降级,降级操作会断开连接,终止用户申请等;
  • 复制集成员心跳检测后果发生变化,比方某个节点挂了或者新增节点,发动从新投票选举规定;
  • 超过 4s 没有执行状态检测过程,发动替换选举;

选举发动
发动选举的节点首先须要做一些条件判断,保护主节点的有 N 个备用节点,备用节点中的所有节点都可能被选举成为主节点,成为主节点前每个备节点都会检测本身以及全局条件是否满足,检测条件如下:

  1. 是否看见复制集中是否有 Majority 在线
  2. 本身 Priority 是否大于 0
  3. 本身不为 arbiter
  4. 本身 opTime 不能落后于最新节点 10s 以上
  5. 本身存储的集群程序按信息为最新

如果所有条件满足,则将本身增加到主节点的备用列表中,否则,将本身从列表中移除

本身检测

  • MongoDB 选举须要取得 大多数 投票能力通过,如果没有节点投反对票,且取得成票数超过有权投票节点总数的 1 /2,则能成为 Primary。否则进入下一轮选举。为防止陷入有限反复选举,MongoDB 倡议复制集的成员个数为奇数,当 Secondary 为单数时,能够减少一个 Arbiter 节点。
  • 选举过程中,复制集没有主节点,所有成员都是只读状态
  • 选举过程很简单,个别状况下须要 5s 左右进行选主。
  • 如果新抉择的主节点立即挂掉,至多须要 30s 工夫从新选主。

大多数的定义
假如复制集内投票成员数量为 N,则大多数 = N/2 + 1,当复制集内存活成员数量有余大多数时,整个复制集将无奈选举出 Primary,复制集将无奈提供写服务,处于只读状态。
咱们依照下面的架构来举例,三台 MongoDB,一台 Primary,两台 Secondary,主节点挂了之后,只有两台 Secondary 能够投票,依据公式咱们来算“2/2 + 1 = 2”,也就是算大多数等于 2,然而当复制集内存活的成员数量有余大多数时,咱们的大多数为 2,集群成员也为 2,所以这两台集群成员会发动选举投票机制,如果两台 Secondary 节点本身条件都满足的状况下,则先发动选举节点的成员成为 Primary 节点

投票成员数 大多数 容忍生效数
1 1 0
2 2 0
3 2 1
4 3 1
5 3 2
6 4 2
7 4 3

复制集群成员阐明

Secondary
失常状况下,复制集的 Seconary 会参加 Primary 选举(本身也可能会被选为 Primary),并从 Primary 同步最新写入的数据,以保障与 Primary 存储雷同的数据。Secondary 能够提供读服务,减少 Secondary 节点能够提供复制集的读服务能力,同时晋升复制集的可用性。另外,Mongodb 反对对复制集的 Secondary 节点进行灵便的配置,以适应多种场景的需要。

Arbiter
Arbiter 节点只参加投票,不能被选为 Primary,并且不从 Primary 同步数据。比方你部署了一个 2 个节点的复制集,1 个 Primary,1 个 Secondary,任意节点宕机,复制集将不能提供服务了(无奈选出 Primary),这时能够给复制集增加一个 Arbiter 节点,即便有节点宕机,仍能选出 Primary。Arbiter 自身不存储数据,是十分轻量级的服务,当复制集成员为偶数时,最好退出一个 Arbiter 节点,以晋升复制集可用性。

Priority0
Priority0 节点的选举优先级为 0,不会被选举为 Primary。比方你跨机房 A、B 部署了一个复制集,并且想指定 Primary 必须在 A 机房,这时能够将 B 机房的复制集成员 Priority 设置为 0,这样 Primary 就肯定会是 A 机房的成员。(留神:如果这样部署,最好将『大多数』节点部署在 A 机房,否则网络分区时可能无奈选出 Primary)

Vote0
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 节点的数据来复原到之前的工夫点。

优先级为 0 复制集成员

此架构由一个 Primary 节点和两个 Secondary 节点组成

1)此架构由一台 Primary 主节点和两台 Secondary 备节点组成,其原理就是主从复制架构的原理,两台 Secondary 节点同样通过 oplog 日志来与 Primary 主节点达成数据统一

2)与其不同的是在 Data Center2 节点上的 Secondary 备用节点的实例优先级 priority 为 0,则不参加选举,也不可能会成为 Primary 节点,将其优先级配置为 0,次要是避免它成为主节点,这在多数据中心的部署特地有用。

3)优先级值范畴为 0-100(0 示意不参加选举),在复制集群中,优先级高的优先成为主节点,如果咱们原来集群中有三台节点,主节点优先级为 2,其它两台备节点优先级为 1,当咱们新退出到集群一台 MongoDB 实例,给它优先级设置为 4,则该实例在退出集群后就会主动争夺 Primary 到本机。

仲裁节点架构


上图中,三个成员组成复制集群

一个主库:负责整个集群的所有写、更改操作

一个从库:通过 oplog 日志来与主节点数据达成统一

一个 Airbiter 节点,在选举中,只进行投票,不能成为主库,而且不复制 Primary 的任何数据,因而这个架构中只能提供一个实现的正本 Secondary,Arbiter 只须要很少的资源,代价是无限的冗余和容错,当 Primary 节点故障后,Aribiter 将票数头给 Secondary,使其成为 Primary 节点,如果 Primary 节点再次故障后,集群将不可用,Arbiter 节点也未存储任何数据。

集群中还有其它的节点成员,然而咱们用的比拟少,所以此文章中没有提到。
能够自行查阅官网文档:https://docs.mongodb.com/manu…

复制集集群环境部署

环境阐明

本次应用一台设施多实例进行,如果你筹备在多台设施上部署,你须要思考的如下:
1)时钟是否统一
2)网络是否通顺
3)SElinux 是否敞开或者策略放通
4)环境是否统一

[root@MongoDB ~]# lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID:    CentOS
Description:    CentOS Linux release 7.6.1810 (Core) 
Release:    7.6.1810
Codename:    Core
[root@MongoDB ~]# hostname -I
10.211.55.12 192.168.0.100 fdb2:2c26:f4e4:0:21c:42ff:fedf:4d85 

后期筹备

# 创立用户组
useradd mongod
echo 'abcdef' | passwd --stdin mongod

#下载 MongoDB
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.0.tgz

#增加文件关上数和 mongod 用户过程连接数
cat >> /etc/security/limits.conf << EOF
* soft nofile 65536
* hard nofile 65536
mongod soft nproc 32768
mongod hard nproc 32768
EOF 

#使上面两个文件批改为 never
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

#开机主动批改
cat >> /etc/rc.local << EOF
if test -f /sys/kernel/mm/transparent_hugepage/enabled;then
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi

if test -f /sys/kernel/mm/transparent_hugepage/defrag;then
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF
此步骤实现后

#官网给出 MongoDB 须要以下两个库的依赖
yum install libcurl openssl -y

#解压并复制程序文件到 bin 目录
mkdir /usr/local/mongodb
tar xf mongodb-linux-x86_64-rhel70-4.2.0.tgz
cp -rf mongodb-linux-x86_64-rhel70-4.2.0/bin/ /usr/local/mongodb/
chown -Rf mongod.mongod /usr/local/moongodb/

#添加程序环境
cat >> /etc/profile << EOF
export MONGODB_HOME=/usr/local/mongodb
export PATH=\$MONGODB/bin:\$PATH
EOF

source /etc/profile

环境配置

1)接下来应用 mongod 用户来操作

su mongod

2)创立文件目录

#!/bin/bash
for i in 27017 27018 27019
    do
    mkdir -p /usr/local/mongodb/$i/{conf,data,logs,run}
done

配置文件

编辑一台配置文件,而后复制到其它实例,配置文件为 yaml 语法
对于以下配置文件详解,请参考:”https://abcops.cn/mongodb-conf/“

cat > mongod.conf << EOF
systemLog:
  destination: file
  path: /usr/local/mongodb/27017/logs/mongodb.log
  logAppend: true
  verbosity: 0
  logRotate: rename

storage:
  journal:
    enabled: true
  dbPath: /usr/local/mongodb/27017/data
  directoryPerDB: true
  engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 1
      directoryForIndexes: true
      journalCompressor: zlib
    collectionConfig:
      blockCompressor: zlib
    indexConfig:
      prefixCompression: true

processManagement:
  fork: true
  pidFilePath: /usr/local/mongodb/27017/run/mongod.pid

net:
  port: 27017
  bindIp: 10.211.55.12
  maxIncomingConnections: 65536
  wireObjectCheck: true
  ipv6: false

replication:
  oplogSizeMB: 4096
  replSetName: abcops_repl

setParameter:
  connPoolMaxShardedConnsPerHost: 200
  connPoolMaxConnsPerHost: 200
EOF

复制配置文件到目录中,并批改其端口及目录地位

#!/bin/bash
for i in 27017 27018 27019
    do
        \cp /home/mongod/mongod.conf /usr/local/mongodb/$i/conf
        sed -i "s/27017/$i/g" /usr/local/mongodb/$i/conf/mongod.conf
done

启动 MongoDB 实例

启动脚本如下

#!/bin/bash
for i in 27017 27018 27019
    do
        /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/$i/conf/mongod.conf
done

敞开脚本如下

#!/bin/bash
for i in 27017 27018 27019
    do
        /usr/local/mongodb/bin/mongod --shutdown -f /usr/local/mongodb/$i/conf/mongod.conf
done

三个实例启动后,不代表复制集曾经搭建胜利了,还须要进行复制集初始化

配置复制集

连贯任何一个实例都能够进行配置

这是我连贯 27017 的实例
/usr/local/mongodb/bin/mongo --host 10.211.55.12 --port 27017
> use admin

> config={
_id:'abcops_repl',
members:[{_id: 0, host: '10.211.55.12:27017',priority:2},
{_id: 1, host: '10.211.55.12:27018',priority:1},
{_id: 2, host: '10.211.55.12:27019',arbiterOnly:true},
    ]
}

> rs.initiate(config)


#以上参数解析
use admin:进入 admin 数据库
config:配置复制集
_id:'abcops_repl':指定复制集组名称,与配置文件中的 replSetName 参数须要保持一致
members:规定的函数,不能更改
_id:设置组成员的 ID 编号,能够自定义,我这里为 0、1、2
host:指定退出复制集成员的 IP 地址及端口,咱们在配置文件中指定了 bindIp 为 10.211.55.12,这里就不能写 127.0.0.1, 必须写为 bind_Ip 指定的地址
priority:指定优先级 0 -100,优先级最高的成为 Primary 节点,优先级为可选选项,如果不指定默认都为 1
arbiterOnly:是否开启仲裁节点 true/false

rs.initiate(config):初始化复制集配置

以上参数图示如下,给你提供下参照

图中开始为SECONDARY, 代表复制集集群正在进行选举 Primary 节点,大略 5s 左右,依据选举机制选举胜利后,成为主节点的 SECONDARY 状态变为PRIMARY

复制集常用命令

1)查看谁是主节点

abcops_repl:PRIMARY> db.isMaster()     

2)查看以后复制集集群中成员的配置

abcops_repl:PRIMARY> rs.conf()

3)查看复制集集群成员状态

abcops_repl:PRIMARY> rs.status()

4)新增节点到复制集
新增节点之前,该实例的配置中的 replSetName 复制集名称,必须和集群统一

abcops_repl:PRIMARY> rs.add("10.211.55.12:27020")

5)新增仲裁节点

abcops_repl:PRIMARY> rs.addArb("10.211.55.12:27020")

6)从复制集内删除节点

abcops_repl:PRIMARY> rs.remove("10.211.55.12:27020")

7)查看 oplog 日志工夫和大小

abcops_repl:PRIMARY> rs.printReplicationInfo() 
configured oplog size:   4096MB
log length start to end: 2422secs (0.67hrs)
oplog first event time:  Wed Sep 11 2019 12:22:13 GMT+0800 (CST)
oplog last event time:   Wed Sep 11 2019 13:02:35 GMT+0800 (CST)
now:                     Wed Sep 11 2019 13:02:37 GMT+0800 (CST)

8)降级服务器
此操作只能在 PRIMARY 上操作
通过执行 rs.stepDown 命令将以后主服务器被动降级为备用节点,120 单位为 s,为 120 秒内这个实力不能把本人选为 PRIMARY 角色,120 秒后因为它自身的优先级较高,所以会从新抢占 PRIMARY 节点。

abcops_repl:PRIMARY> rs.stepDown(120)

9)容许在 Secondary 节点能够进行查问
在正本节点上操作

rs.slaveOk()

10)查看以后连贯

db.getMongo()

批改优先级

批改 27018 的优先级为 3,使其优先级超过 27017 实例,夺得 PRIMARY 角色,此操作需在 PRIMARY 上执行

abcops_repl:PRIMARY> config=rs.conf()
abcops_repl:PRIMARY> config.members[1].priority=3
3
abcops_repl:PRIMARY> rs.reconfig(config)
{
    "ok" : 1,
    "$clusterTime" : {"clusterTime" : Timestamp(1568179129, 1),
        "signature" : {"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    },
    "operationTime" : Timestamp(1568179129, 1)
}

abcops_repl:PRIMARY> rs.conf()
abcops_repl:SECONDARY> db.isMaster()

#以上参数解析
config=rs.conf():将现有的配置读取到变量中进行存储
config.members[1].priority=3:批改变量中的值,1 是指执行 rs.conf()中看到节点的程序,不是 ID 号哦,rs.conf()看到的程序是从 0 开始排序,三个正本集排序就是 0 -3
rs.reconfig(config):将批改后的数据同步到配置,使批改失效

rs.conf():查看以后配置,能够看到优先级哦
db.isMaster():查看谁是 Primary 节点

复制测试

1)插入数据

# 连贯以后 Primary 节点
/usr/local/mongodb/bin/mongo --host 10.211.55.12 --port 27018

#进入 abcops 数据库,在 documents 文档中插入以下 JSON 格局的数据
abcops_repl:PRIMARY> use abcops
abcops_repl:PRIMARY> db.documents.insert(
    {name: "xuweiliang",
    age: 25,
    Job: "DevOps"}
)

#查看 documents 文档中的数据
abcops_repl:PRIMARY> db.documents.find()
{"_id" : ObjectId("5d78863768fbf9eac4704232"), "name" : "xuweiliang", "age" : 25, "Job" : "DevOps" }

#查看复制节点状态
abcops_repl:PRIMARY> rs.printSlaveReplicationInfo()
source: 10.211.55.12:27017
    syncedTo: Wed Sep 11 2019 13:30:42 GMT+0800 (CST)
    0 secs (0 hrs) behind the primary

2)登录 Secondary 节点查看

/usr/local/mongodb/bin/mongo --host 10.211.55.12 --port 27017

abcops_repl:SECONDARY> rs.slaveOk()         #运行正本节点可进行查问
abcops_repl:SECONDARY> show dbs             #查看以后节点的数据库
abcops  0.000GB
admin   0.000GB
config  0.000GB
local   0.000GB
abcops_repl:SECONDARY> use abcops               #abcops 数据库曾经从主节点同步至此
switched to db abcops
abcops_repl:SECONDARY> db.getCollectionNames()  #以下间断三个命令都是查看进入到 abcops 库中的文档命令
["documents"]
abcops_repl:SECONDARY> show collections
documents
abcops_repl:SECONDARY> show tables
documents
abcops_repl:SECONDARY> db.documents.find()      #查看文档中的内容
{"_id" : ObjectId("5d78863768fbf9eac4704232"), "name" : "xuweiliang", "age" : 25, "Job" : "DevOps" }

创立复制集中的账户

1)连贯到主节点,创立用户
以下创立的用户及权限和角色请参考上面用户权限阐明

/usr/local/mongodb/bin/mongo --host 10.211.55.12 --port 27018
abcops_repl:PRIMARY> use admin

abcops_repl:PRIMARY> db.createUser( {
        user:'abcops',
        pwd:'123456',
        roles:[{ role: "root", db: "admin"} ]
    }
)
Successfully added user: {
    "user" : "abcops",
    "roles" : [
        {
            "role" : "root",
            "db" : "admin"
        }
    ]
}

#查看所有创立的用户信息
abcops_repl:PRIMARY> show users 

用户中权限的阐明

权限 阐明
Read 容许用户读取指定数据库
readWrite 容许用户读写指定数据库
dbAdmin 容许用户在指定数据库中指定治理函数,如(索引创立、删除、查看统计拜访 system.profile)
userAdmin 容许用户向 system.users 汇合写入,能够找指定数据外面创立、删除和治理用户
clusterAdmin 只在 admin 数据库中可用,赋予用户所有分片和复制集相干函数的管理权限
readAnyDatabase 只在 admin 数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase 只在 admin 数据库中可用,赋予用户所有数据库的读写权限
userWriteAnyDatabase 只在 admin 数据库中可用,赋予用户所有数据库的 userAdmin 权限
dbAdminAnyDatabase 只在 admin 数据库中可用,赋予用户所有数据库的 dbAdmin 权限
root 只在 admin 数据库中可用,超级管理员

为复制集集群增加权限认证

复制集咱们这里采纳 keyfile 文件实现权限认证,并且正本集中的所有成员应用的 keyfile 必须一样

增加平安认证配置

三台实例必须都要配置

cat >> /usr/local/mongodb/27017/conf/mongod.conf << EOF

security:
  authorization: enabled
  clusterAuthMode: keyFile
  keyFile: /usr/local/mongodb/27017/conf/keyfile
  javascriptEnabled: true
EOF 


cat >> /usr/local/mongodb/27018/conf/mongod.conf << EOF

security:
  authorization: enabled
  clusterAuthMode: keyFile
  keyFile: /usr/local/mongodb/27018/conf/keyfile
  javascriptEnabled: true
EOF

cat >> /usr/local/mongodb/27019/conf/mongod.conf << EOF

security:
  authorization: enabled
  clusterAuthMode: keyFile
  keyFile: /usr/local/mongodb/27019/conf/keyfile
  javascriptEnabled: true
EOF

keyfile 文件操作

1)生产 keyfile 文件

openssl rand -base64 90 > ./keyfile

2)复制 keyfile 文件到其它实例中

#!/bin/bash
for i in 27017 27018 27019
    do
        \cp /home/mongod/keyfile /usr/local/mongodb/$i/conf/
done

3)批改 keyfile 权限
keyfile 文件权限必须为 X00,不能给 group 和 other 成员调配任何权限,否则实例无奈启动

#!/bin/bash
for i in 27017 27018 27019
    do
        chmod 400 /usr/local/mongodb/$i/conf/keyfile
done

4)重启所有实例

#!/bin/bash
for i in 27017 27018 27019
    do
        /usr/local/mongodb/bin/mongod --shutdown -f /usr/local/mongodb/$i/conf/mongod.conf
        sleep 3s
        /usr/local/mongodb/bin/mongod -f /usr/local/mongodb/$i/conf/mongod.conf
done

认证验证

登录验证能够在连贯的时候指定用户名和明码,也能够先连贯到数据库后再进行认证

1)登录指定用户明码

/usr/local/mongodb/bin/mongo --host 10.211.55.12 --port 27018 --username abcops -p 123456
abcops_repl:PRIMARY> show dbs
abcops  0.000GB
admin   0.000GB
config  0.000GB
local   0.000GB

2)先登录,后验证

abcops_repl:PRIMARY> use admin                          #必须要先切换到 admin 库中才能够进行进行验证
switched to db admin
abcops_repl:PRIMARY> db.auth('abcops','123456')       #认证用户名及明码,认证胜利返回 1,否则返回 0
1
abcops_repl:PRIMARY> show dbs           
abcops  0.000GB
admin   0.000GB
config  0.000GB
local   0.000GB
abcops_repl:PRIMARY> db
admin

3)在备库进行验证
备库只能进行查问,勿要在备库上进行任何操作

/usr/local/mongodb/bin/mongo --host 10.211.55.12 --port 27017

abcops_repl:SECONDARY> rs.slaveOk()
abcops_repl:SECONDARY> use admin
switched to db admin
abcops_repl:SECONDARY> db.auth('abcops','123456')
1

客户端验证

咱们能够找一台 SQL 管理工具来连贯该库

能够看到我创立的 abcops 库和一个文档及三个字段

有段时间没跟大家分享资源福利了,看了下本人的资料夹,整顿了一些我认为比拟好的 Python 学习材料了。置信这套材料能够对你进阶高级工程师有帮忙

学习工具

大厂实战手册

自学视频(局部)

【材料收费支付形式】: 点这里:2020Python 高薪实战学习大合集

正文完
 0