【mongo系列】 七、mongo副本集群

本文详细介绍了MongoDB副本集群的搭建、测试过程,包括三节点、四节点以及四节点加仲裁节点的集群配置。讨论了集群的角色、选举机制,以及在故障发生时的处理方法,强调了奇数节点集群的高可用性优势。
摘要由CSDN通过智能技术生成

一、简介

mongo副本集即一组mongo实例组成的一个集群,集群中有一个Primary节点和多个Secondary节点

客户端的所有数据都写入Primary节点,Secondary节点从Primary节点同步数据,从而实现数据冗余与高可用

客户端通过driver链接mongo集群时所有节点都写入链接字符串中,mongo集群角色转变,主备切换时客户端并不用做任何配置修改。

  • 架构如下

    • 客户端的读写请求全部在primary节点上

    • secondary同步primary节点的数据

    当然客户端也可以通过配置让secondary处理读请求

在这里插入图片描述

二、集群角色与选举机制

1. 集群角色

前两种为常见角色

  • primary

    主节点,接受所有的写请求,然后把数据修改同步到secondary节点。

    一个集群只能有一个主节点。

    主节点故障后其他节点会再选出一个主节点。

  • secondary

    从节点,同步主节点数据,保存一份数据副本,也可提供读服务。

    主节点故障后参与投票并且自身可被选择为主节点。

  • arbiter

    仲裁者,不保存数据,仅参与投票,自身不能被选择为主节点

  • priority0

    该节点的选举优先级为0,不会被选举为primary节点,比如性能较差或者跨机房部署,防止主节点切到另一个机房,priority参数用于控制选主优先级,数字越大越容易被选为主节点

  • vote0

    vote为0的节点不参与投票

  • hidden

    hidden节点不能被选为主节点,且对客户端driver不可见,可以用来做些数据备份之类的工作

  • delayed

    delayed节点必须是hidden节点,可配置数据与primary节点落后一段时间,这样主节点误删或误修改后可以从这个节点恢复数据

3. 选举机制

  • 集群初始化或主节点故障或手动切换主节点时会触发选举。

  • 集群故障容忍度

    假设集群内参数投票节点数为N

    仅当集群内存活的投票节点超过N/2+1时才可以选择出主节点,集群才可用

    若小于该数量则集群变为只读状态

    投票节点数 N/2+1 容忍故障节点数
    1 1 0
    2 2 0
    3 2 1
    4 3 1
    5 3 2
    6 4 2

    ​ 从上表可以看出偶数节点集群的故障容忍度与比它少一个节点的奇数节点相同,因此从集群可用性方面讲偶数节点没有任何意义(从数据可靠性来讲还是有意义的必经多了一个数据副本),因此线上环境一般建议部署奇数个节点的集群

三、副本集群搭建与测试

1. 三节点集群搭建测试

(1)配置三个单独的mongo实例

我们在同一台机器上分别使用三个端口启动三个mongo实例来做集群

  • 创建mongo用户

    useradd mongo
    echo "mongo" | passwd --stdin mongo
    
  • 解压mongo二进制文件

    tar -xzvf mongodb-linux-x86_64-rhel70-4.2.3.tgz -C /usr/local/
    cd /usr/local/
    mv mongodb-linux-x86_64-rhel70-4.2.3 mongodb
    chown mongo:mongo mongodb/ -R
    
  • 修改环境变量

    • 若允许所有用户都可以使用mongo命令则在/etc/profile中加入如下行,然后执行source /etc/profile生效
    • 若仅允许mongo用户使用mongo则切换到mongo用户,在mongo用户家目录中的.bash_profile文件中加入如下行,然后source ~/.bash_profile生效
    export PATH=/usr/local/mongodb/bin:$PATH
    
  • /data/mongo下新建三个目录,作为mongo的数据目录

    mkdir -p /data/mongo/2701{
         7,8,9}/{
         data,log}
    chown mongo:mongo -R /data/mongo
    

    创建完成后目录如下:

    /data/mongo/
    ├── 27017
    │   ├── data
    │   └── log
    ├── 27018
    │   ├── data
    │   └── log
    └── 27019
        ├── data
        └── log
    
  • 在27017,27018,27019三个目录下新建mongo.conf配置文件,文件内容如下,每个实例修改端口和路径配置

    // 27017/mongo.conf
    dbpath=/data/mongo/27017/data
    logpath=/data/mongo/27017/log/mongo.log      
    fork=true                               // 后台运行 
    port=27017			
    replSet=rs1								// 副本集名称,所有节点都要相同
    
    // 27018/mongo.conf
    dbpath=/data/mongo/27018/data
    logpath=/data/mongo/27018/log/mongo.log      
    fork=true                               
    port=27018
    replSet=rs1
    
    // 27019/mongo.conf
    dbpath=/data/mongo/27019/data
    logpath=/data/mongo/27019/log/mongo.log      
    fork=true                               
    port=27019
    replSet=rs1
    
  • 启动三个实例

    // 切换到mongo用户
    su - mongo
    // 启动三个实例
    mongod -f /data/mongo/27017/mongo.conf
    mongod -f /data/mongo/27018/mongo.conf
    mongod -f /data/mongo/27019/mongo.conf
    
  • 检查

    分别执行连接这三个端口看能否正常连接

    mongo --port 27017
    mongo --port 27018
    mongo --port 27019
    

    (2)集群配置

  • 登录27017实例,初始化集群

    // 登录实例
    mongo --port 27017
    // 初始化集群
    rs.initiate()
    

    初始化之后mongo shell提示符会变成如下状态,先是OTHER然后变成primary,说明我们当前节点已经是主节点了

    rs1:OTHER> 
    rs1:PRIMARY> 
    rs1:PRIMARY>
    

    可以使用rs.status()查看集群状态

    结果太多截了一部分,members块里面列出的集群成员及状态

    可以看到27017节点状态是primary

在这里插入图片描述

  • 添加一个节点

    rs.add("localhost:27018")
    

    然后在用rs.status()看下集群状态

    可以看到members中有两个节点了,新加入的节点角色是secondary

在这里插入图片描述

  • 下面我们再加入一个节点

    rs.add("localhost:27019")
    

    此时我们再来查看状态可以查看到三个节点的状态

    (3)测试

    为了便于测试集群可用性,用如下一个小脚本连续插入

    这里写了个python脚本,不停的插入数据

    (需要安装pymongo模块pip install pymongo

    #!/usr/bin/python
    import pymongo
    
    mongo_str="mongodb://localhost:27017,localhost:27018,localhost:27019/"
    
    myclient=pymongo.MongoClient(mongo_str)
    
    mydb=myclient["testdb"]
    
    mycol=mydb["test"]
    
    mycol.drop()
    
    if __name__ == '__main__':
        count=1
        while 1==1:
            mydict={
         "_id":count,"a":count}
            x=mycol.insert_one(mydict)
            print(x.inserted_id)
            count+=1
    

    脚本执行的截图就不贴了,我们手动kill mongo进程观察写入情况

    结论:

    1. 若故障节点为secondary节点,不影响程序执行
    2. 若故障节点为primary节点,在集群选举新主节点是程序会稍微卡顿以下(1秒以内)
    3. 若故障两个节点,则程序终止,无法继续执行。(第二个挂掉的如果是从节点,不会立即中断,还可以写入一点数据,然后才会报异常退出)

2. 四节点集群测试

我们继续在刚才的三节点集群基础上,在扩充一个节点,使用27020端口

  • 创建mongo目录

    mkdir -p /data/mongo/27020/{data,log}
    
  • 创建配置文件

    cat /data/mongo/27020/mongo.conf

    dbpath=/data/mongo/27020/data
    logpath=/data/mongo/27020/log/mongo.log      
    fork=true                               
    port=27020
    replSet=rs1
    
  • 启动这个mongo实例

    mongod -f /data/mongo/27020/mongo.conf
    
  • 登录原来的集群加入这个新节点

    需要登录到主节点,我这里是27019

    // 登录
    mongo --port 27019
    // 加入新节点
    rs.add("localhost:27020")
    // 查看状态
    rs.status()
    
  • 测试

    继续用刚才的脚本,在运行起来,然后手动杀掉进程测试执行状态

    • 0
      点赞
    • 2
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值