惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MongoDB | Blog
MongoDB | Blog
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
V
Visual Studio Blog
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Docker
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
博客园 - 叶小钗
博客园 - 聂微东
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
MyScale Blog
MyScale Blog
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
腾讯CDC
S
SegmentFault 最新的问题
博客园 - 【当耐特】

Liu Zijian's Blog | 一个技术博客

使用Certbot自动续签HTTPS证书 使用Filebeat采集Nginx日志到ES Python的协程 Python中的异常 Python中的类和对象 Python的函数 Python的数据结构,推导式、迭代器和生成器 Spring AI集成多模态模型 LangChain4j多模态 LangChain Tools工具使用 Python中的模块和包 Python全局环境和虚拟环境(venv) LangChain Prompt提示词工程 LangChain4j Tools工具使用 基于Dify搭建AI智能体应用 LangChain4j RAG检索增强生成 Spring AI实现MCP Server Spring AI集成MCP Client LangChain4j Prompt提示词工程 Spring AI使用知识库增强对话功能 Spring AI实现一个智能客服 Spring AI实现一个简单的对话机器人 自己实现一个DNS服务 简单理解AI智能体 大模型和大模型应用 LangChain开篇 LangChain4j开篇 一个解析Excel2007的POI工具类 DataPermissionInterceptor源码解读 TenantLineInnerInterceptor源码解读
实现MinIO数据的每日备份
Liu Zijian · 2025-10-20 · via Liu Zijian's Blog | 一个技术博客

1.概述

MinIO是一个对象存储解决方案,常作为中间件用于后端系统保存和管理文件附件,附件和关系型数据库的库表数据一样是系统的核心用户数据,因此系统运行过程中,需要对附件数据进行每天备份。

在常年累月运行中,系统产生的附件量是巨大的,有时单独一个附件就很大,如果每天进行全量备份,那备份的文件就会像滚雪球一样越来越大,因此这里采用增量备份的形式,每天只备份当天的数据。

2.后端代码适配

首先,MinIO的文件层次就需要按天分开,在后端调用S3接口进行上传的代码进行控制

path = FileUtils.generatePath(content, name);
int year = LocalDate.now().getYear();
int month = LocalDate.now().getMonthValue();
int day = LocalDate.now().getDayOfMonth();
path = year+"/"+month+"/"+day+"/"+path;

这样,在前端调用上传接口上传附件后,返回的附件路径应该是这样的

{
    "code": 0,
    "data": "2025/10/20/62ca4c572522f9708199a4f96e0816f879669785347483232a8fcfd085267dc5.PNG",
    "msg": "",
    "total": null
}

文件在MinIO中会按照年月日分级存储

3.备份Shell脚本

编写以下Shell脚本,调用MinIO客户端命令mc拷贝文件,并定时调用脚本实现每天进行备份

#!/bin/bash

# MinIO 备份脚本 

YEAR=$(date +%Y)
MONTH=$(date +%m)
DAY=$(date +%d)

# 配置变量
MINIO_ALIAS="myminio"
BUCKET_NAME="u******ia"
BACKUP_BASE_DIR="/opt/backup"
LOG_DIR="/var/log/minio_backup"
DATE_SUFFIX=$(date +%Y-%m-%d)-back
BACKUP_PATH="${BACKUP_BASE_DIR}/${DATE_SUFFIX}"

# 创建必要的目录
mkdir -p "${BACKUP_PATH}"
mkdir -p "${LOG_DIR}"

# 日志文件
LOG_FILE="${LOG_DIR}/backup_$(date +%Y%m%d).log"

# 函数:记录日志
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# 函数:错误处理
error_exit() {
    log_message "错误: $1"
    exit 1
}

# 开始备份
log_message "=== 开始 MinIO 备份 ==="
log_message "备份源: ${MINIO_ALIAS}/${BUCKET_NAME}"
log_message "备份目标: ${BACKUP_PATH}"

# 检查 mc 命令是否存在
if ! command -v /opt/mc &> /dev/null; then
    error_exit "mc 命令未找到,请确保 MinIO Client 已安装"
fi

# 检查备份目录是否可写
if [ ! -w "${BACKUP_BASE_DIR}" ]; then
    error_exit "备份目录 ${BACKUP_BASE_DIR} 不可写"
fi


# 执行备份
log_message "开始复制数据..."
/opt/mc cp "${MINIO_ALIAS}/${BUCKET_NAME}/${YEAR}/${MONTH}/${DAY}" "${BACKUP_PATH}/" --recursive 2>&1 | tee -a "$LOG_FILE"

# 检查备份结果
if [ ${PIPESTATUS[0]} -eq 0 ]; then
    log_message "备份成功完成"
    
    # 显示备份统计信息
    BACKUP_SIZE=$(du -sh "${BACKUP_PATH}" | cut -f1)
    FILE_COUNT=$(find "${BACKUP_PATH}" -type f | wc -l)
    log_message "备份大小: ${BACKUP_SIZE}"
    log_message "文件数量: ${FILE_COUNT}"
    log_message "备份位置: ${BACKUP_PATH}"
else
    error_exit "备份过程中出现错误"
fi

log_message "=== 备份完成 ==="