当前位置: 首页 > news >正文

【最后203篇系列】033 Mongo副本集修复过程

今天又经历了一次修复Mongo副本集的过程,我觉得得写下来。

大约在3年前搭建了Mongo集群(Mongo5),然后我使用ip代理的方式让集群的机器可以公网访问。ip代理机器一般只能租3年,所以到期就会更换,此时就会出现问题:集群的机器不能通信,访问失败

首先,肯定是要登录到终端。

docker exec -it Mongo_Rep_Container
use admin
db.auth("user","password")

在查询db.isMaster()大概会是这样的: Does not have a valid replica set config

{"topologyVersion" : {"processId" : ObjectId("68a282f5dd03af7c246cded7"),"counter" : NumberLong(1)},"ismaster" : false,"secondary" : false,"info" : "Does not have a valid replica set config",
...
}

此时整个集群已经属于不可用状态, node1, node2和node3都已经失联了。

Step1 将某个节点升级为PRIMARY

此时,先选一个节点重新初始化集群,副本集已经初始化过,所以直接 rs.initiate() 会报 “AlreadyInitialized”

rs.initiate({_id : "xxx",members: [{ _id : 0, host : "YOURIP:THE_PORT",priority:1 }]})

强制执行又会报一个错,这是因为如果节点存在过,即使重新初始化也不可以改变NodeID

mymeta:SECONDARY> rs.reconfig(cfg, {force: true})
{"ok" : 0,"errmsg" : "New and old configurations both have members with host of IP:PORT but in the new configuration the _id field is MemberId(0) and in the old configuration it is MemberId(12) for replica set mymeta","code" : 103,"codeName" : "NewReplicaSetConfigurationIncompatible"
}

保持NodeID不变,重新强制初始化

cfg = rs.conf()
cfg.members = [{_id: 12,                 // 保持原来的 _idhost: "IP:PORT",priority: 1,votes: 1}
]rs.reconfig(cfg, {force:true})

此时节点会完成变化,正式转为PRIMARY节点

rs.status()
{"set" : "REPLICA NAME",
...},"members" : [{"_id" : 12,"name" : "IP:PORT","health" : 1,"state" : 1,"stateStr" : "PRIMARY",mymeta:PRIMARY>

Step2 将其他节点加入

我之前的三个节点,其中一个已经重新成为主节点,且网络中只有一个节点。一个节点被我弄坏了(被大模型骗的),另一个除了失联,别的没问题。

处理弄坏的节点

先把对应的数据部分删除(/data/...replica)

重新初始化项目:在opt下方配置和秘钥,在data下放文件夹

# 1 在data目录创建文件夹proc_path=/opt/MongoReplica/
data_path=/data/MongoReplica/sh ${proc_path}/create_shard_folder.sh ${data_path}/replica# 修改秘钥文件
chown 999 ${proc_path}replica/mongo.key
chmod 600 ${proc_path}replica/mongo.key

其中create_shard_folder.sh的目的是创建副本文件夹并修改权限。

#!bin/bashmkdir -p $1mkdir $1/dbmkdir $1/logtouch $1/log/mongod.logchmod -R 777 $1

启动容器

image_name="MONGOIMAGE"
port=PORTdocker run -d \--restart=always \--name='CONTAINERNAME' \-v /etc/localtime:/etc/localtime  \-v /etc/timezone:/etc/timezone\-e "LANG=C.UTF-8"\-m 2g \-v ${proc_path}replica/mongo.key:/etc/mongo.key \-v ${data_path}/replica:/home/mongod \-v ${proc_path}replica/mongod.conf:/etc/mongod.conf \-p ${port}:27017 \${image_name} \-f /etc/mongod.conf

在PRIMARY节点执行:

rs.add("IP:PORT2")
rs.status()"_id" : 13,"name" : "IP:PORT2","health" : 1,"state" : 5,"stateStr" : "STARTUP2",
...

到这里"stateStr" : "STARTUP2",节点已经在同步数据了

处理没坏的节点

这个过程很顺利,并没有发生问题。当然最坏的情况也就是重新同步一次。

日志问题

因为集群是依靠oplog来进行同步的,这个日志会随着时间越来越大。一些所谓的控制方法我都试过,似乎不太灵光。然后之前我做好过轮转日志,但是只会轮转主节点,不会作用在从节点,这就比较麻烦。
毕竟如果集群搭建起来,总不能隔三差五的去删节点,加节点吧。

这次也解决了这个问题:主节点用Rotate,从节点用SIGUSR1

SIGUSR1 是什么
SIGUSR1 是 Unix/Linux 系统里的一个 用户自定义信号(Signal)
MongoDB 对这个信号有特殊处理:
当 mongod 进程收到 SIGUSR1 时,会 安全地关闭当前日志文件并重新打开日志
不会影响数据库的读写,也不会触发重启
换句话说,这是 MongoDB 官方推荐的 日志轮转方式,尤其适合 Secondary 或通过 Docker 启动的节点。

直接执行命令可以测试

副本日志清理
docker exec -it CONTAINER pgrep mongod // 一般是1
docker exec -it CONTAINER kill -USR1 1

考虑到是低频操作,而且节点可能会随着选举变化

import subprocess
import pymongo# -------------------------------
# 配置
# -------------------------------
container_name = "CONTAINER"
mongo_host = "127.0.0.1"
mongo_port = PORT
mongo_user = "fff"
mongo_pwd = "ff"
auth_db = "admin"# -------------------------------
# 1️⃣ 连接 MongoDB
# -------------------------------
client = pymongo.MongoClient(host=mongo_host,port=mongo_port,username=mongo_user,password=mongo_pwd,authSource=auth_db,authMechanism='SCRAM-SHA-1'
)db = client['admin']# -------------------------------
# 2️⃣ 判断是否主节点
# -------------------------------
ismaster = db.command("isMaster")
if ismaster.get("ismaster", False):# 主节点,用 logRotate 命令db.command({'logRotate': 1})print("Primary 节点日志轮转完成")
else:# 从节点,用 SIGUSR1# 找 PIDpid_cmd = f"docker exec -i {container_name} pgrep mongod"pid = subprocess.check_output(pid_cmd, shell=True).decode().strip()kill_cmd = f"docker exec -i {container_name} kill -USR1 {pid}"subprocess.run(kill_cmd, shell=True)print(f"Secondary 节点日志轮转完成,发送 SIGUSR1 给 PID {pid}")

然后日志可以被轮转,另外再写一个简单的sh脚本,把对应目录下包含日期的文件取出来,然后再删除。
clear_mongo_rep.sh

#!/bin/bash
LOG_DIR="/data/aprojects/MongoReplica/replica/log"# 删除所有带日期的日志文件(只保留 mongod.log)
find "$LOG_DIR" -type f -name "mongod.log.2*" -deleteecho "✅ 已清理所有历史日志文件"

Mongo5集群作为一个基础部件,以后应该也不太改了。以后有需要还可以搭建Mongo8集群。

http://www.dtcms.com/a/338220.html

相关文章:

  • Maven resources资源配置详解
  • 小程序被爬虫攻击,使用waf能防护吗?
  • Vision Master的C#脚本与opencv联合编程
  • 【opencv-Python学习笔记(7):图像平滑处理】
  • 【图像算法 - 17】慧眼识“果”:基于深度学习与OpenCV的苹果智能检测系统(附完整代码)
  • sqli-labs通关笔记-第54关 GET字符型注入(单引号闭合 限制10次探测机会)
  • 英特尔公司Darren Pulsipher 博士:以架构之力推动政府数字化转型
  • 【leetcode】392. 判断子序列
  • 【yocto】为什么要选择yocto?
  • leetcode4_452 and 763
  • 力扣热题100------19.删除链表的倒数第N个结点
  • 【MongoDB与Python:数据库操作入门教程】
  • 力扣hot100:移动零问题的巧妙解决:双指针与原地交换策略(283)
  • ETL中统一调度的方式
  • Vue深入组件:组件事件详解1
  • 如何使用 React 101 的 Highcharts 包装器
  • 【网络安全实验报告】实验七:简单的防火墙搭建实验
  • css word-pass
  • 数据转换细节揭秘:ETL如何精准映射复杂业务逻辑
  • 专题:2025AI技术应用与发展报告|附600+份报告PDF、数据仪表盘汇总下载
  • 前端处理导出PDF。Vue导出pdf
  • GPT-5博士级AI使用教程及国内平替方案
  • 活到老学到老之vue-vben-admin项目安装
  • WordPress (LNMP 架构) 一键部署 Playbook
  • django+Vue3实现前后端分离式实时聊天室
  • Java面试考点
  • ​Kali Linux 环境中的系统配置文件与用户配置文件大全
  • MySQL 自增主键满了咋办?
  • PowerBI CrossFilter解决关联关系过滤传播问题
  • 对象存储 COS 端到端质量系列 —— 终端网络诊断工具