当前位置: 首页 > news >正文

第5节:分布式文件存储

本节主要是讲解的是分布式文件存储,主要介绍了阿里云OSS云存储和Minio文件存储,本章重点主要是掌握怎么在SpringBoot项目里面接入文件存储。

记录、交流、实践,让每一份付出皆可看见,让你我共同前行😁

1.分布式文件存储高性能高可用讲解

1.1 核心知识介绍

  • 数据存储背景:数据量持续攀升,存储单位从 KB、MB、GB、TB、PB 到 ZB 级别,涵盖图片、文档、素材、静态页面、音视频、安装包等各类文件。
  • 业务应用内存储问题:传统 javaweb 项目文件量增长后,会占用大量内存、磁盘和带宽,无法满足海量请求,存在开发易但扩容难的问题。
  • 分布式文件系统(Distributed File System)
    • 定义:文件系统管理的物理存储资源通过计算机网络与节点相连,或由不同逻辑磁盘分区组合形成层次化文件系统。
    • 特点:自研的分布式文件系统扩容容易,但开发难度大。

1.2 如何保证分布式存储的高性能与高可用?

  • 常见思路:采用副本备份、双活、多活等架构,通过复制协议同步数据到多个存储节点,确保数据一致性,故障时自动切换服务。
  • 性能与高可用的矛盾(基于 CAP 定理)
    • 异步复制:先写一份数据到某机器并立即返回,再异步备份。性能好,但存在容错风险(如未同步时节点宕机导致数据丢失)。
    • 同步多写:同时写多个副本,全部成功后返回。保证数据一致性,但性能受最慢机器影响,性能下降。
  • 选择依据
    • 若要求高性能,可接受偶尔文件丢失或访问出错,选异步复制。
    • 若要求高可用,需保证数据一致性,选同步多写,牺牲部分性能。
  • 类似案例:RocketMQ 消息高可用采用同步双写、异步刷盘策略,即同时写到两个节点内存后返回,再异步持久化到磁盘。

1.3 分布式文件存储业界常见解决方案介绍

解决方案

特点

MinIO

Apache License v2.0 下的对象存储服务器,学习、安装运维简单,支持主流语言客户端整合,可与容器化技术结合,社区活跃但不够成熟,参考资料少

FastDFS

开源轻量级分布式文件系统,客户端少(主要 C 和 java),在互联网创业公司应用较多,无官方文档,社区不活跃,架构和部署复杂,问题定位难

云厂商(阿里云 OSS、七牛云、腾讯云、亚马逊云等)

优点:开发简单,功能强大,易维护(支持不同网络下图片质量、水印、加密、扩容、加速等);缺点:收费,个性化处理和未来转移复杂(部分厂商提供一键迁移)

CDN(Akamai)

在 CDN 领域表现突出

2.Minio

官方网站: MinIO | 企业级高性能对象存储 - MinIO 对象存储

2.1 环境安装

docker run -d -p 9111:9111 -p 9112:9112 --name guslegend_minio \
-e "MINIO_ROOT_USER=XXX" \
-e "MINIO_ROOT_PASSWORD=XXX" \
-v /dev-ops/minio/data:/data \
-v /dev-ops/minio/config:/root/.minio \
minio/minio:RELEASE.2025-04-22T22-12-26Z server /data --console-address ":9112" --address ":9111"

步骤

  1. 访问控制台
  2. 创建 bucket
  3. 上传文件
  4. 预览

总结

MinIO 操作流畅,支持单机和集群部署。对于不能或不使用云厂商存储服务的场景,可自建 MinIO 对象存储集群。

2.2 项目配置

在父文件夹的pom文件中添加maven依赖,并且在用户服务里面也添加。

 <!-- Minio各个项目单独加依赖,根据需要进行添加--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.2</version></dependency>

微服务配置minio

minio:endpoint: http://localhost:9111accesskey: secretKey: bucketname: 

创建MinioConfig配置类

@Data
@ConfigurationProperties(prefix = "minio")
@Component
public class MinioConfig {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketname;
}

2.3 编码实战

service层开发

    @Overridepublic String uploadFileByMinio(MultipartFile file) {try {MinioClient minioClient = MinioClient.builder().endpoint(minioConfig.getEndpoint()).credentials(minioConfig.getAccessKeyId(), minioConfig.getAccessKeySecret()).build();//判断桶是否存在boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioConfig.getBucketname()).build());if (!found) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioConfig.getBucketname()).build());}else {log.info("{}桶,存在",minioConfig.getBucketname());}//设置存储对象的名称String folder= String.format("%s",LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));String fileName = CommonUtil.generateUUID();String newFileName = folder+fileName+file.getOriginalFilename();PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(minioConfig.getBucketname()).stream(file.getInputStream(), file.getSize(),-1).object(newFileName).build();minioClient.putObject(putObjectArgs);String imgUrl =minioConfig.getEndpoint()+"/"+minioConfig.getBucketname()+"."+newFileName;log.info("文件上传地址为:{}",imgUrl);return imgUrl;} catch (Exception e) {log.error("文件上传失败:{}",e);}return null;}

controller层开发

    @PostMapping("upload_by_minio")public JsonData uploadHearImgByMinio(MultipartFile file){String result = fileService.uploadFileByMinio(file);return result!=null?JsonData.buildSuccess(result):JsonData.buildResult(BizCodeEnum.FILE_UPLOAD_USER_IMG_FAIL);}

3.阿里云OSS

官方网站:对象存储_云存储服务_企业数据管理_存储-阿里云

3.1 项目配置

在父文件夹的pom文件中添加maven依赖,并且在用户服务里面也添加。

 <!-- OSS各个项目单独加依赖,根据需要进行添加--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency>

在用户服务配置配置文件

aliyun:oss:endpoint: XXXaccess-key-id: XXXaccess-key-secret: XXXbucketname: XXX

创建OSSConfig配置类

@ConfigurationProperties(prefix = "aliyun.oss")
@Configuration
@Data
public class OSSConfig {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketName;
}

3.2 编码实战

UUID随机生成工具类开发

   /*** UUID* @return*/public static String generateUUID() {return UUID.randomUUID().toString().replace("-", "");}

service层编写

@Slf4j
@Service
public class FileServiceImpl implements FileService {@Autowiredprivate OSSConfig ossConfig;@Overridepublic String uploadFile(MultipartFile file) {String originalFileName = file.getOriginalFilename();//相关配置String endpoint = ossConfig.getEndpoint();String accessKeyId = ossConfig.getAccessKeyId();String accessKeySecret = ossConfig.getAccessKeySecret();String bucketName = ossConfig.getBucketName();//创建OSS对象OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);LocalDateTime localDateTime = LocalDateTime.now();DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");String folder = localDateTime.format(formatter);String fileName = CommonUtil.generateUUID();String extension = originalFileName.substring(originalFileName.lastIndexOf("."));//在OSS创建shop-user文件夹String newFileName = "shop-user/"+folder+"/"+fileName+"."+extension;try {PutObjectResult result = ossClient.putObject(bucketName, newFileName, file.getInputStream());//访问路径if (null!=result){String imgUrl = "https://"+bucketName+"."+endpoint+"/"+newFileName;return imgUrl;}} catch (Exception e) {log.error("头像上传失败",e);}finally {//关闭OSS对象ossClient.shutdown();}return null;}
}

controller层编写

@RestController
@RequestMapping("/api/user/v1")
public class UserController {@Autowiredprivate FileService fileService;/*** 上传用户头像* @param file* @return*/@PostMapping("upload")public JsonData uploadHearImg(MultipartFile file){String result = fileService.uploadFile(file);return result!=null?JsonData.buildSuccess(result):JsonData.buildResult(BizCodeEnum.FILE_UPLOAD_USER_IMG_FAIL);}
}


文章转载自:

http://Jkt6uTe9.ydwsg.cn
http://iNs1ahZ7.ydwsg.cn
http://awt2JIfc.ydwsg.cn
http://WmLCmFgl.ydwsg.cn
http://l6PDxbHZ.ydwsg.cn
http://7IgiLjpU.ydwsg.cn
http://RG83oby5.ydwsg.cn
http://nQVbFPuC.ydwsg.cn
http://WECX1OPf.ydwsg.cn
http://AWur1beC.ydwsg.cn
http://UyAXJtdY.ydwsg.cn
http://CuqX9to5.ydwsg.cn
http://aSFbSf4Q.ydwsg.cn
http://Jnp3bxvk.ydwsg.cn
http://75E2PVqg.ydwsg.cn
http://K9v907um.ydwsg.cn
http://kKEX57wx.ydwsg.cn
http://dO8sxwo9.ydwsg.cn
http://0LC3hNnM.ydwsg.cn
http://8ssew0gy.ydwsg.cn
http://U8LHGmBQ.ydwsg.cn
http://I6wWuTSA.ydwsg.cn
http://QhW5gLSV.ydwsg.cn
http://8tUpPVtA.ydwsg.cn
http://MTiMkJ66.ydwsg.cn
http://I0dRz354.ydwsg.cn
http://NdxBJ27y.ydwsg.cn
http://gguXF7kT.ydwsg.cn
http://SgD5emxQ.ydwsg.cn
http://u1zMpuDQ.ydwsg.cn
http://www.dtcms.com/a/362449.html

相关文章:

  • Nginx 全攻略:从部署到精通的实战指南(CentOS 环境)
  • CentOS 7/8 单用户模式重置 root 密码完整流程
  • 解析ELK(filebeat+logstash+elasticsearch+kibana)日志系统原理以及k8s集群日志采集过程
  • 鸿蒙HarmonyOS应用开发者认证:抢占万物智联时代先机
  • C++之基于正倒排索引的Boost搜索引擎项目介绍
  • mac 本地安装maven环境
  • hadoop 框架 jar下载
  • Python面试题及详细答案150道(91-100) -- 迭代器与生成器篇
  • 大数据生态系统全景图:Hadoop、Spark、Flink、Hive、Kafka 的关系
  • 传统大数据 Hadoop 和 云原生湖仓 Databend 对比
  • 科学研究系统性思维的方法体系:数据分析方法
  • 【AI - nlp】Transformer输入部分要点
  • 3dmax烘培插件3dmax法线贴图烘焙教程glb和gltf元宇宙灯光效果图烘焙烘焙光影贴图支持VR渲染器
  • 为什么同步是无线通信的灵魂?WiFi 与 5G 帧结构中的关键技术
  • 10G网速不是梦!5G-A如何“榨干”毫米波,跑出比5G快10倍的速度?
  • 为什么神经网络网络算法比机器学习模型算法更加强大?
  • 神经网络|(十八)概率论基础知识-伽马函数溯源-阶乘的积分表达式
  • 如何将大疆无人机拍摄到的图像回传到应急指挥中心大屏?5G单兵图传轻松解决图传问题|伟博视讯
  • Java基础(十):关键字static详解
  • 一文带你入门 AT 指令集:从串口通信到模块控制
  • 【Qt开发】按钮类控件(二)-> QRadioButton
  • lua脚本在redis中执行是否是原子性?
  • 每次开机弹出‘killer network manager launcher’链接无应用打开”解决方案
  • 【Lua】题目小练13
  • CodeForge v25.0.3 发布:Web 技术栈全覆盖,编辑器个性化定制新时代
  • 分页功能设计
  • Docker镜像指南:从核心命令到离线迁移实战
  • 实时视频链路的产业化路径:多场景应用与长期思考
  • 力扣:2458. 移除子树后的二叉树高度(dfs序)
  • leetcode111. 二叉树的最小深度