Sauvegarde complète et incrémentielle de bases MongoDB

Sauvegarde complète et incrémentielle de bases MongoDB

Dans un environnement de production avec un volume de données MongoDB croissant, une stratégie de sauvegarde robuste est essentielle pour minimiser les temps d'arrêt en cas de panne. Une approche combine une sauvegarde complète périodique avec des sauvegardes incrémentielles régulières, basées sur le journal des opérations (oplog).

Mise en place de l'environnement de test (réplicat)

Pour tester, nous déployons un ensemble de réplicas sur une machine CentOS. Après l'installation de MongoDB 3.6, nous créons le réplicat :

rs0:PRIMARY> rs.isMaster();
{
    "hosts" : [
        "192.168.118.16:27017",
        "192.168.118.16:27018",
        "192.168.118.16:27019"
    ],
    ...
}

Ensuite, nous insérons des données de test :

rs0:PRIMARY> for (let idx = 1; idx <= 10000; idx++) {
    db.users.insertOne({user_id: idx, username: "test_user", location: "Lyon"});
}
WriteResult({ "nInserted" : 1 })
rs0:PRIMARY> db.users.countDocuments();
10000

Sauvegarde complète et restauration

Le script suivant effectue une sauvegarde complète de toutes les bases, comprenant le journal des opérations, et gère la rétention des anciens dumps.

#!/bin/bash
# Script de sauvegarde complète MongoDB
DB_HOST="192.168.118.16"
DB_PORT="27017"
MONGO_TOOLS="/mongodb/bin"
BACKUP_ROOT="/mongodb/backup"
BACKUP_TAG=$(date +"%Y%m%d")
BACKUP_DIR="${BACKUP_ROOT}/${BACKUP_TAG}"

if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
fi

echo "Démarrage de la sauvegarde complète à $(date)"
${MONGO_TOOLS}/mongodump --host ${DB_HOST} --port ${DB_PORT} --oplog --gzip --out ${BACKUP_DIR}

if [ $? -eq 0 ]; then
    echo "Sauvegarde complète réussie."
else
    echo "Échec de la sauvegarde complète."
    exit 1
fi

# Nettoyage des backups de plus de 7 jours
EXPIRATION_TAG=$(date -d "7 days ago" +"%Y%m%d")
EXPIRATION_DIR="${BACKUP_ROOT}/${EXPIRATION_TAG}"
if [ -d "$EXPIRATION_DIR" ]; then
    rm -rf "$EXPIRATION_DIR"
    echo "Ancien backup supprimé : ${EXPIRATION_DIR}"
fi
echo "Fin de la procédure de sauvegarde complète à $(date)"

Pour la restauration, un script interactif permet de sélectionner la date du backup à restaurer.

#!/bin/bash
# Script de restauration complète MongoDB
DB_HOST="192.168.118.16"
MONGO_TOOLS="/mongodb/bin"
BACKUP_STORE="/mongodb/backup"

echo "=== Restauration complète de MongoDB ==="
echo "Sauvegardes disponibles :"
ls ${BACKUP_STORE}

read -p "Entrez la date du backup à restaurer (ex: 20230912) : " SELECTED_DATE

if [[ -z "$SELECTED_DATE" || ! -d "${BACKUP_STORE}/${SELECTED_DATE}" ]]; then
    echo "Date invalide ou répertoire inexistant."
    exit 1
fi

read -p "Confirmer la restauration complète depuis '${SELECTED_DATE}' ? (o/n) : " CONFIRM
if [[ "$CONFIRM" != "o" ]]; then
    exit 0
fi

echo "Restauration en cours..."
${MONGO_TOOLS}/mongorestore --host ${DB_HOST} --port 27017 --oplogReplay --gzip "${BACKUP_STORE}/${SELECTED_DATE}/"

if [ $? -eq 0 ]; then
    echo "Restauration complète terminée avec succès."
else
    echo "Échec de la restauration."
    exit 1
fi

Sauvegarde incrémentielle et restauration

La sauvegarde incrémentielle capture les opérations récentes via l'oplog. Le script ci-dessous extrait les entrées d'oplog des dernières heures et vérifie la continuité temporelle.

#!/bin/bash
# Script de sauvegarde incrémentielle MongoDB
MONGO_CLI="/mongodb/bin/mongo"
DB_HOST="192.168.118.16"
DB_PORT="27017"
OPLOG_BACKUP_DIR="/mongodb/backup/incr_oplogs"
INTERVAL_SECONDS=3600 # 1 heure

# Préparation des répertoires
INCR_DIR="${OPLOG_BACKUP_DIR}/mongo-${DB_PORT}"
LOG_DIR="${OPLOG_BACKUP_DIR}/logs-${DB_PORT}"
mkdir -p "${INCR_DIR}" "${LOG_DIR}"

CURRENT_TS=$(date +%s)
START_TS=$((CURRENT_TS - INTERVAL_SECONDS))
SAFETY_MARGIN_SECONDS=3720 # 1h 2min
SAFETY_START_TS=$((CURRENT_TS - SAFETY_MARGIN_SECONDS))

TIMESTAMP=$(date +"%Y%m%d%H%M%S")
echo "Début de la sauvegarde incrémentielle à ${TIMESTAMP}"

# Récupération du temps de début de l'oplog
OPLOG_INFO=$(echo "db.printReplicationInfo()" | ${MONGO_CLI} ${DB_HOST}:${DB_PORT} --quiet)
OPLOG_FIRST_TS=$(echo "${OPLOG_INFO}" | grep -o "oplog first event time.*" | awk -F: '{print $2}' | xargs -I{} date -d "{}" +%s 2>/dev/null)

if [ -z "$OPLOG_FIRST_TS" ]; then
    echo "Avertissement : Impossible de déterminer le premier timestamp de l'oplog. La vérification de couverture est sautée."
elif [ "$OPLOG_FIRST_TS" -gt "$START_TS" ]; then
    echo "ERREUR : L'oplog ne couvre pas la période demandée. Augmentez la taille de l'oplog ou la fréquence de backup."
    exit 1
fi

# Extraction de l'oplog pour l'intervalle
OPLOG_FILE="${INCR_DIR}/oplog_${TIMESTAMP}"
${MONGO_TOOLS}/mongodump --host ${DB_HOST} --port ${DB_PORT} -d local -c oplog.rs --query "{\"ts\":{\"\$gte\":Timestamp(${START_TS},1),\"\$lte\":Timestamp(${CURRENT_TS},9999)}}" -o "${OPLOG_FILE}"

# Vérification post-sauvegarde
if [ -d "${OPLOG_FILE}" ]; then
    echo "Sauvegarde incrémentielle réussie : ${OPLOG_FILE}"
else
    echo "Échec : Fichier de backup non généré."
    exit 1
fi

# Nettoyage des anciens backups incrémentiels
KEEP_DAYS=3
find "${INCR_DIR}" -type d -mtime +${KEEP_DAYS} -exec rm -rf {} + 2>/dev/null
echo "Fin de la sauvegarde incrémentielle à $(date)"

Pour restaurer des opérations incrémentielles, le script applique l'oplog sauvegardé par-dessus une base restaurée.

#!/bin/bash
# Script de restauration incrémentielle MongoDB
DB_HOST="192.168.118.16"
DB_PORT="27017"
MONGO_TOOLS="/mongodb/bin"
INCR_BACKUP_STORE="/mongodb/backup/incr_oplogs/mongo-27017"

echo "=== Restauration incrémentielle de MongoDB ==="
echo "Sauvegardes incrémentielles disponibles :"
ls ${INCR_BACKUP_STORE} | grep oplog_

read -p "Entrez le nom du dossier de backup à appliquer (ex: oplog_20230912153000) : " INCR_NAME

if [[ -z "$INCR_NAME" || ! -d "${INCR_BACKUP_STORE}/${INCR_NAME}" ]]; then
    echo "Nom de backup invalide."
    exit 1
fi

read -p "Confirmer l'application du delta '${INCR_NAME}' ? (o/n) : " CONFIRM
if [[ "$CONFIRM" != "o" ]]; then
    exit 0
fi

TEMP_DIR="/tmp/mongo_restore_${INCR_NAME}"
mkdir -p "${TEMP_DIR}"
cp -a "${INCR_BACKUP_STORE}/${INCR_NAME}/local/oplog.rs.bson" "${TEMP_DIR}/oplog.bson"

echo "Application de l'oplog incrémentiel..."
${MONGO_TOOLS}/mongorestore --host ${DB_HOST} --port ${DB_PORT} --oplogReplay "${TEMP_DIR}/"

if [ $? -eq 0 ]; then
    echo "Restauration incrémentielle appliquée avec succès."
    rm -rf "${TEMP_DIR}"
else
    echo "Échec de l'application du delta."
    exit 1
fi

Stratégie de sauvegarde recommandée

Pour un environnement de production, une combinaison est efficace : une sauvegarde complète hebdomadaire et des sauvegardes incrémentielles quotidiennes. Une étape avancée consiste à restaurer systématiquement ces backups sur un jeu de réplicas secondaire dédié à la vérification de l'intégrité des données.

Étiquettes: MongoDB sauvegarde oplog réplicat mongodump

Publié le 30 juillet à 10h56