【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南
Minio的元数据
数据存储
MinIO对象存储系统没有元数据数据库,所有的操作都是对象级别的粒度的,这种做法的优势是:
个别对象的失效,不会溢出为更大级别的系统失效。
便于实现“强一致性”这个特性。此特性对于机器学习与大数据处理非常重要。
数据管理
元数据与数据一起存放在磁盘上:数据部分纠删分片以后存储在磁盘上,元数据以明文形式存放在元数据文件里(xl.json)。假定对象名字为obj-with-metadata, 它所在的桶的名字是bucket_name, disk是该对象所在纠删组的任一个磁盘的路径,如下目录:
disk/bucket_name/obj-with-metadata
记录了这个对象在此磁盘上的信息。其中的内容如下:
xl.json
xl.json即是此对象的元数据文件。对象的元数据文件xl.json的内容是如下这种形式的json字符串:
字段说明
format字段
该字段指明了这个对象的格式是xl,MinIO内部存储数据主要有两种数据格式:xl与fs。使用如下命令启动的MinIO使用的存储格式是fs:
这种模式主要用于测试, 对象存储很多API都是并没有真正实现的桩函数。在生产环境所用的部署方式(本地分布式集群部署、联盟模式部署、云网关模式部署)中,存储格式都是xl。
part.1 :对象的第一个数据分片
stat字段
记录了此对象的状态,包括大小与修改时间,如下图:
erasure字段
这个字段记录此对象与纠删码有关的信息,如下图:
其中的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: http://192.168.8.50: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("/").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("/").concat(bucketName).concat("/").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配置文件
去掉主入口函数,去掉application.properties配置文件(新建一个测试用的springboot项目,把配置文件拿过去)
剩下最重要的一步:在resources下创建META-INF/spring.factories文件,配置文件中加入需要自动装配的类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.*(你的路径).MinioAutoConfiguration
demo:
import com.team.common.core.web.Result;
import com.team.common.minio.MinioUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@Api(value = "uploadFile", tags = "文件上传")
@RequestMapping("uploadFile")
@RestController
public class UploadFileController {
@Autowired
private MinioUtil minioUtil;
@ApiOperation(value = "通用文件上传")
@PutMapping("/upload")
public Result uploadFile(@ApiParam("存储桶名称") String bucketName,@ApiParam("文件") MultipartFile file) {
String url = null;
try {
url = minioUtil.putFile(bucketName,file);
} catch (Exception e) {
e.printStackTrace();
}
return Result.success(url);
}
}
打包安装到maven仓库,本地测试用的同一仓库地址的话可以直接maven install,新建一个springboot项目,填入application.properties,pom中增加starter的依赖。
<dependency>
<groupId>com.jxwy</groupId>
<artifactId>minio-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
其他OSS服务对比
厂商支持
国内使用Ceph的厂商、基于Ceph进行自研的存储厂商都比较多,在使用过程中遇到的问题(有些时候,甚至需要修改、增强乃至重新实现Ceph本身的功能),可以向相关厂商寻求支持。国际方面,Ceph早已被红帽收购,而红帽近期又被IBM收购。
MinIO开发与支持的厂商只有MinIO公司。由于架构比较先进,语言高级,MinIO本身的程序比较容易读懂、修改。招聘Golang程序员来 维护MinIO所花费的成本,显然低于招聘c++程序员来维护Ceph。
多语言客户端SDK
二者均有常见编程语言的客户端,比如:python, java等。MinIO对象存储软件的开发SDK另外支持纯函数式的语言Haskell。
技术文档
内部实现的文档MinIO基本不存在。想要了解内部实现乃至参与开发的技术人员,只能到如下社区:http://minio.slack.com/ ,与MinIO的开发人员直接交流,或者自己阅读代码。Ceph的各种实现文档、算法说明文档非常丰富。这方面Ceph要比MinIO成熟很多。
Ceph和MinIO的对比
开源对象存储软件以MinIO,Ceph为典型代表。为帮助相关人员在选择对象存储系统之时选择合适的产品,此处对二者的特点、特性做一定讨论。
MinIO优势
部署极其简单
MinIO系统的服务程序仅有minio一个可执行文件,基本不依赖其它共享库或者rpm/apt包。minio的配置项很少(大部分都是内核之类系统级的设置),甚至不配置也可以正常运行起来。百度、google、bing等搜索引擎上基本没有关于MinIO部署问题的网页,可见在实践中,很少有使用者遇到这方面的问题。
相比之下,Ceph系统的模块,相关的rpm、apt包众多,配置项非常多,难以部署,难调优。某些Linux发行版的Ceph安装包甚至有bug,需要使用者手动改动Ceph的python脚本,才能安装完毕。
二次开发容易
MinIO对象存储系统除了极少数代码使用汇编实现以外,全部使用Golang语言实现。Ceph系统是使用业界闻名的难学难用的c++语言编写的。Golang语言由于产生较晚,吸收了很多语言尤其是c++的教训,语言特性比较现代化。
相对而言,MinIO系统的维护、二次开发比较容易。
网管模式支持多种其他存储
通过网关模式,MinIO对象存储后端,可以对接各种现有的常见其它存储类型,比如的NAS系统,微软Azure Blob 存储、Google 云存储、HDFS、阿里巴巴OSS、亚马逊S3等,非常有利于企业复用现有资源,有利于企业低成本(硬件成本约等于零,部署MinIO对象存储软件即可)地从现有系统平滑升级到对象存储。
Ceph优势
数据冗余策略更加丰富,Ceph同时支持副本、纠删码,而MinIO只支持纠删码。对于个别的对于数据可靠性要求极高的单位,Ceph对象存储更加合适。
参考硬件
MinIO是符合软件定义存储SDS理念的,兼容主流X86服务器以及ARM/飞腾平台,同时也可以移植到诸如申威(Alpha架构)和龙芯(Mips架构)等硬件平台。
下面这些符合工业标准的、广泛采用的服务器是经过MinIO inc.优化测试过的、MinIO对象存储软件表现优异的服务器:
结论
由以上讨论,可见作为对象存储软件来说,MinIO, Ceph都非常优秀,各自有各自的优势。准备使用对象存储软件的用户,应该根据自己单位的需求、技术储备等实际情况,选择适当的软件。
参考资料
https://github.com/krishnasrinivas/wikinotes/wiki/minio-scaling
https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/Welcome.html
Klaus Post官网:https://klauspost.com/
https://min.io/resources/docs/MinIO-throughput-benchmarks-on-NVMe-SSD.pdf
https://github.com/minio/minio/blob/master/cmd/admin-heal-ops.go
https://github.com/klauspost/reedsolomon/blob/master/options.go
https://min.io/resources/docs/CPG-MinIO-implementation-guide.pdf
https://docs.min.io/docs/minio-bucket-notification-guide.html
【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南的更多相关文章
- 【SpringCloud技术专题】「Gateway网关系列」(3)微服务网关服务的Gateway全流程开发实践指南(2.2.X)
开发指南须知 本次实践主要在版本:2.2.0.BUILD-SNAPSHOT上进行构建,这个项目提供了构建在Spring生态系统之上API网关. Spring Cloud Gateway的介绍 Spri ...
- 【分布式技术专题】「Zookeeper中间件」给大家学习一下Zookeeper的”开发伴侣”—Curator-Framework(基础篇)
CuratorFramework基本介绍 CuratorFramework是Netflix公司开源的一套Zookeeper客户端框架,它作为一款优秀的ZooKeeper客户端开源工具,主要提供了对客户 ...
- 【Java技术专题】「性能优化系列」针对Java对象压缩及序列化技术的探索之路
序列化和反序列化 序列化就是指把对象转换为字节码: 对象传递和保存时,保证对象的完整性和可传递性.把对象转换为有字节码,以便在网络上传输或保存在本地文件中: 反序列化就是指把字节码恢复为对象: 根据字 ...
- 【Netty技术专题】「原理分析系列」Netty强大特性之ByteBuf零拷贝技术原理分析
零拷贝Zero-Copy 我们先来看下它的定义: "Zero-copy" describes computer operations in which the CPU does n ...
- ☕【难点攻克技术系列】「海量数据计算系列」如何使用BitMap在海量数据中对相应的进行去重、查找和排序
BitMap(位图)的介绍 BitMap从字面的意思,很多人认为是位图,其实准确的来说,翻译成基于位的映射,其中数据库中有一种索引就叫做位图索引. 在具有性能优化的数据结构中,大家使用最多的就是has ...
- ☕【Java深层系列】「并发编程系列」让我们一起探索一下CyclicBarrier的技术原理和源码分析
CyclicBarrier和CountDownLatch CyclicBarrier和CountDownLatch 都位于java.util.concurrent这个包下,其工作原理的核心要点: Cy ...
- 「数据挖掘入门系列」Python快速入门
Python环境搭建 本次入门系列将使用Python作为开发语言.要使用Python语言,我们先来搭建Python开发平台.我们将基于Python 2.7版本.以及Python的开发发行版本Anaco ...
- 「美团面试系列」面试加分项,这样说你会JVM,面试官还能问什么
Java性能调优都是老生常谈的问题,特别当“糙快猛”的开发模式大行其道时,随着系统访问量的增加.代码的臃肿,各种性能问题便会层出不穷. 比如,下面这些典型的性能问题,你肯定或多或少都遇到过: 在进行性 ...
- 分布式技术专题-分布式协议算法-带你彻底认识Paxos算法、Zab协议和Raft协议的原理和本质
内容简介指南 Paxo算法指南 Zab算法指南 Raft算法指南 Paxo算法指南 Paxos算法的背景 [Paxos算法]是莱斯利·兰伯特(Leslie Lamport)1990年提出的一种基于消息 ...
随机推荐
- python实现图像梯度
一,定义与作用 图像梯度作用:获取图像边缘信息 二,Sobel 算子与函数的使用 (1)Sobel 算子------来计算变化率 (2)Sobel函数的使用 (3-1)代码实现(分别): (3-2)代 ...
- Java包装类,以及Integer与int之间的比较
一.Java的基本类型 Java语言中提供了八种基本类型,包括六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. 整数型,包括byte.short.int.long,默认初始值是0 ...
- [bzoj3351]Regions
这道题有一种较为暴力的做法,对于每个点枚举所有与r2为该属性的询问并加以修改,最坏时间复杂度为o(nq),然而是可过的(97s) 发现只有当r2相同的询问数特别多时才会达到最坏时间复杂度,因此如果删除 ...
- 构建“元宇宙”,有哪些3D建模方式?
"沉浸.3D世界.虚拟社交.虚拟购物",最近"元宇宙"的概念特别火.人们畅想通过AR/VR以及其他互联网技术,把现实世界的楼房街道.天气温度.人际关系等投射到虚 ...
- Spring Cloud Gateway过滤器精确控制异常返回(实战,控制http返回码和message字段)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 前文<Spring Cloud Gat ...
- SpringCloud升级之路2020.0.x版-45. 实现公共日志记录
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 我们这一节在前面实现的带有链路信息的 Publisher 的工厂的基础上,实现公共日志记录 ...
- python3使用concurrent执行多进程任务
技术背景 随着计算机技术的发展,诸如GPU和超算平台等越来越发达,这些技术的本质其实并没有带来算法上的革新,之所以能够提升计算的速度和规模,很大程度上是因为分布式和并行计算的优势.这里我们介绍一个简单 ...
- 洛谷 P4663 - [BalticOI 2008]魔法石(dp)
题面传送门 A:我该是有多无聊来写这种题的题解啊 B:大概是因为这题题解区里没有题解所以我来写一篇了,说明我有高尚的济世情怀(大雾 跑题了跑题了 首先看到字典序第 \(i\) 小小可以自然地想到按位决 ...
- 如何根据fasta快速统计基因组大小及其各染色体长度?
基因组长度 利用seqkit统计长度 seqkit stat test.fa 结果如下: file format type num_seqs sum_len min_len avg_len max_l ...
- Linux三剑客之老三grep
说明: Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来.工作中我们常常用它来过滤出我们想要的数据. 格式: grep [OPTIONS] 基本参 ...