RocksDB备份恢复 #

一、备份概述 #

1.1 为什么需要备份 #

text
备份的重要性:
├── 数据安全 - 防止数据丢失
├── 灾难恢复 - 系统故障时恢复
├── 数据迁移 - 跨环境迁移数据
└── 历史版本 - 保留历史数据状态

1.2 RocksDB备份方式 #

方式 说明 适用场景
BackupEngine 增量备份,支持多版本 定期备份
Checkpoint 快速创建一致性快照 即时备份
文件复制 直接复制数据文件 简单备份

二、BackupEngine #

2.1 创建备份 #

cpp
#include <rocksdb/db.h>
#include <rocksdb/utilities/backup_engine.h>
#include <iostream>

int main() {
    rocksdb::DB* db;
    rocksdb::Options options;
    options.create_if_missing = true;
    
    rocksdb::Status status = rocksdb::DB::Open(options, "/tmp/testdb", &db);
    if (!status.ok()) {
        std::cerr << "Open failed: " << status.ToString() << std::endl;
        return 1;
    }
    
    // 创建BackupEngine
    rocksdb::BackupEngine* backup_engine;
    rocksdb::BackupEngineOptions backup_options("/tmp/backup");
    
    status = rocksdb::BackupEngine::Open(rocksdb::Env::Default(), 
                                         backup_options, 
                                         &backup_engine);
    
    if (!status.ok()) {
        std::cerr << "BackupEngine open failed: " << status.ToString() << std::endl;
        delete db;
        return 1;
    }
    
    // 创建备份
    status = backup_engine->CreateNewBackup(db);
    
    if (status.ok()) {
        std::cout << "Backup created successfully!" << std::endl;
    } else {
        std::cerr << "Backup failed: " << status.ToString() << std::endl;
    }
    
    delete backup_engine;
    delete db;
    return 0;
}

2.2 BackupEngineOptions #

cpp
#include <rocksdb/utilities/backup_engine.h>

rocksdb::BackupEngineOptions GetBackupOptions(const std::string& backup_dir) {
    rocksdb::BackupEngineOptions options(backup_dir);
    
    // 备份目录
    options.backup_dir = backup_dir;
    
    // 备份线程数
    options.backup_rate_limit = 0;  // 无限制
    options.restore_rate_limit = 0;  // 无限制
    
    // 最大备份数量
    options.max_valid_backups_to_open = 10;
    
    // 是否共享表文件
    options.share_table_files = true;
    
    // 是否共享带ID的表文件
    options.share_files_with_checksum = true;
    
    // 同步备份
    options.sync = true;
    
    // 备份日志
    options.backup_log_files = true;
    
    return options;
}

2.3 列出备份 #

cpp
#include <rocksdb/utilities/backup_engine.h>
#include <iostream>
#include <vector>

void ListBackups(rocksdb::BackupEngine* backup_engine) {
    std::vector<rocksdb::BackupInfo> backup_info;
    backup_engine->GetBackupInfo(&backup_info);
    
    std::cout << "Available backups:" << std::endl;
    for (const auto& info : backup_info) {
        std::cout << "  Backup ID: " << info.backup_id << std::endl;
        std::cout << "    Timestamp: " << info.timestamp << std::endl;
        std::cout << "    Size: " << info.size << " bytes" << std::endl;
        std::cout << "    Number of files: " << info.number_files << std::endl;
        std::cout << std::endl;
    }
}

2.4 恢复备份 #

cpp
#include <rocksdb/db.h>
#include <rocksdb/utilities/backup_engine.h>
#include <iostream>

void RestoreBackup(const std::string& backup_dir,
                   const std::string& db_dir) {
    
    rocksdb::BackupEngine* backup_engine;
    rocksdb::BackupEngineOptions backup_options(backup_dir);
    
    rocksdb::Status status = rocksdb::BackupEngine::Open(
        rocksdb::Env::Default(), backup_options, &backup_engine);
    
    if (!status.ok()) {
        std::cerr << "Open backup engine failed: " << status.ToString() << std::endl;
        return;
    }
    
    // 恢复最新备份
    status = backup_engine->RestoreDBFromLatestBackup(db_dir, db_dir);
    
    if (status.ok()) {
        std::cout << "Database restored successfully!" << std::endl;
    } else {
        std::cerr << "Restore failed: " << status.ToString() << std::endl;
    }
    
    delete backup_engine;
}

// 恢复指定备份
void RestoreSpecificBackup(const std::string& backup_dir,
                           const std::string& db_dir,
                           uint32_t backup_id) {
    
    rocksdb::BackupEngine* backup_engine;
    rocksdb::BackupEngineOptions backup_options(backup_dir);
    
    rocksdb::BackupEngine::Open(rocksdb::Env::Default(), backup_options, &backup_engine);
    
    // 恢复指定ID的备份
    rocksdb::Status status = backup_engine->RestoreDBFromBackup(
        backup_id, db_dir, db_dir);
    
    if (status.ok()) {
        std::cout << "Database restored from backup " << backup_id << std::endl;
    }
    
    delete backup_engine;
}

2.5 删除备份 #

cpp
#include <rocksdb/utilities/backup_engine.h>

void DeleteOldBackups(rocksdb::BackupEngine* backup_engine, int keep_count) {
    // 只保留最近N个备份
    rocksdb::Status status = backup_engine->PurgeOldBackups(keep_count);
    
    if (status.ok()) {
        std::cout << "Old backups purged, keeping " << keep_count << " latest" << std::endl;
    }
}

void DeleteSpecificBackup(rocksdb::BackupEngine* backup_engine, uint32_t backup_id) {
    rocksdb::Status status = backup_engine->DeleteBackup(backup_id);
    
    if (status.ok()) {
        std::cout << "Backup " << backup_id << " deleted" << std::endl;
    }
}

三、Checkpoint #

3.1 创建检查点 #

cpp
#include <rocksdb/db.h>
#include <rocksdb/utilities/checkpoint.h>
#include <iostream>

void CreateCheckpoint(rocksdb::DB* db, const std::string& checkpoint_dir) {
    rocksdb::Checkpoint* checkpoint;
    rocksdb::Status status = rocksdb::Checkpoint::Create(db, &checkpoint);
    
    if (!status.ok()) {
        std::cerr << "Create checkpoint object failed: " << status.ToString() << std::endl;
        return;
    }
    
    // 创建检查点
    status = checkpoint->CreateCheckpoint(checkpoint_dir);
    
    if (status.ok()) {
        std::cout << "Checkpoint created at " << checkpoint_dir << std::endl;
    } else {
        std::cerr << "Create checkpoint failed: " << status.ToString() << std::endl;
    }
    
    delete checkpoint;
}

int main() {
    rocksdb::DB* db;
    rocksdb::Options options;
    options.create_if_missing = true;
    
    rocksdb::DB::Open(options, "/tmp/testdb", &db);
    
    // 写入一些数据
    for (int i = 0; i < 100; i++) {
        db->Put(rocksdb::WriteOptions(), 
                "key" + std::to_string(i), 
                "value" + std::to_string(i));
    }
    
    // 创建检查点
    CreateCheckpoint(db, "/tmp/checkpoint");
    
    delete db;
    return 0;
}

3.2 检查点与备份的区别 #

特性 Checkpoint BackupEngine
创建速度 快(硬链接) 较慢(复制)
空间占用 共享文件 独立文件
增量支持
版本管理
适用场景 即时快照 定期备份

四、增量备份 #

4.1 增量备份原理 #

text
增量备份流程:

第一次备份:
├── 复制所有SST文件
├── 复制WAL文件
└── 记录文件清单

第二次备份(增量):
├── 检查文件变化
├── 只复制新文件
├── 硬链接共享文件
└── 更新文件清单

4.2 实现增量备份 #

cpp
#include <rocksdb/db.h>
#include <rocksdb/utilities/backup_engine.h>
#include <iostream>

class BackupManager {
public:
    BackupManager(rocksdb::DB* db, const std::string& backup_dir)
        : db_(db), backup_dir_(backup_dir) {
        
        rocksdb::BackupEngineOptions options(backup_dir);
        options.share_table_files = true;
        options.share_files_with_checksum = true;
        
        rocksdb::BackupEngine::Open(rocksdb::Env::Default(), options, &backup_engine_);
    }
    
    ~BackupManager() {
        if (backup_engine_) {
            delete backup_engine_;
        }
    }
    
    bool CreateBackup() {
        rocksdb::Status status = backup_engine_->CreateNewBackup(db_);
        
        if (status.ok()) {
            std::cout << "Backup created at " << backup_dir_ << std::endl;
            return true;
        }
        
        std::cerr << "Backup failed: " << status.ToString() << std::endl;
        return false;
    }
    
    void ListBackups() {
        std::vector<rocksdb::BackupInfo> info;
        backup_engine_->GetBackupInfo(&info);
        
        for (const auto& i : info) {
            std::cout << "Backup " << i.backup_id 
                      << ": " << i.size << " bytes" << std::endl;
        }
    }
    
    bool RestoreLatest(const std::string& restore_dir) {
        rocksdb::Status status = backup_engine_->RestoreDBFromLatestBackup(
            restore_dir, restore_dir);
        return status.ok();
    }
    
    void PurgeOldBackups(int keep_count) {
        backup_engine_->PurgeOldBackups(keep_count);
    }

private:
    rocksdb::DB* db_;
    std::string backup_dir_;
    rocksdb::BackupEngine* backup_engine_ = nullptr;
};

五、备份策略 #

5.1 定期备份 #

cpp
#include <rocksdb/db.h>
#include <rocksdb/utilities/backup_engine.h>
#include <chrono>
#include <thread>

void ScheduledBackup(rocksdb::DB* db, 
                     const std::string& backup_dir,
                     int interval_seconds,
                     int max_backups) {
    
    rocksdb::BackupEngine* backup_engine;
    rocksdb::BackupEngineOptions options(backup_dir);
    rocksdb::BackupEngine::Open(rocksdb::Env::Default(), options, &backup_engine);
    
    while (true) {
        // 创建备份
        rocksdb::Status status = backup_engine->CreateNewBackup(db);
        
        if (status.ok()) {
            std::cout << "Backup created at " 
                      << std::chrono::system_clock::now().time_since_epoch().count()
                      << std::endl;
            
            // 清理旧备份
            backup_engine->PurgeOldBackups(max_backups);
        }
        
        // 等待下一次备份
        std::this_thread::sleep_for(std::chrono::seconds(interval_seconds));
    }
    
    delete backup_engine;
}

5.2 备份验证 #

cpp
#include <rocksdb/utilities/backup_engine.h>
#include <iostream>

bool VerifyBackup(rocksdb::BackupEngine* backup_engine, uint32_t backup_id) {
    rocksdb::Status status = backup_engine->VerifyBackup(backup_id);
    
    if (status.ok()) {
        std::cout << "Backup " << backup_id << " is valid" << std::endl;
        return true;
    } else {
        std::cerr << "Backup " << backup_id << " is corrupted: " 
                  << status.ToString() << std::endl;
        return false;
    }
}

void VerifyAllBackups(rocksdb::BackupEngine* backup_engine) {
    std::vector<rocksdb::BackupInfo> backup_info;
    backup_engine->GetBackupInfo(&backup_info);
    
    for (const auto& info : backup_info) {
        VerifyBackup(backup_engine, info.backup_id);
    }
}

六、灾难恢复 #

6.1 恢复流程 #

cpp
#include <rocksdb/db.h>
#include <rocksdb/utilities/backup_engine.h>
#include <iostream>

class DisasterRecovery {
public:
    DisasterRecovery(const std::string& backup_dir, const std::string& db_dir)
        : backup_dir_(backup_dir), db_dir_(db_dir) {}
    
    bool Recover() {
        std::cout << "Starting disaster recovery..." << std::endl;
        
        // 1. 打开备份引擎
        rocksdb::BackupEngine* backup_engine;
        rocksdb::BackupEngineOptions options(backup_dir_);
        
        rocksdb::Status status = rocksdb::BackupEngine::Open(
            rocksdb::Env::Default(), options, &backup_engine);
        
        if (!status.ok()) {
            std::cerr << "Cannot open backup engine: " << status.ToString() << std::endl;
            return false;
        }
        
        // 2. 列出可用备份
        std::vector<rocksdb::BackupInfo> backup_info;
        backup_engine->GetBackupInfo(&backup_info);
        
        if (backup_info.empty()) {
            std::cerr << "No backups available" << std::endl;
            delete backup_engine;
            return false;
        }
        
        // 3. 选择最新备份
        uint32_t latest_backup_id = backup_info.back().backup_id;
        std::cout << "Restoring from backup " << latest_backup_id << std::endl;
        
        // 4. 验证备份
        status = backup_engine->VerifyBackup(latest_backup_id);
        if (!status.ok()) {
            std::cerr << "Backup verification failed" << std::endl;
            delete backup_engine;
            return false;
        }
        
        // 5. 恢复数据库
        status = backup_engine->RestoreDBFromBackup(
            latest_backup_id, db_dir_, db_dir_);
        
        if (!status.ok()) {
            std::cerr << "Restore failed: " << status.ToString() << std::endl;
            delete backup_engine;
            return false;
        }
        
        // 6. 验证恢复的数据库
        rocksdb::DB* db;
        status = rocksdb::DB::Open(rocksdb::Options(), db_dir_, &db);
        
        if (!status.ok()) {
            std::cerr << "Cannot open restored database" << std::endl;
            delete backup_engine;
            return false;
        }
        
        std::cout << "Recovery completed successfully!" << std::endl;
        
        delete db;
        delete backup_engine;
        return true;
    }

private:
    std::string backup_dir_;
    std::string db_dir_;
};

七、最佳实践 #

7.1 备份建议 #

建议 说明
定期备份 设置自动备份计划
多份备份 保留多个历史版本
异地备份 备份存储到远程位置
验证备份 定期验证备份有效性
测试恢复 定期测试恢复流程

7.2 备份配置示例 #

cpp
#include <rocksdb/utilities/backup_engine.h>

rocksdb::BackupEngineOptions GetProductionBackupOptions() {
    rocksdb::BackupEngineOptions options("/backup/rocksdb");
    
    // 启用文件共享(增量备份)
    options.share_table_files = true;
    options.share_files_with_checksum = true;
    
    // 同步写入
    options.sync = true;
    
    // 备份日志文件
    options.backup_log_files = true;
    
    // 限速(可选)
    // options.backup_rate_limit = 100 * 1024 * 1024;  // 100MB/s
    
    return options;
}

八、总结 #

8.1 备份API速查 #

操作 方法 说明
创建备份 CreateNewBackup(db) 创建新备份
列出备份 GetBackupInfo(&info) 获取备份列表
恢复最新 RestoreDBFromLatestBackup(db_dir, wal_dir) 恢复最新备份
恢复指定 RestoreDBFromBackup(id, db_dir, wal_dir) 恢复指定备份
删除备份 DeleteBackup(id) 删除指定备份
清理旧备份 PurgeOldBackups(count) 保留最近N个
验证备份 VerifyBackup(id) 验证备份有效性
创建检查点 checkpoint->CreateCheckpoint(dir) 创建检查点

8.2 关键要点 #

  1. 定期备份:设置自动备份计划
  2. 增量备份:使用BackupEngine节省空间
  3. 验证备份:定期验证备份有效性
  4. 测试恢复:确保恢复流程可用
  5. 异地备份:备份存储到远程位置

下一步,让我们学习存储引擎原理!

最后更新:2026-03-27