# 存储管理 **本文引用的文件** - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能与索引优化](#性能与索引优化) 8. [配置与容量规划](#配置与容量规划) 9. [监控与可观测性](#监控与可观测性) 10. [故障排查指南](#故障排查指南) 11. [结论](#结论) 12. [附录:数据模型与迁移建议](#附录数据模型与迁移建议) ## 简介 本技术文档围绕文件存储管理子系统,系统性阐述 MinIO 对象存储集成、Bucket 管理、权限控制、文件元数据设计、存储路径规划、版本管理、数据库表结构与索引优化、查询性能调优、配置与容量规划、监控方案、生命周期与归档策略、备份恢复机制以及扩展与迁移指南。目标是帮助读者快速理解并高效运维该存储子系统。 ## 项目结构 文件存储子系统位于 crm-file 模块,采用分层架构: - API 层:对外暴露统一接口(FileApi) - 控制器层:HTTP 入口(FileController) - 服务层:业务编排与流程控制(IFileInfoService、FileApiImpl、FileInfoServiceImpl) - 客户端层:第三方能力集成(KkFileViewClient) - 配置层:MinIO、调度、属性等(MinioConfig、SchedulingConfig、FileProperties) - 领域层:实体与 DTO(FileInfo、FileInfoDTO、UploadSession 等) - 持久化层:MyBatis-Plus Mapper(FileInfoMapper) - 任务层:定时清理(OrphanChunkCleanupTask) ```mermaid graph TB subgraph "应用启动" App["CrmAppApplication"] end subgraph "文件模块" Ctrl["FileController"] Api["FileApi / FileApiImpl"] Svc["IFileInfoService / FileInfoServiceImpl"] Client["KkFileViewClient"] Cfg["MinioConfig / FileProperties / SchedulingConfig"] Entity["FileInfo / DTOs"] Mapper["FileInfoMapper"] Task["OrphanChunkCleanupTask"] end subgraph "外部系统" MinIO["MinIO 对象存储"] KK["KKFileView 在线预览"] end App --> Ctrl Ctrl --> Api Api --> Svc Svc --> Mapper Svc --> Client Svc --> Cfg Svc --> MinIO Client --> KK Task --> Svc ``` 图表来源 - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) 章节来源 - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [application.yml](file://crm-app/src/main/resources/application.yml) ## 核心组件 - 配置中心 - MinioConfig:封装 MinIO 客户端初始化与连接参数 - FileProperties:文件相关配置项(如 Bucket、路径前缀、分片大小等) - SchedulingConfig:开启/关闭定时任务(如孤儿分片清理) - 控制器与API - FileController:提供上传、下载、分片上传、预览等 HTTP 接口 - FileApi / FileApiImpl:定义并实现文件操作的业务契约 - 服务层 - IFileInfoService / FileInfoServiceImpl:文件元数据管理、上传流程编排、下载流程、预览链接生成 - KkFileViewClient:调用第三方在线预览服务 - 持久化 - FileInfo 实体与 FileInfoMapper:文件元数据持久化 - 任务 - OrphanChunkCleanupTask:定期清理未完成的分片上传残留 章节来源 - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) ## 架构总览 整体采用“控制器-服务-客户端”的分层模式,结合 MinIO 对象存储与第三方预览服务,形成高内聚、低耦合的文件管理能力。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "FileController" participant Service as "IFileInfoService/FileInfoServiceImpl" participant MinIO as "MinIO 对象存储" participant KK as "KKFileView 预览服务" Client->>Controller : "发起上传/下载/预览请求" Controller->>Service : "校验参数与权限" alt 上传流程 Service->>MinIO : "创建Bucket(若不存在)/生成对象键" Service->>MinIO : "分片上传或直传" Service-->>Controller : "返回文件元数据" else 下载流程 Service->>MinIO : "获取对象流/签名URL" Service-->>Controller : "返回下载响应" else 预览流程 Service->>KK : "生成预览链接" Service-->>Controller : "返回预览地址" end Controller-->>Client : "统一结果封装" ``` 图表来源 - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) ## 详细组件分析 ### MinIO 对象存储集成 - 目标:通过 MinioConfig 初始化客户端,使用 FileProperties 中的 Bucket、Endpoint、AccessKey、SecretKey 等配置进行连接与鉴权。 - 关键职责: - 动态创建/检查 Bucket 存在性 - 生成对象键(路径规划) - 上传(直传/分片)、下载(流式/签名URL)、删除、元数据读取 - 权限控制: - 基于访问密钥的细粒度权限 - 可在 MinIO 控制台设置 Bucket 策略,限制读写范围 - 路径规划建议: - 按租户/业务域划分 Bucket - 对象键采用“业务类型/日期/唯一标识”三段式,便于检索与归档 章节来源 - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) ### Bucket 管理 - 自动创建:首次写入时检测 Bucket 是否存在,不存在则创建 - 命名规范:建议使用小写英文字母与数字,避免冲突 - 生命周期策略:在 MinIO 侧配置规则(过期、转储到冷存储) - 多环境隔离:开发/测试/生产分别独立 Bucket 章节来源 - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) ### 权限控制 - 认证与授权:由上层安全模块负责(JWT、角色、数据权限),文件接口需鉴权后访问 - 数据可见性:通过 OwnedEntity 基类注入所有者信息,确保仅本人或授权角色可操作 - 最小权限原则:为 MinIO 访问密钥配置最小可用权限(只读/只写特定 Bucket) 章节来源 - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) ### 文件元数据设计与存储路径规划 - 元数据字段建议: - 唯一标识、文件名、原始大小、MIME 类型、MD5/SHA1、存储桶名、对象键、上传者、所属者、状态、版本、创建/更新时间 - 路径规划: - 示例:/{tenant}/{bizType}/{yyyyMMdd}/{uuid}.{ext} - 支持按业务域与时间分区,提升检索与归档效率 - 版本管理: - 建议在对象键中追加版本号或使用 MinIO 版本控制功能 - 元数据记录当前版本与历史版本映射 章节来源 - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) - [FileConstants.java](file://crm-file/src/main/java/com/crm/file/constant/FileConstants.java) ### 分片上传与会话管理 - 流程: - 初始化会话(MultipartInitDTO) - 逐块上传(UploadSession 维护分片状态) - 合并分片并落盘元数据 - 异常处理: - 网络中断重试、分片完整性校验 - 超时与幂等控制 - 清理策略: - OrphanChunkCleanupTask 定期扫描并清理未完成会话 章节来源 - [MultipartInitDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/MultipartInitDTO.java) - [UploadSession.java](file://crm-file/src/main/java/com/crm/file/domain/dto/UploadSession.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) ### 在线预览集成 - 通过 KkFileViewClient 调用第三方预览服务,返回预览 URL - 支持常见办公文档格式,无需本地转换 章节来源 - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) ### 下载流程 - 支持直接流式下载与签名 URL 下载 - 根据文件大小与场景选择合适方式 章节来源 - [FileDownloadDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileDownloadDTO.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) ## 依赖关系分析 - 模块内依赖: - FileController -> FileApi -> IFileInfoService -> FileInfoMapper - FileApiImpl/FileInfoServiceImpl -> MinioConfig/FileProperties - FileInfoServiceImpl -> KkFileViewClient - 基础依赖: - MyBatis-Plus 配置(MybatisPlusConfig、MetaObjectFillHandler、SnowflakeIdWorker) - 全局异常处理与统一结果封装 ```mermaid classDiagram class FileController class FileApi class FileApiImpl class IFileInfoService class FileInfoServiceImpl class FileInfoMapper class MinioConfig class FileProperties class KkFileViewClient class FileInfo class FileInfoDTO FileController --> FileApi : "调用" FileApi <|.. FileApiImpl : "实现" FileApiImpl --> IFileInfoService : "委托" IFileInfoService <|.. FileInfoServiceImpl : "实现" FileInfoServiceImpl --> FileInfoMapper : "持久化" FileInfoServiceImpl --> MinioConfig : "配置" FileInfoServiceImpl --> FileProperties : "配置" FileInfoServiceImpl --> KkFileViewClient : "预览" FileInfoServiceImpl --> FileInfo : "实体" FileInfoServiceImpl --> FileInfoDTO : "数据传输" ``` 图表来源 - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [MinioConfig.java](file://crm-file/src/main/java/com/crm/file/config/MinioConfig.java) - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoDTO.java](file://crm-file/src/main/java/com/crm/file/domain/dto/FileInfoDTO.java) 章节来源 - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) ## 性能与索引优化 - 数据库索引建议: - 主键:雪花ID(SnowflakeIdWorker) - 常用查询列:所属者、业务类型、创建时间、状态、MD5 - 复合索引:(owner_id, biz_type, create_time) - 唯一索引:md5(去重校验) - 查询优化: - 分页查询使用合理页大小 - 避免 SELECT *,按需投影 - 大对象不入库,仅存元数据 - 上传优化: - 分片大小与并发数调优 - 启用断点续传与重试 - 缓存策略: - 热点文件元数据可缓存(Redis) - 预览 URL 短期缓存 章节来源 - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) ## 配置与容量规划 - 配置项建议: - MinIO Endpoint、AccessKey、SecretKey、Bucket、Region - 分片大小、最大分片数、超时时间 - 是否启用预览服务、预览服务地址 - 定时任务开关与执行周期 - 容量规划: - 预估年增量与峰值吞吐 - 冷热数据分离策略(热数据 SSD,冷数据 HDD/归档) - 副本与纠删码策略(MinIO 默认纠删码) - 生命周期与归档: - 90 天未访问转冷存储 - 180 天归档至低成本介质 - 365 天合规删除 章节来源 - [FileProperties.java](file://crm-file/src/main/java/com/crm/file/config/FileProperties.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java) ## 监控与可观测性 - 指标采集: - MinIO 指标(QPS、延迟、错误率、磁盘使用) - 应用指标(上传成功率、分片失败率、预览成功率) - 日志规范: - 统一 TraceId 贯穿请求链路 - 关键步骤打点(初始化、上传、合并、下载、预览) - 告警策略: - 上传失败率阈值 - 存储空间使用率阈值 - 预览服务不可用告警 章节来源 - [application.yml](file://crm-app/src/main/resources/application.yml) ## 故障排查指南 - 常见问题定位: - 连接失败:检查 MinIO 配置与网络连通性 - 权限不足:核对访问密钥权限与 Bucket 策略 - 分片上传失败:检查分片大小、超时与重试策略 - 预览失败:确认预览服务可达与文件格式支持 - 工具与手段: - 查看应用日志与 MinIO 审计日志 - 使用 MinIO 控制台验证对象存在性与元数据 - 通过统一结果封装与全局异常处理器定位错误码 章节来源 - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) ## 结论 本存储管理子系统以 MinIO 为核心,结合完善的元数据管理与第三方预览能力,提供了稳定高效的文件处理能力。通过合理的索引与配置、完善的监控与告警、清晰的生命周期与归档策略,可满足企业级文件存储需求。后续可按业务增长进行水平扩展与迁移升级。 ## 附录:数据模型与迁移建议 ### 数据模型(FileInfo 实体) ```mermaid erDiagram FILE_INFO { bigint id PK string file_name bigint size string mime_type string md5 string bucket string object_key bigint owner_id int status int version datetime created_at datetime updated_at } ``` 图表来源 - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) ### 迁移与扩展建议 - 横向扩展: - 多实例部署共享 MinIO,无状态化文件服务 - 引入消息队列异步处理预览与转码 - 迁移方案: - 使用 MinIO 官方迁移工具批量迁移历史数据 - 双写过渡期保证一致性,逐步切换流量 - 版本管理: - 启用 MinIO 版本控制,保留历史版本 - 元数据维护版本映射与回滚策略 章节来源 - [FileInfoMapper.java](file://crm-file/src/main/java/com/crm/file/mapper/FileInfoMapper.java) - [SchedulingConfig.java](file://crm-file/src/main/java/com/crm/file/config/SchedulingConfig.java)