【Python基础】mongodb副本集如何搭建

2021-01-20 10:21发布

2条回答
年年
2楼 · 2021-01-20 16:39

环境准备

服务器:centOS7
mongodb版本:3.6.2
副本集方案:1个主节点+2个二级节点
注意:部署生产环境的时候最好将不同的节点部署在不同的服务器上,本文为了演示,因此直接部署在同一台。

配置

3个节点除了端口号其余的配置都一样,如下:

processManagement:
    fork: true
    pidFilePath: ../mongod.pid
net: 
    bindIp: 0.0.0.0
    port: 27019
    maxIncomingConnections: 65536  
    wireObjectCheck: true 
    ipv6: falsestorage:
    dbPath: ../data
    indexBuildRetry: true
    journal:
        enabled: truesystemLog:
    path: ../logs/mongodb.log
    logAppend: true
    destination: file
replication:
    oplogSizeMB: 10240
    replSetName: myrepl
    secondaryIndexPrefetch: all
security:
    authorization: enabled
    clusterAuthMode: keyFile
    keyFile: ../../mongodb.key
    javascriptEnabled: true

步骤

  1. 生成keyFile文件

openssl rand -base64 735 > mongodb.key  
chmod 600 mongodb.key
  1. 分别启动各个节点mongodb实例

./mongod -f ../mongod.conf//进入mongodb的bin目录下
  1. 服务器启动之后,进入任意一个节点的命令行,将三个的实例关联起来

> config = {... _id : "myrepl",... members : [... {_id : 0, host : "127.0.0.1:27017"},... {_id : 1, host : "127.0.0.1:27018"},... {_id : 2, host : "127.0.0.1:27019"}]}{
        "_id" : "myrepl",
        "members" : [
                {
                        "_id" : 0,
                        "host" : "127.0.0.1:27017"
                },
                {
                        "_id" : 1,
                        "host" : "127.0.0.1:27018"
                },
                {
                        "_id" : 2,
                        "host" : "127.0.0.1:27019"
                }
        ]}
  1. 初始化副本集的配置

> rs.initiate(config)
{
        "ok" : 1,
        "operationTime" : Timestamp(1520260635, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1520260635, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}
>
  1. 当初始化配置信息后,可以明显的看到mongodb的命令行发生了变化,会显示出当前节点所属的副本集名称和节点类型。

[root@pmj bin]# ./mongoMongoDB shell version v3.6.2connecting to: mongodb://127.0.0.1:27017MongoDB server version: 3.6.2myrepl:PRIMARY>

至此,mongodb的副本集配置已经完成了,接下来是测试副本集是否可用

测试

  1. 由于之前的配置是开启安全认证的,因此需要进入主节点先建一个root用户,然后认证

myrepl:PRIMARY> use admin
switched to db admin
myrepl:PRIMARY>  db.createUser({user: "admin",pwd:"admin",roles:[{role:"root",db:"admin"}]})
Successfully added user: {
        "user" : "admin",
        "roles" : [
                {
                        "role" : "root",
                        "db" : "admin"
                }
        ]
}
myrepl:PRIMARY> db.auth("admin","admin")
1
myrepl:PRIMARY>
  1. 查看副本集状态

myrepl:PRIMARY> rs.config()
{
        "_id" : "myrepl",
        "version" : 1,
        "protocolVersion" : NumberLong(1),
        "members" : [
                {
                        "_id" : 0,
                        "host" : "127.0.0.1:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 1,
                        "host" : "127.0.0.1:27018",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "127.0.0.1:27019",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],
        "settings" : {
                "chainingAllowed" : true,
                "heartbeatIntervalMillis" : 2000,
                "heartbeatTimeoutSecs" : 10,
                "electionTimeoutMillis" : 10000,
                "catchUpTimeoutMillis" : -1,
                "catchUpTakeoverDelayMillis" : 30000,
                "getLastErrorModes" : {
                },
                "getLastErrorDefaults" : {
                        "w" : 1,
                        "wtimeout" : 0
                },
                "replicaSetId" : ObjectId("5a9d561bdecc034b55b5a5b9")
        }
}
  1. 查看主节点信息

myrepl:PRIMARY> rs.isMaster(){
        "hosts" : [
                "127.0.0.1:27017",
                "127.0.0.1:27018",
                "127.0.0.1:27019"
        ],
        "setName" : "myrepl",
        "setVersion" : 1,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "127.0.0.1:27017",
        "me" : "127.0.0.1:27017",
        //.......................}
  1. 新建一个测试库mydb和测试用户test,用于测试数据插入

myrepl:PRIMARY> use mydb
switched to db mydb
myrepl:PRIMARY>  db.createUser({user: "test",pwd:"test",roles:[{role:"readWrite",db:"mydb"}]})Successfully added user: {
        "user" : "test",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "mydb"
                }
        ]}myrepl:PRIMARY> use mydb
switched to db mydb
myrepl:PRIMARY> db.auth("test","test")1

5.插入100条数据

myrepl:PRIMARY> for(var i = 0; i < 100; i++) {... db.testCollection.insert({order: i, name: "test" + i}) }WriteResult({ "nInserted" : 1 })myrepl:PRIMARY> db.testCollection.count()100
  1. 进入二级节点,查看数据是否同步

myrepl:SECONDARY> use mydb
switched to db mydb
myrepl:SECONDARY> db.auth("test","test")1myrepl:SECONDARY> db.testCollection.count()2018-03-05T22:58:27.069+0800 E QUERY    [thread1] Error: count failed: {
        "operationTime" : Timestamp(1520261897, 1),
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotMasterNoSlaveOk",
        //.........................省略}

当我们要查看二级节点数据时,发现出错,这是因为二级节点默认情况下是拒绝读取的,因此需开启读取功能

myrepl:SECONDARY> conn = new Mongo("127.0.0.1:27018")connection to 127.0.0.1:27018myrepl:SECONDARY> conn.setSlaveOk()

接着再查看数据,发现已经同步了

myrepl:SECONDARY> use mydb
switched to db mydbmyrepl:SECONDARY> db.auth("test","test")1myrepl:SECONDARY> db.testCollection.count()100

故障转移

在这个例子中,副本集有3个成员,因此,我们将现在的主节点(端口号为27017)进程杀死,然后再查看副本集的状态,发现节点(端口号27019)的变为主节点

myrepl:PRIMARY> rs.isMaster(){
        "hosts" : [
                "127.0.0.1:27017",
                "127.0.0.1:27018",
                "127.0.0.1:27019"
        ],
        "setName" : "myrepl",
        "setVersion" : 1,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "127.0.0.1:27019",
        "me" : "127.0.0.1:27019",
       //后面省略

测试数据插入也是正常的

myrepl:PRIMARY> use mydb
switched to db mydb
myrepl:PRIMARY> db.testCollection.count()
100
myrepl:PRIMARY> db.testCollection.insert({name:"test",pwd:"test",address:"beijing"})
WriteResult({ "nInserted" : 1 })

将最开始关掉进程的节点重启,会发现其变为副本集的二级节点,且数据会同步

增删节点

  1. 删除节点:进入主节点27019,然后移除27018节点

myrepl:PRIMARY> use admin
switched to db admin
myrepl:PRIMARY> db.auth("admin","admin")1myrepl:PRIMARY> rs.remove("127.0.0.1:27018"){
        "ok" : 1,
        "operationTime" : Timestamp(1520340394, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1520340394, 1),
                "signature" : {
                        "hash" : BinData(0,"0VUzGmXGZ4EXAUC/HYJbRaPY6qc="),
                        "keyId" : NumberLong("6529469760260800513")
                }
        }}myrepl:PRIMARY> rs.isMaster(){
        "hosts" : [
                "127.0.0.1:27017",
                "127.0.0.1:27019"
        ],
        "setName" : "myrepl",
        "setVersion" : 2,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "127.0.0.1:27019",
        "me" : "127.0.0.1:27019",
        //后面省略
  1. 增加节点:进入主节点27019,然后将刚刚删除的节点27018又重新加入到集群中

myrepl:PRIMARY> rs.add("127.0.0.1:27018")
{
        "ok" : 1,
        "operationTime" : Timestamp(1520340538, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1520340538, 1),
                "signature" : {
                        "hash" : BinData(0,"a3TQIbz8yCaDh4Uxh4yUUkF7auk="),
                        "keyId" : NumberLong("6529469760260800513")
                }
        }
}
myrepl:PRIMARY> rs.isMaster()
{
        "hosts" : [
                "127.0.0.1:27017",
                "127.0.0.1:27019",
                "127.0.0.1:27018"
        ],
        "setName" : "myrepl",
        "setVersion" : 3,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "127.0.0.1:27019",
        "me" : "127.0.0.1:27019",
        "electionId" : ObjectId("7fffffff0000000000000002"),
        后面省略.......

修改节点

修改优先级

  1. 获取节点配置信息

myrepl:PRIMARY> cfg = rs.config(){
        "_id" : "myrepl",
        "version" : 3,
        "protocolVersion" : NumberLong(1),
        "members" : [
                {
                        "_id" : 0,
                        "host" : "127.0.0.1:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "127.0.0.1:27019",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 3,
                        "host" : "127.0.0.1:27018",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],
       //后面省略
  1. 修改节点信息

myrepl:PRIMARY> cfg.members[0].priority=9
9
myrepl:PRIMARY> cfg.members[1].priority=6
6
myrepl:PRIMARY> cfg.members[2].priority=6
6
  1. 重新配置副本集信息后,发现每个节点的priority值改了,并且优先级最高的变为了主节点

myrepl:PRIMARY> rs.reconfig(cfg)
{
        "ok" : 1,
        "operationTime" : Timestamp(1520341204, 2),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1520341204, 2),
                "signature" : {
                        "hash" : BinData(0,"G3PlqiS3AP7NHVVqp9svYSmNrdI="),
                        "keyId" : NumberLong("6529469760260800513")
                }
        }
}
myrepl:PRIMARY> rs.config()
{
        "_id" : "myrepl",
        "version" : 4,
        "protocolVersion" : NumberLong(1),
        "members" : [
                {
                        "_id" : 0,
                        "host" : "127.0.0.1:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 9,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "127.0.0.1:27019",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 6,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 3,
                        "host" : "127.0.0.1:27018",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 6,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],

隐藏成员

要将节点变为隐藏节点,节点的priority值必须为0,否则配置会失败

myrepl:PRIMARY> cfg.members[2].priority=0
0
myrepl:PRIMARY> cfg.members[2].hidden=true
true
myrepl:PRIMARY> rs.reconfig(cfg)
{
        "ok" : 1,
        "operationTime" : Timestamp(1520341554, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1520341554, 1),
                "signature" : {
                        "hash" : BinData(0,"ZHXBdgARPnus/DDNl4fVjXVs30I="),
                        "keyId" : NumberLong("6529469760260800513")
                }
        }
}
myrepl:PRIMARY> rs.isMaster()
{
        "hosts" : [
                "127.0.0.1:27017",
                "127.0.0.1:27019"
        ],
        "setName" : "myrepl",
        "setVersion" : 5,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "127.0.0.1:27017",
        "me" : "127.0.0.1:27017",

延迟节点

要将节点变为延迟节点,节点的priority值必须为0,否则配置会失败

myrepl:PRIMARY> cfg.members[1].priority=0
0
myrepl:PRIMARY> cfg.members[1].slaveDelay=NumberLong(240)
NumberLong(60000)
myrepl:PRIMARY> rs.reconfig(cfg)
{
        "ok" : 1,
        "operationTime" : Timestamp(1520341773, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1520341773, 1),
                "signature" : {
                        "hash" : BinData(0,"6dkgGNTaykWIa0ojdBSqyZ7j8IM="),
                        "keyId" : NumberLong("6529469760260800513")
                }
        }
}

上面是将节点27019变为延迟节点,延迟时间为4分钟,现在往主节点数据库mydb的testHello集合插入一条数据

myrepl:PRIMARY> use mydb
switched to db mydb
myrepl:PRIMARY> db.testHello.insert({name:"hello",pwd:"world"})
WriteResult({ "nInserted" : 1 })

插入之后,在4分钟之内进入延迟节点,发现数据并没有同步,说明配置延迟节点成功

myrepl:SECONDARY> conn = new Mongo("127.0.0.1:27019")connection to 127.0.0.1:27019myrepl:SECONDARY> conn.setSlaveOk()myrepl:SECONDARY> db = conn.getDB("mydb")mydb
myrepl:SECONDARY> db.auth("test","test")1myrepl:SECONDARY> db.testHello.find()myrepl:SECONDARY>

4分钟之后,再进入延迟节点查看,发现数据同步了

myrepl:SECONDARY> db.testHello.find(){ "_id" : ObjectId("5a9e93f9bff707d8f99916fe"), "name" : "hello", "pwd" : "world" }

仲裁节点

现在副本集的组成为1个主节点+1个延迟节点+1个隐藏节点。现在将隐藏节点删除,再以添加仲裁节点的方式将此节点重新添加回来

myrepl:PRIMARY> rs.remove("127.0.0.1:27018"){
        "ok" : 1,
        /............}myrepl:PRIMARY> rs.addArb("127.0.0.1:27018"){
        "ok" : 1,
        //..............
        }}myrepl:PRIMARY> rs.config(){
        "_id" : "myrepl",
        "version" : 14,
        "protocolVersion" : NumberLong(1),
        "members" : [
                {
                        "_id" : 0,
                        "host" : "127.0.0.1:27017",
                        //......
                },
                {
                        "_id" : 2,
                        "host" : "127.0.0.1:27019",
                        //......
                },
                {
                        "_id" : 3,
                        "host" : "127.0.0.1:27018",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],
        //.................}



作者:panmingjie
链接:https://www.jianshu.com/p/b5a7d13e1391
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


小凡仔
3楼 · 2021-01-21 10:33

后期mongodb开发了个新的架构方案副本集,所以呢,目前已经淘汰master-slave的架构 改为可副本集,这种模式有一个主(primary),和多个从(secondary),只读,给他们设置权重,当主宕掉后,权重最高的从切换为主。其他从会自动识别新的主
在次架构还可以建立一个仲裁(arbiter)的角色,它只负责裁决,而不存储数据,它清楚的告诉是否有问题,防止脑裂问题
在此架构中读写数据都是在主上,如果想实现负载均衡的目的需要手动指定读库的目标server
副本集搭建:
我有三台机器分别是192.168.191.21 192.168.191.22 192.168.191.23 其中21为主 22 23为从
1,首先三台机器分别安装mongodb
参照我之前安装mongodb的方法
cd /etc/yum.repos.d
vim mongodb-org-3.4.repo
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc
yum install -y mongodb-org
2,三台机器编辑配置文件
vim /etc/mongod.conf
找到replication 删除# 然后在replication下面 写上如下俩行 记得前面有俩个空格
replication
oplogSizeMB: 20 //类似mysql binlog 20M
replSetName: sonice //副本集的名称
找到bindIp后面的127.0.0.1加上本机的内网ip 21,22,23
3,分别重启三台机器
systemctl restart mongod
4,连接主,在主上运行命令mongo
use admin
config={_id:”sonice”,members:[{_id:0,host:”192.168.191.21:27017″},{_id:1,host:”192.168.191.22:27017″},{id:2,host:”192.168.191.23:27017″}]}
// 其中sonice为副本集的名称 ,id为0的 是 主 其他id为1和2的是从
5,初始化
rs.initiate(config) //返回ok:1为正确
配置完之后 使用rs.status() 查看副本集的状态
如果俩个从上的状态为”stateStr”:”STARTUP”,则重新配置一遍即可
再次使用rs.status() 会发现从的状态变为SECONDARY 主的状态为STARTUP
mongodb的权重设置
使用rs.config 查看三台机器的priority 权重都是 1
更改他们的权重 ,设置一个变量 用索引的方式 来设置权重
首先进入主的mongo里面 执行下面5行操作
cfg = rs.config()
cfg.members[0].priority = 3
cfg.members[0].priority = 3
cfg.members[0].priority = 3
rs.reconfig(cfg)
这样设置下来 用rc.status() 可以看到21的主上机器权重为3 22的权重为2 23的权重为1

这样 当21宕了 会优先跳到22上 , 当21恢复后又跳回21为主了


相关问题推荐

  • 回答 3

    换行。比如,print hello\nworld效果就是helloworld\n就是一个换行符。\是转义的意思,&#39;\n&#39;是换行,&#39;\t&#39;是tab,&#39;\\&#39;是,\ 是在编写程序中句子太长百,人为换行后加上\但print出来是一整行。...

  • 回答 42

    十种常见排序算法一般分为以下几种:(1)非线性时间比较类排序:a. 交换类排序(快速排序、冒泡排序)b. 插入类排序(简单插入排序、希尔排序)c. 选择类排序(简单选择排序、堆排序)d. 归并排序(二路归并排序、多路归并排序)(2)线性时间非比较类排序:...

  • 回答 70
    已采纳

    前景很好,中国正在产业升级,工业机器人和人工智能方面都会是强烈的热点,而且正好是在3~5年以后的时间。难度,肯定高,要求你有创新的思维能力,高数中的微积分、数列等等必须得非常好,软件编程(基础的应用最广泛的语言:C/C++)必须得很好,微电子(数字电...

  • 回答 28

    迭代器与生成器的区别:(1)生成器:生成器本质上就是一个函数,它记住了上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。而且记录了程序执行的上下文。生成器不仅记住了它的数据状态,生成器还记住了程序...

  • 回答 9

    python中title( )属于python中字符串函数,返回’标题化‘的字符串,就是单词的开头为大写,其余为小写

  • 回答 6

    第一种解释:代码中的cnt是count的简称,一种电脑计算机内部的数学函数的名字,在Excel办公软件中计算参数列表中的数字项的个数;在数据库( sq| server或者access )中可以用来统计符合条件的数据条数。函数COUNT在计数时,将把数值型的数字计算进去;但是...

  • 回答 1

    head是方法,所以需要取小括号,即dataset.head()显示的则是前5行。data[:, :-1]和data[:, -1]。另外,如果想通过位置取数据,请使用iloc,即dataset.iloc[:, :-1]和dataset.iloc[:, -1],前者表示的是取所有行,但不包括最后一列的数据,结果是个DataFrame。...

  • Python入门简单吗2021-09-23 13:21
    回答 45

    挺简单的,其实课程内容没有我们想象的那么难、像我之前同学,完全零基础,培训了半年,直接出来就工作了,人家还在北京大公司上班,一个月15k,实力老厉害了

  • 回答 4

    Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来说的,后面学习到包package时,将会介绍),这些内建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Pyt...

  • 回答 8

     相当于 ... 这里不是注释

  • 回答 4

    还有FIXME

  • 回答 3

    python的两个库:xlrd和xlutils。 xlrd打开excel,但是打开的excel并不能直接写入数据,需要用xlutils主要是复制一份出来,实现后续的写入功能。

  • 回答 8

    单行注释:Python中的单行注释一般是以#开头的,#右边的文字都会被当做解释说明的内容,不会被当做执行的程序。为了保证代码的可读性,一般会在#后面加一两个空格然后在编写解释内容。示例:#  单行注释print(hello world)注释可以放在代码上面也可以放在代...

  • 回答 2

    主要是按行读取,然后就是写出判断逻辑来勘测行是否为注视行,空行,编码行其他的:import linecachefile=open(&#39;3_2.txt&#39;,&#39;r&#39;)linecount=len(file.readlines())linecache.getline(&#39;3_2.txt&#39;,linecount)这样做的过程中发现一个问题,...

  • 回答 4

    或许是里面有没被注释的代码

  • 回答 26

    自学的话要看个人情况,可以先在B站找一下视频看一下

没有解决我的问题,去提问