记录一次MongoDB故障恢复

最近忙的不行,事都赶在一起了,下午正打算写代码,组内同事来一句新搭建的MongoDB复制集(版本4.2.5)有个节点挂了,让我看看,奈何没有专业运维,只能自己上手(真就全干工程师😤)。实话说,从用MongoDB开始,这是第一次遇到故障,处理流程也是野路子,本文只对我遇到的情况进行记录,并非专业的解决方案,处理方式也可能并非正确。

第一个问题

其实说是一次故障,但是我觉得是两个问题,先看第一个,同事告诉我节点挂了,SSH登录进去查看了下服务状态,确定服务掉了,就去查日志,在里面看到类似这样的报错(到家复盘,只记得关键字了):

file:WiredTiger.wt, connection: read checksum error for 4096B block at offset 12288: block header checksum of 1955562709 doesn’t match expected checksum of 3146787951

看到WiredTigerdoesn't match expected checksum的时候,心里一凉,因为引擎报错,不是好现象…

对报错信息进行了检索,发现了一些类似问题,给出的解决方案基本都是通过repair模式启动MongoDB,让mongod会尽可能的尝试自己去修复数据的不一致状态,修复过程中尽可能多的保留有效的数据。但这篇文章中,给出了五种解决方案:MongoDB无法启动,如何恢复数据?

先通过repair尝试恢复,命令如下:

1
mongod --repair --dbpath /path/to/data/db

但是使用该命令的时候需要注意执行用户的问题,正常情况下dbpath的group、user都是mongodb才对。如果出现问题,需要利用chown将指定文件的拥有者改为指定的group、user。

1
chown -R mongodb:mongodb dbpath

按上面提到的文章中所说,存储元数据的数据文件没损坏,执行repair后,可以看到类似下面的内容:

1
2
3
4
5
6
7
[initandlisten] finished checking dbs
[initandlisten] WiredTigerKVEngine shutting down
[initandlisten] Shutting down session sweeper thread
[initandlisten] Finished shutting down session sweeper thread
[initandlisten] shutdown: removing fs lock...
[initandlisten] now exiting
[initandlisten] shutting down with code:0

第二个问题

repair执行完毕以后,重启MongoDB,仍然无法启动,在log中有提示:

This instance has been repaired and may contain modified replicated data that would not match other replica set members. To see your repaired data, start mongod without the –replSet option. data and would like to perform a complete re-sync, please refer to the documentation here: https://docs.mongodb.com/manual/tutorial/resync-replica-set-member/

journalctl -xe中的信息显示Unit mongod.service not found.再次检索相关的报错后,检查了/etc/mongodb.conf文件和/systemd/system/相关目录下的mongod.service文件,发现都是正常的,但就是无法正常启动。

技术水平不够,实属无奈情况下,根据上面日志的内容,决定将故障节点进行重置。出现故障的节点当时处于Secondary节点状态,就先去Primary节点中进行配置,将故障节点的优先级降为0,使其只能投票,但无法成为Primary节点。

开始完全卸载故障节点中的MongoDB:

1
2
3
yum erase $(rpm -qa | grep mongodb-org)
rm -r /var/log/mongodb
rm -r /var/lib/mongo

重新安装MongoDB:

1
yum install -y mongodb-org

要说为撒卸载重装,那就一个答案: 强迫症,这样可能也最省事。

配置修改/etc/mongodb.conf文件以后,此时启动MongoDB正常,用命令行进入,可以看到处于STARTUP2状态,代表该成员已加入集合,并正在运行初始同步,有资格投票。

等待一段以后,状态从STARTUP2切换到Secondary

当然如果数据量过大,可以采用拷贝其他节点数据文件的方式来解决,我这里采用rsync进行差异同步:

1
$ rsync -avz --delete user@ip:/var/lib/mongo/ /var/lib/mongo/

其中rsync的选项含义:

  • a: 递归方式传输文件,并保持文件属性
  • v: 详细输出模式
  • z: 传输之前对文件进行压缩处理
  • delete: 在同步文件的时候删除多余的文件

如果拷贝时间长的话,建议多次同步结束后再重新启动服务。

一些知识点

1、第一次遇到STARTUP2这种状态,才知道复制集成员状态有10种:
https://docs.mongodb.com/manual/reference/replica-states/

2、复制集延迟原因:
https://docs.mongodb.com/manual/tutorial/troubleshoot-replica-sets/#replication-lag-causes

3、重新同步复制集成员:
https://docs.mongodb.com/manual/tutorial/resync-replica-set-member/
里面提到两种方式:

  • 使用Initial Sync, 让mongo自动从0开始,重新同步所有数据
  • 使用磁盘快照

但是最新的数据肯定是Primary节点,而Primary节点一直有数据在进入,这里有一篇文章提到了resync的坑,可以看看: Devops必须留意的Mongo副本集Resync的坑

结束

到这里也算是故障解决了吧,但是出现故障的原因还没搞清楚,着急恢复数据,日志也没留下,想起来已经晚了😶

参考

1、https://stackoverflow.com/questions/42648009/error-while-recovering-a-wiredtiger-collection-from-a-corrupt-mongodb-installati
2、https://jira.mongodb.org/browse/SERVER-37309
3、https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-repair
4、https://docs.mongodb.com/manual/tutorial/restore-replica-set-from-backup/

0%