MongoDB副本集实现主从热备

MongoDB副本集搭建

环境准备

  1. 参考教程
  2. 三台CentOS 7 64 位虚拟机1192.168.2.5-mg1(primary)、192.168.2.6-mg2(secondary)、192.168.2.7-mg3(secondary)
  3. MongoDB版本:mongodb-linux-x86_64-amazon-4.2.8.tgz 下载地址

安装配置

副本集的特点

1)主节点唯一

主节点唯一,但是不固定(不确定的原因是:主节点挂了的话,会重新选举出一个主节点)。

2)大多数原则

大多数原则,即1/2原则,一个复制集集群中,如果有大于等于1/2的节点不可用的话,那么整个进群将不可写,只可读(注:实际上应该是投票权重的1/2。

3)从库无法写入

从库无法写入,使用root权限也不行,这一点与MySQL不同,MySQL从库不能写入,原因是设置了readOnly。

4)副本集可以自动进行容灾

主节点服务不可用,会自动选举出新的主节点。

副本集节点介绍

1)数据节点-------主节点(Primary)

主节点负责数据的读写操作,并把写的操作记录到OpLog中(mongo隐藏的库local的oplog集合)

2)数据节点-------从节点(Secondary)

复制主节点的数据,备份容灾用,主节点挂掉,会重新选举出新的主节点,从节点无法进行写操作,即使拥有root权限也不行(不同于MySQL)

3)投票节点(Arbiter)

不负责数据的存储和复制,只负责投票。(注:理论上一个mongo复制集,可以有一个主节点,多个从节点,多个投票节点) 无法 升职为主节点。投票节点的存在是为了使复制集中的节点数量为奇数,这样保证在进行投票的时候不会出现票数相同的情况。如果添加了一个节点后,总节点数为偶数,那么就需要相应的增加一个投票节点。

  1. 禁用 THP(数据库应用对内存的访问一般都是稀疏访问模式而很少是连续访问模式,如果启用大页面会导致更多的磁盘 IO)。
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag 
  1. 解压安装包。

    mkdir /usr/local/mongodb4.2.8
    cd /usr/local/mongodb4.2.8
    # 上传文件并解压
    tar -xvf mongodb-linux-x86_64-amazon-4.2.8.tgz
    # 重命名
    mv mongodb-linux-x86_64-amazon-4.2.8 mongodb
    
  2. 创建配置文件。

    cd /usr/local/mongodb4.2.8/mongodb && mkdir config && cd config
    cat<<"EOF">mongodb.conf
    bind_ip = 0.0.0.0
    #bind_ip_all = true 
    # add in 3.6 和 bind_ip 互斥
    port = 27017
    # 数据目录
    dbpath = /var/lib/mongodb/mongodb4.2.8
    # 日志目录
    logpath = /var/log/mongodb4.2.8.log 
    #数据是否故障恢复
    journal = true
    #复制集日志是以追加的方式进行
    logappend = true
    #是否后台启动
    fork = true
    auth = false
    # 副本集启用认证的配置
    #keyFile = 
    directoryperdb = true
    storageEngine = wiredTiger
    #wiredTigerCacheSizeGB = 1
    #profile = 2
    #slowms = 1000
    #oplogSize = 100
    # 副本集名称
    #replSet = test 
    EOF
    
  3. 创建数据目录。

    mkdir -pv /var/lib/mongodb/mongodb4.2.8
    
  4. 启动 mongodb。

    yum -y install numactl.x86_64
    numactl --interleave=all /usr/local/mongodb4.2.8/mongodb/bin/mongod -f /usr/local/mongodb4.2.8/mongodb/config/mongodb.conf
    
  5. 确认启动,通过ps命令可以看到以下进程,说明成功启动,如果启动失败可以通过/var/log/mongodb4.2.8.log 日志文件观察具体失败原因。 以下为命令和输出示例:

ps -ef | grep mongodb
root      92478      1 20 17:39 ?        00:00:01 /usr/local/mongodb4.2.8/mongodb/bin/mongod -f /usr/local/mongodb4.2.8/mongodb/config/mongodb.conf
  1. 登录
/usr/local/mongodb4.2.8/mongodb/bin/mongo --host 127.0.0.1 --port 27017
#创建相关账号 3.x 或 4.x 需要提前创建账号才能使用 rs.add()
use admin
db.createUser({user:"root",pwd:"root",roles:[{role:"root",db:"admin"}]});
#验证账号密码
use admin
db.auth('root','root')

通过以上步骤我们就成功的启动了 3 个 MongoDB 实例。

配置副本集

副本集配置比较简单,主要关注两个参数 replSet (每个节点必须配置一致)和 keyFile (认证相关)。

  1. 任意一台服务器生成 keyfile 文件,用于副本集认证,然后传送到每台服务器。

cd /usr/local/mongodb4.2.8/mongodb/config

openssl rand -base64 741 > mongodb-keyfile




2. 注意修改权限,否则会报错。

```shell
chmod 600 mongodb-keyfile 

权限未修改为 600 的报错如下输出: ACCESS permissions on xxx are too open

  1. 编辑每个实例的配置文件,修改 replSet 和 keyfile

vi /usr/local/mongodb4.2.8/mongodb/config/mongodb.conf

auth = true
replSet = myRepl
keyFile = /usr/local/mongodb4.2.8/mongodb/config/mongodb-keyfile




4. 重启 mongodb

```shell
 /usr/local/mongodb4.2.8/mongodb/bin/mongod -f /usr/local/mongodb4.2.8/mongodb/config/mongodb.conf --shutdown 
 
 numactl --interleave=all  /usr/local/mongodb4.2.8/mongodb/bin/mongod -f /usr/local/mongodb4.2.8/mongodb/config/mongodb.conf
  1. 加入副本集集群

    #使用命令行,进入到主节点实例
    /usr/local/mongodb4.2.8/mongodb/bin/mongo --host 127.0.0.1 --port 27017
    #验证账号密码,获取权限
    use admin
    db.auth('root','root')
    
    #初始化一个副本集
    config = {_id: "myRepl", members: []} # _id 为副本集的名称
    config.members.push({_id: 0, host: "192.168.2.5:27017", "priority": 2})
    config.members.push({_id: 1, host: "192.168.2.6:27017", "priority": 1})
    config.members.push({_id: 2, host: "192.168.2.7:27017", "priority": 1})
    rs.initiate(config)
    
    #查看副本集状态命令
    rs.conf()
     
    #加入secondary节点
    #rs.add("192.168.2.6:27017")
     
    #加入投票节点
    #rs.addArb("192.168.2.7:27017")
     
    #查看副本集状态
    rs.status()
     
     
    #重要且必须, secondary节点允许读取操作在当前节点进行,否则从节点无法复制主节点的数据
    #进入secondary实例-从节点
    /usr/local/mongodb4.2.8/mongodb/bin/mongo --host 127.0.0.1 --port 27017
    #验证账号密码,获取权限
    use admin
    

db.auth(‘root’,‘root’)
rs.slaveOk()




至此为止一个三节点的副本集已经搭建完成。

Navicat连接示例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBSvvFFP-1594198368164)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200708103355034.png)]

## 测试

```sql
#主节点
use admin
db.auth('root','root')

use test
db.createCollection('user')
db.user.insert({'name':'james'})

#从节点
use admin
db.auth('root','root')

use test
show collections
db.user.find()

常用命令

以下命令能帮助您更快的上手副本集。

  • 查看oplog 大小

    rs.printReplicationInfo() # 2.6+``db.getReplicationInfo()

  • 查看延迟

    db.printSlaveReplicationInfo()

  • 查看副本集的状态

    rs.status()

  • 设置SECONDARY 为可读

    rs.slaveOk() db.isMaster() rs.config()

  • 增加副本集成员

    rs.add()

  • 删除副本集成员

    rs.remove()

    rs 帮助命令

    rs.help()

  • 使Primary 节点退化为

Secondary ,并在一段时间内不能参与选举。

rs.stepDown(time)

  • 阻止选举,始终处于备份节点状态。比如主节点需要做一些维护,不希望其他成员选举为主节点,可以在每个备份节点上执行。强制他们出于备份节点状态。

    rs.freeze(time)

常见问题

在使用副本集的过程中,对于一些有较高频率碰到的问题,在此做了一些总结,用以帮助想要学习 MongoDB 副本集的小伙伴们少走弯路。

  1. 初始化节点的时候报错怎么办?

    • 如果某个节点有数据,则必须到该节点初始化,否则会报错 “errmsg” : “couldn’t initiate : member 127.0.0.1:27017 has data already, cannot initiate set. All members except initiator must be empty.”
    • 对于一机多实例,如果单独用 rs.initiate()则会默认用主机名:端口初始化"me" : "mytest201.com:27018"导致 rs.add (“127.0.0.1:27018”)“errmsg” : “exception: can’t use localhost in repl set member names except when using it for all members”。
  2. 为什么使用奇数个数成员?

    MongoDB 本身设计的就是一个可以跨 IDC 的分布式数据库,假设一种场景,偶数 8 节点,IDC 网络故障发生分裂,这两个分裂后的 IDC 各持有 4 个节点,因为投票数未超过半数,所以无法选举出新 Primary。

  3. 仲裁节点作用?

    仲裁节点并不需要太多系统资源,也并不持有数据本身,而是参与投票。 投票选举机制,根据数据最后操作、更新时间戳等判定,若有两方都为最新,且票数相等,此环节需要等待若干分钟。仲裁节点打破这个僵局。当节点数目为奇数时,可以不需要。 当节点数目为偶数个时,需要部署一个仲裁节点,否则偶数个节点,当主节点挂了后,其他节点会变为只读。

  4. 将一台节点移除副本集,并且注释掉相关配置文件后,重启启动该节点登录后会有REMOVED 字样,如何去掉?

    登录后在 local 数据库下查找 db.system.replset.find(),如果还有之前的副本集相关记录,删掉即可,db.system.replset.remove({})

  5. 什么情况下会出现 OTHER 状态?

    当使用 rs.reconfig 重新对副本集进行初始化的时候,SECONDARYARBITER 节点会出现 OTHER 状态。

  6. 对于连接 MongoDB 的客户端都是外网的情况,如何配置副本级?

    初始化副本级的时候 host 必须为外网 IP。

参考资源

  • MongoDB 副本文档
  • 使用 IBM Cloud Kubernetes Service 部署一个 MongoDB 副本集
  • MongoDB4.2.8副本集部署

你可能感兴趣的:(mongodb,mongodb)