前言
原因是在2025年2月26日MinIO合并的一个PR中,删除了114736行代码,删除了Web UI的几乎所有核心管理功能,仅保留对象浏览能力。也就是镜像minio/minio:RELEASE.2025-04-08T15-41-24Z 后面都是阉割版,在写这篇文章,最新的MinIO的镜像需要用户自己构建。
因此考虑其他开源的对象存储解决方案,很多人推荐国产存储项目RustFS。作为新兴的存储解决方案,凭借高性能和灵活性逐渐受到关注,所以本次实现的迁移工具需达成以下目标:
-
支持多类型 RustFS 后端(S3 兼容接口、本地文件系统、HTTP API)
-
具备高并发迁移能力,兼顾效率与稳定性
-
完善的错误处理与重试机制,保障数据完整性
-
安全防护(如路径遍历攻击防范)
-
详细的进度跟踪与日志记录
工具架构
工具采用模块化设计,主要分为 5 个核心模块:
-
基础工具模块:配置加载、日志初始化、路径安全验证等通用功能
-
MinIO 客户端模块:负责从 MinIO 读取对象元数据与数据流
-
RustFS 客户端模块:适配不同类型的 RustFS 后端,提供统一上传接口
-
迁移核心模块:实现并发调度、进度统计与结果汇总
-
主程序模块:协调各组件工作,完成端到端迁移流程
核心功能
配置与环境
配置加载采用 YAML 格式,支持默认值填充,提升容错性:
def load_config():
config_path = os.path.join(get_exe_dir(), "config.yml")
if not os.path.exists(config_path):
logger.error(f"配置文件不存在:{config_path}")
sys.exit(1)
日志系统支持文件与控制台双输出,兼容 Windows 环境的中文显示与权限问题:
def init_logger():
# 日志目录自适应(优先EXE目录,权限不足时切换到桌面)
log_dir = Path(get_exe_dir()) / "logs"
try:
log_dir.mkdir(exist_ok=True, parents=True)
except PermissionError:
log_dir = Path(os.path.expanduser("~")) / "Desktop" / "migrate_logs"
log_dir.mkdir(exist_ok=True, parents=True)
MinIO客户端
MinIO 客户端实现了对象列表获取与数据流读取功能,特别注意路径安全验证:
class MinioClient:
def __init__(self, config):
self.client = Minio(
endpoint=config["endpoint"],
access_key=config["access_key"],
secret_key=config["secret_key"],
secure=config["secure"],
)
if not self.client.bucket_exists(self.bucket):
raise ValueError(f"Minio桶不存在:{self.bucket}")
RustFS 客户端
多后端适配
class RustfsClient:
def __init__(self, config, migrate_config):
self.type = config["type"].lower()
if self.type == "s3":
self._init_s3_client(config["s3"])
elif self.type == "local":
self._init_local_client(config["local"])
elif self.type == "http":
self._init_http_client(config["http"])
并发调度与进度跟踪
def main():
# 列出待迁移对象
obj_list = list(minio_client.list_objects_with_size())
total = len(obj_list)
logger.info(f"共发现 {total} 个待迁移文件")
# 动态调整并发数(大文件(>100MB)较多时降低并发)
large_file_threshold = 100 * 1024 * 1024
large_file_count = sum(1 for _, size in obj_list if size > large_file_threshold)
adjusted_concurrency = max(1, migrate_config["concurrency"] - large_file_count // 5)
# 并发迁移
with ThreadPoolExecutor(max_workers=adjusted_concurrency) as executor:
future_to_obj = {
executor.submit(migrate_single_object, minio_client, rustfs_client, obj_name, size): (obj_name, size)
for obj_name, size in obj_list
}
使用指南
资源下载
修改配置
解压migrate.zip ,修改config.yml配置,最小修改如下。
minio:
endpoint: "IP:9000"
access_key: "minio_access_key"
secret_key: "minio_secret_key"
bucket: "source-bucket"
rustfs:
type: "s3"
s3:
endpoint: "IP:9000"
access_key: "rustfs_access_key"
secret_key: "rustfs_secret_key"
bucket: "target-bucket"
运行工具
直接执行可执行文件或通过 Python 运行migrate_core.py(评论发送:源码)
查看结果
通过控制台输出或logs目录下的日志文件查看迁移详情

其他扩展
实际应用中,可根据需求进一步扩展:
-
增加增量迁移支持(基于文件修改时间或 ETag)
-
实现断点续传功能
-
添加迁移后的数据校验机制
-
扩展更多存储后端支持(如 OSS、GCS 等)
使用必看
此工具是通过一定并发控制、错误处理与安全防护,仅能够满足中小规模数据迁移的需求,如需大规模附件迁移请寻找更合适的方案。