项目
博客
文档
归档
资源链接
关于我
项目
博客
文档
归档
资源链接
关于我
13| 分布式文件存储方案-MinIO部署&OSS文件上传
2024-07-31
·
·
原创
·
·
本文共 531个字,预计阅读需要 2分钟。
分布式文件系统(Distributed File System):通过计算机网络与节点相连,或是若干不同的逻辑磁盘分区组合在一起而形成的完整的有层次的文件系统 分布式文件系统高可用高性能设计思想:副本备份、双活、多活这种架构 - 通过复制协议将数据同步到多个存储节点,并确保多个副本之间的数据一致性,当某个存储节点出故障时,系统能够自动将服务切换到其他的副本 - CAP定理,高性能与高可用是矛盾的。 - 对性能的考虑,记录数据时先写一个份数据到某个机器上并立即返回,然后异步发起多个数据备份过程。容错性差,如果还没有来得及同步就宕机了,数据就丢失了。 - 同时写多个副本,每个副本写成功以后再返回,则又导致性能下降。取决于性能最差的那个同步。 选择:**高性能**的,允许部分丢失的,考虑第一种。**异步复制**。 **高可用**的,允许性能差一点的,考虑第二种。**同步多写的策略**。 RocketMQ消息高可用:**同步双写、异步刷盘,即同时写到两个节点上的内存才返回,然后异步持久化到磁盘里面** ### 分布式文件存储常见解决方案 - **MinIO**:Apache License v2.0 下发布的对象存储服务器。社区活跃但不够成熟。https://docs.min.io/cn/。特点:功能强大、可以根据业务做`二次的定制`,`新一代分布式文件存储系统`,`容器化结合`强大,免费,支持单机和集群部署。 - **FastDFS**:一个开源的轻量级分布式文件系统。没有官方文档,社区不怎么活跃。部署搭建复杂。 - 云厂商:阿里云OSS等。特点:开发简单,功能强大,`容易维护(不同网络下图片质量、水印、加密策略、扩容、加速`)。 **MinIO**搭建: - 查询minio镜像:docker search minio - 拉取镜像:docker pull minio/minio - 启动: ```shell docker run -p 9000:9000 \ --name minio_yuan \ -v /app/minio:/data \ -e "MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE" \ -e "MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \ minio/minio server /data ``` 使用: - 访问控制台 - 创建bucket - 上传文件 - 预览 ### 云服务OSS对象存储 特点:安全、低成本、高持久,高可用,RESTful API接口。提供标准、低频访问、归档和冷归档四种存储类型,全面覆盖从热到冷的各种数据存储场景 | 标准存储类型 | 高持久、高可用、高性能的对象存储服务,支持频繁的数据访问。是各种社交、分享类的图片、音视频应用、大型网站、大数据分析的合适选择。 | | ---------------- | ------------------------------------------------------------ | | 低频访问存储类型 | 适合长期保存不经常访问的数据(平均每月访问频率1到2次)。存储单价低于标准类型,适合各类移动应用、智能设备、企业数据的长期备份,支持实时数据访问。 | | 归档存储类型 | 适合需要长期保存(建议半年以上)的归档数据,在存储周期内极少被访问,数据进入到可读取状态需要1分钟的解冻时间。适合需要长期保存的档案数据、医疗影像、科学资料、影视素材。 | | 冷归档存储类型 | 适合需要超长时间存放的极冷数据。例如因合规要求需要长期留存的数据、大数据及人工智能领域长期积累的原始数据、影视行业长期留存的媒体资源、在线教育行业的归档视频等。 | 从**Access Key**进入,建立用户,勾选编程访问(保存**accessKey和accessSecret**,只出现一次) - accessKey: LTAI4FJR7bL6JSzBv7zx69J4 - accessSecret: CNfxHJeTTLlFQA2d2X5BpraqjK047l 使用阿里云 添加maven依赖 - 底层聚合工程添加版本 ```xml
com.aliyun.oss
aliyun-sdk-oss
3.10.2
``` - 用户微服务添加 ```xml
com.aliyun.oss
aliyun-sdk-oss
``` - 配置文件配置application.yml ```yaml #阿里云OSS配置 aliyun: oss: endpoint: oss-cn-beijing.aliyuncs.com #端点区域 北京 access-key-id: LTAI4FJR7bL6JSzBv7zx69J4 #accessKey access-key-secret: CNfxHJeTTLlFQA2d2X5BpraqjK047l #accessSecret bucketname: xx #Bucket名称 ``` - 新建配置类 (配置里面的横杠会,自动转驼峰) ```java @ConfigurationProperties(prefix = "aliyun.oss") @Configuration @Data public class OSSConfig { private String endpoint; private String accessKeyId; private String accessKeySecret; private String bucketname; } ``` 开发服务: ```java @Service @Slf4j public class FileServiceImpl implements FileService { @Resource private OSSConfig ossConfig; @Override public String uploadUserHeadImg(MultipartFile file) { String originalFilename = file.getOriginalFilename(); //获取相关配置 String bucketName = ossConfig.getBucketname(); String endpoint = ossConfig.getEndpoint(); String accessKeyId = ossConfig.getAccessKeyId(); String accessKeySecret = ossConfig.getAccessKeySecret(); //创建oss对象 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); //构建路径 LocalDateTime ldt = LocalDateTime.now(); DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd"); String folder = dtf.format(ldt); String fileName = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32); assert originalFilename != null; String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); //在oss上创建文件夹test路径 String newFileName = "test/" + folder + "/" + fileName + extension; try { PutObjectResult result = ossClient.putObject(bucketName, newFileName, file.getInputStream()); //返回访问路径 if (null != result) { return "https://" + bucketName + "." + endpoint + "/" + newFileName; } } catch (Exception e) { log.error("上传头像失败", e); } finally { // 关闭OSS服务 ossClient.shutdown(); } return null; } } ``` > 注意点: > > - `先上传文件,返回url地址`,再和普通表单一并提交(推荐这种,更加灵活,失败率低) > - 默认SpringBoot`最大文件上传是1M` > - @requestPart注解 接收文件以及其他更为复杂的数据类型。`@RequestPart("file") MultipartFile file` 文件上传请求 ```java @RestController @RequestMapping("/file/v1") @Slf4j public class FileController { @Resource private FileService fileService; @PostMapping(value = "/uploadFile", name = "上传文件") public JsonData uploadImage(MultipartFile file) { return JsonData.buildSuccess(fileService.uploadUserHeadImg(file)); } } ```