持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情
Minio存储系统&SpringBoot整合Minio
前言:假如要对系统文件进行存储的话,可以有几种选择:第三方的oss(Object Storage Service)服务,如阿里oss、七牛oss、腾讯等以及自己搭建S3文件服务(minio、FastDFS )。使用第三方系统进行文件存储的好处是便捷、拿来即用且无运维成本。但当涉及敏感文件时,使用第三方文件服务就会有数据泄露的问题,毕竟数据是在第三方公司服务器上。基于这样的场景,我们就得搭建私有云对象存储服务。
1、Minio官方介绍
MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。
MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。
MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。
在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品
知识补充:
什么是S3:Simple Storage Service即简单存储服务,是亚马逊于2006年推出的(Amazon S3 ),此后新老厂商一窝蜂地推出各种产品,形态各异,但都号称对象存储。亚马逊没有给出一个定义,也没有看到有业界普通接受的说法。Amazon S3是⼀个公开的云存储服务,Web 应⽤程序开发⼈员可以使⽤它存储数字资产,包括图⽚、视频、⾳乐和⽂档。S3 提供⼀个 RESTful API 以编程⽅式实现与该服务的交互。Amazon 是最早的对象存储服务厂商,制定文件存储相关的业内标准,即S3协议(Minio 支持s3协议)。
通过 S3 存储和检索的资产被称为对象。对象存储在存储段(bucket) 中。您可以用硬盘进行类比:对象就像是文件,存储段就像是文件夹(或目录)。与硬盘一样,对象和存储段也可以通过统一资源标识符(Uniform Resource Identifier,URI)查找。
1.1、MINIO的基础概念
- Object:存储到Minio的基本对象,如文件、字节流等
- Bucket:用来存储Object的逻辑空间。每个Bucket之间的数据是相互隔离的。对于客户端而言,就相当于一个存储文件的顶层文件夹。
- Drive:即存储数据的磁盘,在MinIO启动时,以参数的方式传入。Minio中所有的对象都会存储在Drive里
- Set:即一组Drive的集合,分布式部署根据集群规模自动划分一个或多个Set,每个Set的Drive分布在不同的位置。一个对象存储在一个Set上
1.2、纠删码EC(Erasure Code)
MinIO使用纠删码机制来保住高可靠性,使用highwayhash来处理数据损坏(Bit Rot Protection)。关于纠删码,简单来说就是可以通过数学计算,把丢失的数据进行还原,它可以将n份原始数据,增加m份数据,并能通过n+m份中的任意n份数据,还原为原始数据。即如果有任意小于等于m份的数据丢失。仍然能通过剩下的数据还原出来。其实就是纠删码将对象拆分为一半数据,一半是奇偶校验块,任意丢失一般磁盘都可以进行数据恢复。
2、实验环境
-
docker
-
minio: (minio/minio:RELEASE.2021-06-17T00-10-46Z)
- 文档:docs.min.io/docs/java-c…
- 备注:因为最新版是有坑的,所以我实际部署的是2021版的,只是截图截了最新版的。
-
vmware
-
github地址:github.com/minio/minio
3、minio安装
- 拉取镜像
docker pull minio/minio:RELEASE.2021-06-17T00-10-46Z.hotfix.35a0912ff
- 创建容器
# 普通部署
docker run -p 9000:9000 -p 9001:9001 -d
--name minio
-v /opt/docker/minio/data:/data
-v /opt/docker/minio/config:/root/.minio
-e "MINIO_ROOT_USER=minio"
-e "MINIO_ROOT_PASSWORD=minio@12345" minio/minio server /data
--console-address ":9000" --address ":9001"
# 纠错码模式部署(使用这个)
docker run --name minio \
-p 9000:9000 \
-d \
-e "MINIO_ACCESS_KEY=minio" \
-e "MINIO_SECRET_KEY=minio@123456" \
-v /opt/docker/minio/data1:/data1 \
-v /opt/docker/minio/data2:/data2 \
-v /opt/docker/minio/data3:/data3 \
-v /opt/docker/minio/data4:/data4 \
-v /opt/docker/minio/config:/root/.minio \
minio/minio:RELEASE.2021-06-17T00-10-46Z.hotfix.35a0912ff \
server /data1 /data2 /data3 /data4
- 现在的数据卷结构
-
创建bucket
Buckets(水桶):MinIO 使用桶来组织对象。存储桶类似于文件系统中的文件夹或目录,其中每个存储桶可以保存任意数量的对象。
- 创建三个bucket
- 再次查看数据卷
- 在test-bucket1上传3个文件,再次查看数据卷
- 查看数据卷,可以看到每个drive(data1、data2...)里的bucket都备份了一份数据
- 查看里面存储的数据,可以看到,data1、data4是原数据,data2、data3是经过算法处理的。同时,若上传的文件大的话就会产生part1、part2...文件,分块存储
3、Java整合minio
3.1、与Spring集成的依赖
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.3.70</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.1</version>
<exclusions>
<exclusion>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
</exclusion>
</exclusions>
</dependency>
3.2、控制台例子
- 基础操作,详细请看代码。更多的操作请看官方例子
- 代码位置:ppz.minio.minio.demo.ConsoleDemo
// 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
MinioClient minioClient =
MinioClient.builder()
.endpoint("http://192.168.138.130:9000")
.credentials("minio", "minio@123456")
.build();
// 获取桶列表
List<Bucket> bucketList = minioClient.listBuckets();
for (Bucket bucket : bucketList) {
System.out.println(bucket.creationDate() + ", " + bucket.name());
}
// 判断桶bucket3是否存在,不存在则新建
boolean found =
minioClient.bucketExists(BucketExistsArgs.builder().bucket("bucket3").build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket("bucket3").build());
} else {
System.out.println("Bucket 'bucket3' already exists.");
}
// 上传文件 默认情况下,如果已存在同名Object且对该Object有访问权限,则新添加的Object将覆盖原有的Object,并返回200 OK
{
// Upload 'my-filename' as object 'my-objectname' in 'my-bucketname'.
ObjectWriteResponse uploadResponse = minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket("bucket3")
.object("test-object.jpg")
.filename("test.jpg")
.contentType("image/jpeg")
.build());
System.out.println("test.jpg is uploaded to bucket3 successfully");
}
// 获取文件url,该url一天后过期
{
String url =
minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket("bucket3")
.object("test.jpg")
.expiry(60 * 60 * 24)
.build());
System.out.println("url:"+url);
}
// 下载文件
{
String downloadPath = "D:\test-object.jpg";
minioClient.downloadObject(
DownloadObjectArgs.builder()
.bucket("bucket3")
.object("test-object.jpg")
.filename(downloadPath)
.build());
System.out.println("test-object.jpg is successfully downloaded to " + downloadPath);
}
// 删除文件
{
minioClient.removeObject(
RemoveObjectArgs.builder().bucket("bucket3").object("test-object.jpg")
.build());
System.out.println("remove test-object.jpg successfully");
}
3.2、SpringBoot整合Minio-sdk
- 其实都差不多的,具体看官网例子套进去就好
@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {
@Autowired
private MinioProperties minioProperties;
@Bean
public MinioClient minioClient(){
return MinioClient.builder()
.endpoint(minioProperties.getEndpoint())
.credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())
.build();
}
}
@Service
public class MinioService {
@Autowired
private MinioClient minioClient;
public String getUrl(String bucket, String objectName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
String url =
minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(objectName)
.expiry(60 * 60 * 24)
.build());
return url;
}
/**
* 创建bucket
*/
public void createBucket(String bucketName) throws Exception {
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
}
// ...
}
3.3、码云地址
4、坑爹:
- minio迭代非常快第一次部署时用的是lastest的,即RELEASE.2022-05-08T23-50-31Z.hotfix.a8c39d7cb
- 连接本地api时一直报SignatureDoesNotMatch等错误,然后最新的jar包是和springboot的包有冲突,然后换了旧版之后就没问题了,坑都给踩平了,请放心食用