【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

Minio的元数据 数据存储

MinIO对象存储系统没有元数据数据库,所有的操作都是对象级别的粒度的,这种做法的优势是:

个别对象的失效,不会溢出为更大级别的系统失效。

便于实现“强一致性”这个特性。此特性对于机器学习与大数据处理非常重要。

数据管理

元数据与数据一起存放在磁盘上:数据部分纠删分片以后存储在磁盘上,元数据以明文形式存放在元数据文件里(xl.json)。假定对象名字为obj-with-metadata, 它所在的桶的名字是bucket_name, disk是该对象所在纠删组的任一个磁盘的路径,如下目录:

disk/bucket_name/obj-with-metadata

记录了这个对象在此磁盘上的信息。其中的内容如下:

【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

xl.json

xl.json即是此对象的元数据文件。对象的元数据文件xl.json的内容是如下这种形式的json字符串:

【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

字段说明 format字段

该字段指明了这个对象的格式是xl,MinIO内部存储数据主要有两种数据格式:xl与fs。使用如下命令启动的MinIO使用的存储格式是fs:

【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

这种模式主要用于测试, 对象存储很多API都是并没有真正实现的桩函数。在生产环境所用的部署方式(本地分布式集群部署、联盟模式部署、云网关模式部署)中,存储格式都是xl。

part.1 :对象的第一个数据分片

stat字段

记录了此对象的状态,包括大小与修改时间,如下图:

【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

erasure字段

这个字段记录此对象与纠删码有关的信息,如下图:

【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

其中的algorithm指明了此对象采用的是Klaus Post实现的纠删码,生成矩阵是范德蒙矩阵。

data,parity指明了纠删组中数据盘、校验盘的个数。

blockSize 指明了对象被分块的大小,默认是5M(请参见上一节“数据分布与均衡”)。

index指明了当前磁盘在纠删组中的序号。

distribution:每个纠删组的数据盘、校验盘的个数是固定的,但是不同的对象的分片写入这个纠删组的不同磁盘的顺序是不同的。这里记录了分布顺序。

checksum:它下面的字段个数跟此对象的分片数量有关。在旧版本的MinIO对象存储系统,每一个分片经过hash函数计算出的checksum会记录在元数据文件的这个位置。最新版的MinIO会把checksum直接计入分片文件(即part.1等文件)的前32个字节。

此字段之下algorithm的值是”highwayhash256S”表明checksum值是写入分片文件的。

Minio的整合Java客户端

文件服务器在用minio,没有独立成微服务也没有抽取starter,所以简单测试一下集成和抽取starter,创建springboot项目集成minio把文件上传成功

Maven环境的pom依赖 <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>6.0.11</version> </dependency> spring的yml配置: minio: endpoint: :9000 accessKey: admin secretKey: 123123123 配置类 MinioProperties : @Data @ConfigurationProperties(prefix = "minio") public class MinioProperties { //连接url private String endpoint; //用户名 private String accessKey; //密码 private String secretKey; } 工具类 MinioUtil import cn.hutool.core.util.StrUtil; import com.team.common.core.constant.enums.BaseResultEnum; import com.team.common.core.exception.BusinessException; import io.minio.MinioClient; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; @AllArgsConstructor @Component public class MinioUtil { private final MinioClient minioClient; private final MinioProperties minioProperties; /** * http文件上传 * @param bucketName * @param file * @return 访问地址 */ public String putFile(String bucketName,MultipartFile file) { return this.putFile(bucketName,null,file); } /** * http文件上传(增加根路径) * @param bucketName * @param folder * @param file * @return 访问地址 */ public String putFile(String bucketName,String folder,MultipartFile file) { String originalFilename = file.getOriginalFilename(); if (StrUtil.isNotEmpty(folder)){ originalFilename = folder.concat("http://www.likecs.com/").concat(originalFilename); } try { InputStream in = file.getInputStream(); String contentType= file.getContentType(); minioClient.putObject(bucketName,originalFilename,in,null, null, null, contentType); } catch (Exception e) { e.printStackTrace(); throw new BusinessException(BaseResultEnum.SYSTEM_EXCEPTION.getCode(),"文件上传失败"); } String url = minioProperties.getEndpoint().concat("http://www.likecs.com/").concat(bucketName).concat("http://www.likecs.com/").concat(originalFilename); return url; } /** * 创建bucket * @param bucketName */ public void createBucket(String bucketName){ try { minioClient.makeBucket(bucketName); } catch (Exception e) { e.printStackTrace(); throw new BusinessException(BaseResultEnum.SYSTEM_EXCEPTION.getCode(),"创建bucket失败"); } } @SneakyThrows public String getBucketPolicy(String bucketName){ return minioClient.getBucketPolicy(bucketName); } } 装配类: import io.minio.MinioClient; import io.minio.errors.InvalidEndpointException; import io.minio.errors.InvalidPortException; import lombok.AllArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @AllArgsConstructor @Configuration @EnableConfigurationProperties(MinioProperties.class) public class MinioAutoConfiguration { private final MinioProperties minioProperties; @Bean public MinioClient minioClient() throws InvalidPortException, InvalidEndpointException { MinioClient client = new MinioClient(minioProperties.getEndpoint(),minioProperties.getAccessKey(),minioProperties.getSecretKey()); return client; } @ConditionalOnBean(MinioClient.class) @Bean public MinioUtil minioUtil(MinioClient minioClient,MinioProperties minioProperties) { return new MinioUtil(minioClient,minioProperties); } } spring.factories配置文件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzswyw.html