一、安装前准备

  1. 系统要求

    • CentOS 7 64位系统
    • 至少 2GB RAM
    • 确保网络通畅
  2. 关闭SELinux

    setenforce 0
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
  3. 配置防火墙

    firewall-cmd --zone=public --add-port=27017/tcp --permanent
    firewall-cmd --reload
  4. 修改透明大页

    echo never > /sys/kernel/mm/transparent_hugepage/enabled
    echo never > /sys/kernel/mm/transparent_hugepage/defrag

    永久关闭:

    vim /etc/systemd/system/disable-transparent-huge-pages.service

    添加以下内容:

    [Unit]
    Description=Disable Transparent Huge Pages
    [Service]
    Type=oneshot
    ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled && echo never > /sys/kernel/mm/transparent_hugepage/defrag'
    RemainAfterExit=yes
    [Install]
    WantedBy=multi-user.target

二、安装MongoDB 4.2.7

  1. 创建MongoDB仓库文件

    vi /etc/yum.repos.d/mongodb-org-4.2.repo

    添加以下内容:

    [mongodb-org-4.2]
    name=MongoDB Repository
    baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86_64/
    gpgcheck=1
    enabled=1
    gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc
  2. 安装MongoDB

    yum install -y mongodb-org-4.2.7 mongodb-org-server-4.2.7 mongodb-org-shell-4.2.7 mongodb-org-mongos-4.2.7 mongodb-org-tools-4.2.7
  3. 固定MongoDB版本
    防止意外升级:

    echo "exclude=mongodb-org,mongodb-org-server,mongodb-org-shell,mongodb-org-mongos,mongodb-org-tools" >> /etc/yum.conf

三、配置MongoDB

  1. 修改配置文件

    vi /etc/mongod.conf

    主要配置项:

    systemLog:
      destination: file
      path: /var/log/mongodb/mongod.log
      logAppend: true
    storage:
      dbPath: /var/lib/mongo
      journal:
        enabled: true
      engine: wiredTiger
      wiredTiger:
        engineConfig:
          cacheSizeGB: 2
    net:
      port: 27017
      bindIp: 0.0.0.0  # 允许所有IP访问,生产环境建议指定具体IP
    security:
      authorization: enabled
    processManagement:
      fork: true
      pidFilePath: /var/run/mongodb/mongod.pid
      timeZoneInfo: /usr/share/zoneinfo

    确认系统生成的服务文件,一定要保障pidfile与配置文件中一致:

    vim /usr/lib/systemd/system/mongod.service

    服务文件内容:

    [Unit]
    Description=MongoDB Database Server
    Documentation=https://docs.mongodb.org/manual
    After=network.target
    
    [Service]
    User=mongod
    Group=mongod
    Environment="OPTIONS=-f /etc/mongod.conf"
    EnvironmentFile=-/etc/sysconfig/mongod
    ExecStart=/usr/bin/mongod $OPTIONS
    ExecStartPre=/usr/bin/mkdir -p /var/run/mongodb
    ExecStartPre=/usr/bin/chown mongod:mongod /var/run/mongodb
    ExecStartPre=/usr/bin/chmod 0755 /var/run/mongodb
    PermissionsStartOnly=true
    PIDFile=/var/run/mongodb/mongod.pid
    Type=forking
    # file size
    LimitFSIZE=infinity
    # cpu time
    LimitCPU=infinity
    # virtual memory size
    LimitAS=infinity
    # open files
    LimitNOFILE=64000
    # processes/threads
    LimitNPROC=64000
    # locked memory
    LimitMEMLOCK=infinity
    # total threads (user+kernel)
    TasksMax=infinity
    TasksAccounting=false
    # Recommended limits for for mongod as specified in
    # http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings
    
    [Install]
    WantedBy=multi-user.target
  2. 创建数据目录和日志目录

    mkdir -p /var/lib/mongo
    mkdir -p /var/log/mongodb
    chown -R mongod:mongod /var/lib/mongo
    chown -R mongod:mongod /var/log/mongodb

四、启动MongoDB服务

  1. 启动服务

    systemctl start mongod

    遇到问题时的重新设置服务流程:

    # 1. 停止 MongoDB 服务
    sudo systemctl stop mongod
    
    # 2. 清理数据目录(因为之前的配置可能导致了数据文件的不一致)
    sudo rm -rf /var/lib/mongo/*
    
    # 3. 重新创建数据和日志目录,确保权限正确
    sudo mkdir -p /var/lib/mongo /var/log/mongodb
    sudo chown -R mongod:mongod /var/lib/mongo /var/log/mongodb
    sudo chmod 0755 /var/lib/mongo /var/log/mongodb
    
    # 4. 确保 pid 目录存在并且权限正确
    sudo mkdir -p /var/run/mongodb
    sudo chown mongod:mongod /var/run/mongodb
    
    # 5. 启动 MongoDB 服务
    sudo systemctl start mongod
    
    # 6. 检查服务状态
    sudo systemctl status mongod
  2. 设置开机自启

    systemctl enable mongod
  3. 检查服务状态

    systemctl status mongod
  4. 验证MongoDB连接

    mongo

    进入MongoDB shell后,执行db.version()查看版本是否为4.2.7。

  5. 创建账号密码
    首先进入 MongoDB shell:

    mongo

    创建用户步骤:

    1. 创建管理员用户

      // 切换到 admin 数据库
      use admin
      
      // 创建管理员账号
      db.createUser(
        {
          user: "sa",
          pwd: "xxxxxx",  // 请修改为安全的密码
          roles: [ 
            { role: "userAdminAnyDatabase", db: "admin" },
            { role: "readWriteAnyDatabase", db: "admin" },
            { role: "dbAdminAnyDatabase", db: "admin" },
            { role: "clusterAdmin", db: "admin" }
          ]
        }
      )
    2. 创建应用数据库用户

      // 切换到业务数据库(例如:myapp)
      use dhtcenter
      
      // 创建普通用户
      db.createUser(
        {
          user: "user_dht",
          pwd: "xxxxxx",  // 请修改为安全的密码
          roles: [
            { role: "readWrite", db: "dhtcenter" }
          ]
        }
      )
    3. 启用认证

      编辑 MongoDB 配置文件:

      vi /etc/mongod.conf

      确保配置文件包含:

      security:
        authorization: enabled
    4. 重启 MongoDB 服务

      systemctl restart mongod
    5. 验证用户认证

      # 管理员用户连接(认证到 admin 库)
      # 方法1:使用 -p 参数后不带密码(推荐,更安全)
      mongo -u "sa" -p --authenticationDatabase "admin"
      # 然后在提示时输入密码
      
      # 方法2:如果密码中包含特殊字符(如 !),使用单引号包裹密码
      mongo -u "sa" -p 'xxxxxx' --authenticationDatabase "admin"
      
      # 应用用户连接(认证到具体业务库)
      mongo -u "user_dht" -p --authenticationDatabase "dhtcenter"
      # 然后在提示时输入密码

    认证相关注意事项:

    1. 认证数据库指定

      • --authenticationDatabase 必须指定正确的认证库
      • 管理员用户通常在 admin
      • 普通用户在其创建时指定的数据库
    2. 角色说明

      • userAdminAnyDatabase: 用户管理权限
      • readWriteAnyDatabase: 读写所有数据库权限
      • dbAdminAnyDatabase: 数据库管理权限
      • clusterAdmin: 集群管理权限
      • readWrite: 特定数据库的读写权限
      • read: 特定数据库的只读权限
    3. 连接字符串格式

      mongodb://username:password@hostname:27017/database?authSource=authdb
      • username: 用户名
      • password: 密码
      • database: 要连接的数据库
      • authSource: 认证库名称
    4. 安全建议

      • 密码要包含大小写字母、数字和特殊字符
      • 定期更换密码
      • 不同应用使用不同的账号
      • 遵循最小权限原则
      • 生产环境中删除或禁用不使用的账号

五、备份方法

  1. 配置MongoDB启用 oplog
    确保/etc/mongod.conf中包含以下配置:

    replication:
      replSetName: rs0

    重启MongoDB服务:

    systemctl restart mongod
  2. 初始化副本集

    # 使用管理员账号连接
    mongo -u "sa" -p 'xxxxxx' --authenticationDatabase "admin"
    
    # 初始化副本集
    rs.initiate({
      _id: "rs0",
      members: [
        { _id: 0, host: "localhost:27017" }
      ]
    })
    
    # 查看副本集状态
    rs.status()
  3. 创建备份目录

    mkdir -p /data/mongodb/backup/
    chown -R mongod:mongod /data/mongodb/backup
  4. 编写备份脚本

    vim /usr/local/bin/mongodb_backup.sh
    #!/bin/bash
    
    # MongoDB备份脚本 - 适用于MongoDB 4.2.7
    # 功能:执行MongoDB备份,添加日志记录,忽略tar提示
    #
    # 注意:MongoDB 4.2.7不支持--oplogSince参数进行真正的增量备份
    # 本脚本使用--oplog参数捕获备份期间的操作日志,实现准实时备份
    # 每次备份都是全量备份+oplog,而非基于时间戳的增量备份
    #
    # 使用方法:
    # 1. 修改脚本中的备份目录和MongoDB连接信息
    # 2. 添加执行权限:chmod +x mongodb_backup.sh
    # 3. 手动执行:./mongodb_backup.sh
    # 4. 或添加到crontab定时执行
    
    # 备份目录
    BACKUP_DIR=/data/mongodb/backup
    
    # 日志目录
    LOG_DIR="$BACKUP_DIR/logs"
    mkdir -p "$LOG_DIR"
    
    # 当前时间
    TIMESTAMP=$(date +%Y%m%d%H%M%S)
    
    # 日志文件
    LOG_FILE="$LOG_DIR/backup_$TIMESTAMP.log"
    
    # 备份文件名 - 包含时间戳
    BACKUP_NAME=mongodb_backup_$TIMESTAMP
    
    # 上次备份的时间戳文件 - 仅用于记录
    LAST_TIMESTAMP_FILE=$BACKUP_DIR/last_timestamp.txt
    
    # 日志函数
    log_message() {
        local level=$1
        local message=$2
        local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
        echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
    }
    
    # 错误处理函数
    handle_error() {
        log_message "ERROR" "备份过程中发生错误,退出代码: $1"
        exit 1
    }
    
    # 设置错误捕获
    trap 'handle_error $?' ERR
    
    # 开始备份
    log_message "INFO" "开始MongoDB备份操作"
    
    # 创建备份目录
    log_message "INFO" "创建备份目录: $BACKUP_DIR/$BACKUP_NAME"
    mkdir -p $BACKUP_DIR/$BACKUP_NAME
    
    # 检查是否有上次备份的记录
    if [ -f $LAST_TIMESTAMP_FILE ]; then
        LAST_TIMESTAMP=$(cat $LAST_TIMESTAMP_FILE)
        log_message "INFO" "上次备份时间: $LAST_TIMESTAMP,执行新的全量备份+oplog"
    else
        log_message "INFO" "首次执行备份"
    fi
    
    # 执行MongoDB备份 (全量+oplog)
    log_message "INFO" "执行MongoDB全量备份并捕获oplog"
    mongodump --username "sa" --password "xxxxxx" --authenticationDatabase "admin" --out $BACKUP_DIR/$BACKUP_NAME --oplog
    if [ $? -ne 0 ]; then
        log_message "ERROR" "MongoDB备份失败"
        exit 1
    fi
    log_message "INFO" "MongoDB备份完成,包含全量数据和oplog"
    
    # 记录当前时间戳 - 使用MongoDB 4.2.7兼容的格式
    # 对于MongoDB 4.2.7,我们只记录时间戳用于日志和文件命名,不用于--oplogSince参数
    CURRENT_TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    log_message "INFO" "记录当前时间戳: $CURRENT_TIMESTAMP"
    echo $CURRENT_TIMESTAMP > $LAST_TIMESTAMP_FILE
    log_message "INFO" "注意:在MongoDB 4.2.7中,时间戳仅用于记录,不用于增量备份参数"
    
    # 压缩备份文件 - 忽略tar提示
    log_message "INFO" "压缩备份文件"
    tar -zcf $BACKUP_DIR/$BACKUP_NAME.tar.gz -C $BACKUP_DIR $(basename $BACKUP_NAME) 2>/dev/null
    if [ $? -ne 0 ]; then
        log_message "ERROR" "压缩备份文件失败"
        exit 1
    fi
    
    # 删除未压缩的备份目录
    log_message "INFO" "删除未压缩的备份目录"
    rm -rf $BACKUP_DIR/$BACKUP_NAME
    
    # 保留最近30天的增量备份
    log_message "INFO" "清理30天前的备份文件"
    find $BACKUP_DIR -name "*.tar.gz" -type f -mtime +30 -delete
    
    # 清理30天前的日志文件
    log_message "INFO" "清理30天前的日志文件"
    find $LOG_DIR -name "*.log" -type f -mtime +30 -delete
    
    log_message "INFO" "备份操作完成"
    
    # 显示备份结果摘要
    BACKUP_SIZE=$(du -sh "$BACKUP_DIR/$BACKUP_NAME.tar.gz" | cut -f1)
    log_message "INFO" "备份完成摘要:"
    log_message "INFO" "- 备份类型: 全量备份+oplog"
    log_message "INFO" "- 备份文件: $BACKUP_DIR/$BACKUP_NAME.tar.gz"
    log_message "INFO" "- 文件大小: $BACKUP_SIZE"
    log_message "INFO" "- 日志文件: $LOG_FILE"
    log_message "INFO" "- 备份时间: $(date)"
    log_message "INFO" "注意:此备份包含完整数据库和操作日志,可用于时间点恢复"
    
    exit 0
  5. 添加执行权限

    chmod +x /usr/local/bin/mongodb_backup.sh
  6. 设置定时任务

    crontab -e

    添加以下内容(每天凌晨2点执行备份):

    0 2 * * * /usr/local/bin/mongodb_backup.sh

六、备份恢复方法

  1. 解压备份文件

    # 创建临时恢复目录
    mkdir -p /tmp/mongodb_restore
    
    # 解压备份文件
    tar -zxf /data/mongodb/backup/mongodb_backup_YYYYMMDDHHMMSS.tar.gz -C /tmp/mongodb_restore
  2. 基本恢复(恢复到备份开始时的状态)

    # 恢复数据库
    mongorestore --username "sa" --password "xxxxxx" --authenticationDatabase "admin" /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS
    
    [root@mongo backup]# mongorestore --username "sa" --password 'xxxxxx' --a AuthenticationDatabase "admin" /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/
    2025-08-05T14:06:50.581+0800    preparing collections to restore from
    2025-08-05T14:06:50.582+0800    restoring to existing collection dhtcenter.1 without dropping
    2025-08-05T14:06:50.582+0800    reading metadata for dhtcenter.1 from /tmp/mongodb_restore/  mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.metadata.json
    2025-08-05T14:06:50.582+0800    restoring dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/   dhtcenter/1.bson
    2025-08-05T14:06:50.582+0800    no indexes to restore
    2025-08-05T14:06:50.582+0800    finished restoring dhtcenter.1 (0 documents, 0 failures)
    2025-08-05T14:06:50.582+0800    restoring users from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/admin/system.users.bson
    2025-08-05T14:06:50.608+0800    0 document(s) restored successfully. 0 document(s) failed to restore.
  3. 完整恢复(应用oplog,恢复到备份结束时的状态)

    # 恢复数据库并应用oplog
    mongorestore --username "sa" --password 'xxxxxx' --authenticationDatabase "admin" --oplogReplay /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS
    
    [root@mongo backup]# mongorestore --username "sa" --password 'xxxxxx' --authenticationDatabase "admin" --oplogReplay /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS
    2025-08-05T14:08:14.948+0800    preparing collections to restore from
    2025-08-05T14:08:14.949+0800    restoring to existing collection dhtcenter.1 without dropping
    2025-08-05T14:08:14.949+0800    reading metadata for dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.metadata.json
    2025-08-05T14:08:14.949+0800    restoring dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.bson
    2025-08-05T14:08:14.950+0800    no indexes to restore
    2025-08-05T14:08:14.950+0800    finished restoring dhtcenter.1 (0 documents, 0 failures)
    2025-08-05T14:08:14.950+0800    restoring users from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/admin/system.users.bson
    2025-08-05T14:08:15.018+0800    replaying oplog
    2025-08-05T14:08:15.018+0800    applied 0 oplog entries
    2025-08-05T14:08:15.018+0800    0 document(s) restored successfully. 0 document(s) failed to restore.
  4. 恢复特定数据库

    # 只恢复特定数据库
    mongorestore --username "sa" --password "xxxxxx" --authenticationDatabase "admin" --db your_database_name /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/your_database_name
    
    [root@mongo mongo]# mongorestore --username "sa" --password 'xxxxxx' --authenticationDatabase "admin" --db dhtcenter /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter
    2025-08-05T14:29:29.246+0800    the --db and --collection args should only be used when restoring from a BSON file. Other uses are deprecated and will not exist in the future; use --nsInclude instead
    2025-08-05T14:29:29.246+0800    building a list of collections to restore from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter dir
    2025-08-05T14:29:29.247+0800    restoring to existing collection dhtcenter.1 without dropping
    2025-08-05T14:29:29.247+0800    reading metadata for dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.metadata.json
    2025-08-05T14:29:29.247+0800    restoring dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.bson
    2025-08-05T14:29:29.247+0800    no indexes to restore
    2025-08-05T14:29:29.247+0800    finished restoring dhtcenter.1 (0 documents, 0 failures)
    2025-08-05T14:29:29.247+0800    0 document(s) restored successfully. 0 document(s) failed to restore.
  5. 恢复到特定时间点(如果备份包含足够的oplog)

    # 恢复到特定时间点
    mongorestore --username "sa" --password "xxxxxx" --authenticationDatabase "admin" --oplogReplay --oplogLimit "$(date -d "2023-05-20 15:30:00" +%s):1" /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS
    
    [root@mongo mongo]# mongorestore --username "sa" --password 'xxxxxx' --authenticationDatabase "admin" --oplogReplay --oplogLimit "$(date -d "2025-08-05 13:50:00" +%s):1" /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS
    2025-08-05T14:32:20.220+0800    preparing collections to restore from
    2025-08-05T14:32:20.221+0800    restoring to existing collection dhtcenter.1 without dropping
    2025-08-05T14:32:20.221+0800    reading metadata for dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.metadata.json
    2025-08-05T14:32:20.221+0800    restoring dhtcenter.1 from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/dhtcenter/1.bson
    2025-08-05T14:32:20.222+0800    no indexes to restore
    2025-08-05T14:32:20.222+0800    finished restoring dhtcenter.1 (0 documents, 0 failures)
    2025-08-05T14:32:20.222+0800    restoring users from /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS/admin/system.users.bson
    2025-08-05T14:32:20.250+0800    replaying oplog
    2025-08-05T14:32:20.250+0800    applied 0 oplog entries
    2025-08-05T14:32:20.250+0800    0 document(s) restored successfully. 0 document(s) failed to restore.

恢复后验证

恢复完成后,请执行以下验证:

  1. 检查MongoDB日志文件中是否有错误
  2. 连接到MongoDB并验证数据是否已正确恢复
  3. 检查关键集合的文档数量是否符合预期
  4. 验证应用程序是否能正常访问恢复的数据
# 连接到MongoDB并检查数据
mongo --username "sa" --password "xxxxxx" --authenticationDatabase "admin"

# 在mongo shell中执行
use your_database
db.your_collection.count()
# 检查其他关键集合

备份恢复常见问题与解决方案

  1. 恢复过程中出现权限错误

    确保使用了正确的用户名、密码和认证数据库。MongoDB 4.2.7需要适当的权限才能执行恢复操作。

  2. 恢复后数据不完整

    • 检查是否正确使用了--oplogReplay参数
    • 验证备份文件是否完整,未被损坏
    • 检查MongoDB日志中的错误信息
  3. oplog恢复失败

    如果应用oplog时出现错误,可能是因为:

    • oplog中的操作依赖于备份中不存在的数据
    • oplog格式不兼容或已损坏

    尝试仅恢复基本数据,不应用oplog:

    mongorestore --username "sa" --password "xxxxxx" --authenticationDatabase "admin" /tmp/mongodb_restore/mongodb_backup_YYYYMMDDHHMMSS

备份恢复安全注意事项

  1. 恢复操作可能会覆盖现有数据,请在执行前确认恢复的必要性
  2. 考虑先恢复到测试环境验证备份的有效性
  3. 在生产环境恢复前,创建现有数据的额外备份
  4. 恢复完成后,验证数据一致性和应用程序功能

定期测试恢复流程

建议定期测试备份恢复流程,确保:

这种定期测试可以提高在实际灾难恢复场景中的成功率。

注意事项

  1. 备份测试与验证

    • 定期测试备份的可用性,确保在需要时能够成功恢复
    • 升级MongoDB前,请确保备份所有数据
  2. 存储与安全

    • 生产环境中建议将备份文件复制到异地存储
    • 对于敏感数据,考虑对备份文件进行加密处理
  3. 监控与维护

    • 定期检查MongoDB的运行状态和日志,及时发现问题
    • 监控备份过程,确保备份任务成功完成