mongodb副本集管理

一.local系统库

1.1 local本地库介绍

  • local库存储replication进程的信息和本地数据,记录着是时间戳,索引以及复制等信息
  • local库里面的内容是不能复制的
rs1:PRIMARY> use local
switched to db local

rs1:PRIMARY> show tables
oplog.rs 			//记录所有操作,mongodb就是通过oplog.rs实现数据同步的
replset.election	//副本集选择信息
replset.minvalid	//保存数据库最新操作的时间戳
replset.oplogTruncateAfterPoint 
startup_log			//记录mongod每次的启动信息
system.indexs 		//记录当前库的所有索引信息
system.replset		//记录主从配置信息,不能直接修改该集合,必须通过rs.initiate()来初始化,rs.reconfig()来重新配置

1.2 关于oplogTruncateAfterPoint

  • 4.2及以前版本中,oplogTruncateAfterPoint只用于备库,用来保证oplog batch应用的原子性,最终目的是确保主备数据的一致性。
  • 4.4中,主库也会维护oplogTruncateAfterPoint,主要是和oplog hole相关
  • oplog hole是因为事务在WiredTiger层面的提交顺序和oplog顺序不一致导致,复制时如果要保证主备一致性需要避开这个hole
rs1:PRIMARY> db.replset.oplogTruncateAfterPoint.find()
{ "_id" : "oplogTruncateAfterPoint", "oplogTruncateAfterPoint" : Timestamp(0, 0) }

1.3 关于system.replset

rs1:PRIMARY> db.system.replset.find()
{ "_id" : "rs1", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "172.16.0.103:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {  }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "172.16.0.104:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : {  }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "172.16.0.105:27017", "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("61efafe1f9b107af5deb6af5") } }
  • arbiterOnly:表示该成员为仲裁者
  • buildIndexes:表示实在在成员上创建索引,该属性不能修改,只能在增加成员时设置属性
  • hidden:将成员配置为隐藏成员,priority需要设置为0。client不会向隐藏成员发送请求,因此成员不会收到client的request
  • priority:优先级,默认是1,取值范围0~100,为0的节点永远不能成为primary节点
  • slaveDelay:将Secondary 成员配置为延迟备份节点,要求Priority 为0,表示该成员比Primary 成员滞后指定的时间,才能将Primary上进行的写操作同步到本地。
  • votes:0或1,表示有权限参与选举

1.4 关于的oplog

  • oplog:存储replica set的写操作,记录信息存储在local数据库中的oplog.rs的集合中。oplog.rs是一个固定长度的capped collection。
  • oplog日志默认情况下是比较大的,可达到5%的磁盘空间,可通过参数--oplogSize来设置大小
  • 修改oplogSize需要重启服务,而在为大型的oplog预分配空间非常消耗时间,且可能导致主节点停机时间增加,所以尽可能手动预分配数据文件。
  • 修改oplogSize重启主节点之后,所有从节点需要使用–autoresync重启,否则需要手动重新同步
// 查看master的oplog元数据信息
db.printReplicationInfo()
configured oplog size:   990MB
log length start to end: 3073secs (0.85hrs)
oplog first event time:  Tue Jan 25 2022 16:08:01 GMT+0800 (CST)
oplog last event time:   Tue Jan 25 2022 16:59:14 GMT+0800 (CST)
now:                     Tue Jan 25 2022 16:59:23 GMT+0800 (CST)
printReplicationInfo字段含义说明:
  • configured oplog size:配置的oplog文件大小
  • log length start to end:oplog日志的启用时间短
  • oplog first event time:第一个事务日志的产生时间
  • oplog last event time:最后一个事务日志的产生时间
  • now:现在的时间
// 查看oplog的信息,oplog.rs系统集合只用于复制,不能创建索引,查询语句会比较慢
db.oplog.rs.findOne()
{
        "ts" : Timestamp(1643098081, 1),
        "h" : NumberLong("-5182796776932811184"),
        "v" : 2,
        "op" : "n",
        "ns" : "",
        "wall" : ISODate("2022-01-25T08:08:01.364Z"),
        "o" : {
                "msg" : "initiating set"
        }
}

// 查询1小时内的oplog
var now = Math.floor((new Date().getTime())/1000)
db.oplog.rs.find({"ts":{"$lt":Timestamp(now,1),"$gt":Timestamp(now-3600,1)}})

// 查询指定时间段(时间UTC)
var start_time = Math.floor(ISODate("2022-01-26T10:00:00.000Z").getTime()/1000)
var end_time = Math.floor(ISODate("2022-01-26T10:30:00.000Z").getTime()/1000)
db.oplog.rs.find({"ts":{"$lt":Timestamp(start_time,1),"$gt":Timestamp(end_time,1)}})

// 统计各个集合的insert操作
db.oplog.rs.aggregate([{$match:{"op":"i"}},{$group:{_id:"$ns",count:{$sum:1}}}])
{ "_id" : "test.blog", "count" : 1 }
{ "_id" : "admin.system.keys", "count" : 2 }
{ "_id" : "config.system.sessions", "count" : 9 }
{ "_id" : "admin.system.version", "count" : 1 }
{ "_id" : "admin.system.users", "count" : 2 }
oplog记录字段含义:
  • ts:某个操作的时间戳,在选举时,会选择max(ts)的那个secondary作为新的primary
  • op:操作类型(i:insert,d:delete,u:update,c:db cmd,db:声明当前数据库,n:空操作)
  • ns:操作所在的namespace
  • o:当前操作的内容
  • o2:在执行更新操作时的条件,仅限于update才有该属性

二.副本集primary和secondary基本信息查询

// 查看副本集状态
rs.status()

// 查看副本集配置信息
rs.conf()

// 查看是否是主节点
rs.isMaster()

// 查看slave的同步状态
db.printSlaveReplicationInfo()

// printSlaveReplicationInfo输出信息字段含义说明:
- source:从库的IP及端口
- syncedTo:目前的同步情况,延时了多久等信息

三、节点管理

3.1 开启从库客户模式才能读,secondary默认是不可读

rs1:SECONDARY> db.blog.find()
Error: error: {
        "operationTime" : Timestamp(1643102404, 1),
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotMasterNoSlaveOk",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1643102404, 1),
                "signature" : {
                        "hash" : BinData(0,"9PcQVaACwkxAYyp0Z+dd7YJBYY0="),
                        "keyId" : NumberLong("7057052573554966530")
                }
        }
}

// 在从库上执行,开启从库可读模式,默认secondary是不可读的
rs1:SECONDARY>db.getMongo().setSlaveOk()

rs1:SECONDARY> db.blog.find()
{ "_id" : ObjectId("61efbd0c91b49e592d29811c"), "title" : "My First Post", "content" : "hello word!", "date" : ISODate("2022-01-25T09:03:48.287Z") }

3.2 添加节点

增加方式:
  • 方法1:通过oplog来增加节点
  • 方法2:通过数据库快照(--fastsync)和oplog来增加节点
方法1优缺点:
  • oplog直接进行增加节点操作,简单且无需人工过多干预,但是由于oplog是capped collection,采用的是循环方式进行日志处理。所以采用oplog方式进行增加节点,有可能导致数据的不一致。
方法1添加步骤:

1)配置并启动新节点

## 创建新节点数据目录
mkdir -p /data/mongodb/data2

## 配置新节点配置文件
vi mongodb2.conf
dbpath=/data/mongodb/data2/
logpath=/data/mongodb/logs/mongodb2.log
bind_ip=172.16.0.103
port=28017
fork=true
journal=true
logappend=true
replSet=rs1
keyFile=/data/mongodb/key/mongodb-keyfile
auth=true

## 启动新节点
/usr/local/mongodb4/bin/mongod -f /data/mongodb/config/mongodb2.conf --fork

## 开启防火墙
firewall-cmd --zone=public --add-port=28017/tcp --permanent
firewall-cmd --reload

2)将新节点加入副本集(主节点上执行)

rs1:PRIMARY> rs.add("172.16.0.103:28017")
{
        "ok" : 1,
        "operationTime" : Timestamp(1643175863, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1643175863, 1),
                "signature" : {
                        "hash" : BinData(0,"T3yN+Cjh0odz7XqNvGysBkrdFRE="),
                        "keyId" : NumberLong("7057052573554966530")
                }
        }
}

3)查看进行初始化和数据同步信息

rs.status()

4)同步完成后,验证数据信息

// secondary上执行
rs.slaveOk()

use test

db.blog.findOne()
{
        "_id" : ObjectId("61efbd0c91b49e592d29811c"),
        "title" : "My First Post",
        "content" : "hello word!",
        "date" : ISODate("2022-01-25T09:03:48.287Z")
}
方法2添加节点
  • 可以避免数据不一致
方法2添加节点步骤

1)拷贝某成员的物理文件作为初始化数据

cp -r /data/mongodb/data/ /data/mongodb/data2

2)配置节点信息

## 拷贝某节点的配置文件
cp /data/mongodb/config/mongodb.conf /data/mongodb/config/mongodb2.conf

## 修改对应的路径和端口等信息
vi mongodb2.conf
dbpath=/data/mongodb/data2/
logpath=/data/mongodb/logs/mongodb2.log
bind_ip=172.16.0.105
port=28017
fork=true
journal=true
auth=true
replSet=rs1
logappend=true
keyFile=/data/mongodb/key/mongodb-keyfile

2)在主节点上,插入一条测试数据进行标记,用于最后验证次更新是否正常同步
rs1:PRIMARY> use test
switched to db test

rs1:PRIMARY> db.test.insert({info:"test"})
WriteResult({ "nInserted" : 1 })

3)启动新节点服务

## 开通端口防火墙
firewall-cmd --zone=public --add-port=28017/tcp --permanent
firewall-cmd --reload

## 启动服务
/usr/local/mongodb4/bin/mongod -f /data/mongodb/config/mongodb2.conf --fork

4)将新节点加入副本集

rs1:PRIMARY> rs.add("172.16.0.105:28017")
{
        "ok" : 1,
        "operationTime" : Timestamp(1643176797, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1643176797, 1),
                "signature" : {
                        "hash" : BinData(0,"nzUgoOvbcftL+hQRh31kR6OhiS0="),
                        "keyId" : NumberLong("7057052573554966530")
                }
        }
}

// 查看副本集信息
rs.status()

5)检验数据是否正常同步

rs1:SECONDARY> use test
switched to db test

rs1:SECONDARY> rs.slaveOk()

rs1:SECONDARY> db.test.find()
{ "_id" : ObjectId("61f0e2ca408edb6607456e81"), "info" : "test" }

3.3 删除节点
1)直接remove

rs1:PRIMARY> rs.remove("172.16.0.103:28018")
{
        "ok" : 1,
        "operationTime" : Timestamp(1643175909, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1643175909, 1),
                "signature" : {
                        "hash" : BinData(0,"dHhka82X5TSVD7juBbhHCqUgpxk="),
                        "keyId" : NumberLong("7057052573554966530")
                }
        }
}

2)通过数组处理对象方法

  • 执行rs.reconfig()不一定会造成副本集的重新选举,添加force参数同样如此
cfg = rs.conf()
// splice(数组下表,删除个数)
// 从下标2的节点开始,删除1个节点配置
cfg.members.splice(2,1)
rs.reconfig(cfg)

3.4替换副本集成员

cfg = rs.conf()
cfg.members[5].host = "172.16.0.103"
rs.reconfig(cfg)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值