MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合使用,它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。
它一大特点就是轻量,使用简单,功能强大,支持各种平台,单个文件最大5TB,兼容 Amazon S3接口,提供了 Java、Python、GO等多版本SDK支持。
MinIO集群采用去中心化共享架构,每个结点是对等关系,通过Nginx可对MinIO进行负载均衡访问。
去中心化有什么好处?
在大数据领域,通常的设计理念都是无中心和分布式。Minio分布式模式可以帮助你搭建一个高可用的对象存储服务,你可以使用这些存储设备,而不用考虑其真实物理位置。
它将分布在不同服务器上的多块硬盘组成一个对象存储服务。由于硬盘分布在不同的节点上,分布式Minio避免了单点故障。如下图:
Minio使用纠删码技术来保护数据,它是一种恢复丢失和损坏数据的数学算法,它将数据分块冗余的分散存储在各各节点的磁盘上,所有的可用磁盘组成一个集合,上图由8块硬盘组成一个集合,当上传一个文件时会通过纠删码算法计算对文件进行分块存储,除了将文件本身分成4个数据块,还会生成4个校验块,数据块和校验块会分散的存储在这8块硬盘上。
使用纠删码的好处是即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据。 比如上边集合中有4个以内的硬盘损害仍可保证数据恢复,不影响上传和下载,如果多于一半的硬盘坏了则无法恢复。
minio下载
中文:https://www.minio.org.cn/,http://docs.minio.org.cn/docs/
数据恢复演示
安装minio后进入minio的文件夹建立4个文件夹
在当前文件夹下进入cmd输入
minio.exe server B:\workspace\xuecheng\minio\data1 B:\workspace\xuecheng\minio\data2 B:\workspace\xuecheng\minio\data3 B:\workspace\xuecheng\minio\data4
启动minio
SQL |
1)老版本使用的MINIO_ACCESS_KEY 和 MINIO_SECRET_KEY不推荐使用,推荐使用MINIO_ROOT_USER 和MINIO_ROOT_PASSWORD设置账号和密码。
2)pool即minio节点组成的池子,当前有一个pool和4个硬盘组成的set集合
3)因为集合是4个硬盘,大于2的硬盘损坏数据将无法恢复。
4)账号和密码默认为minioadmin、minioadmin,可以在环境变量中设置通过'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' 进行设置。
下边输入http://localhost:9000进行登录,账号和密码为:minioadmin/minioadmin
下一步创建bucket,桶,它相当于存储文件的目录,可以创建若干的桶。
点击“upload”上传文件。
下边上传几个文件
下边去四个目录观察文件的存储情况
我们发现上传的1.mp4文件存储在了四个目录,即四个硬盘上。
下边测试minio的数据恢复过程:
1、首先删除一个目录。
删除目录后仍然可以在web控制台上传文件和下载文件。
稍等片刻删除的目录自动恢复。
2、删除两个目录。
删除两个目录也会自动恢复。
3、删除三个目录 。
由于 集合中共有4块硬盘,有大于一半的硬盘损坏数据无法恢复。
此时报错:We encountered an internal error, please try again. (Read failed. Insufficient number of drives online)在线驱动器数量不足。
在实际开发中一般会使用docker来创建minio容器
SDK
上传文件
MinIO提供多个语言版本SDK的支持,下边找到java版本的文档:
地址:https://docs.min.io/docs/java-client-quickstart-guide.html
最低需求Java 1.8或更高版本:
maven依赖如下:
XML |
在service工程添加此依赖。
参数说明:
需要三个参数才能连接到minio服务。
参数 | 说明 |
Endpoint | 对象存储服务的URL |
Access Key | Access key就像用户ID,可以唯一标识你的账户。 |
Secret Key | Secret key是你账户的密码。 |
官方的示例代码如下:
Java |
参考示例在media-service工程中 测试上传文件功能,
首先创建一个用于测试的bucket
点击“Manage”修改bucket的访问权限
选择public权限
在xuecheng-plus-media-service工程 的test下编写测试代码如下:
package com.xuecheng.media;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import org.junit.jupiter.api.Test;
public class MinioTest {
static MinioClient minioClient =
MinioClient.builder()
.endpoint("http://192.168.101.65:9000")
.credentials("minioadmin", "minioadmin")
.build();
@Test
void uploadTest(){
try {
UploadObjectArgs testbucket = UploadObjectArgs.builder()
.bucket("testbucket")//桶名
// .object("test001.mp4")//上传后的文件名
.object("001/test001.mp4")//添加子目录
.filename("D:\\develop\\upload\\1mp4.temp")//本地文件路径
.contentType("video/mp4")//默认根据扩展名确定文件内容类型,也可以指定
.build();
minioClient.uploadObject(testbucket);
System.out.println("上传成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("上传失败");
}
}
}
执行upload方法,分别测试向桶的根目录上传文件以及子目录上传文件。
上传成功,通过web控制台查看文件,并预览文件。
说明:
设置contentType可以通过com.j256.simplemagic.ContentType枚举类查看常用的mimeType(媒体类型)
通过拓展名来获取mimeType
在pom中引入依赖
<!--根据扩展名取mimetype-->
<dependency>
<groupId>com.j256.simplemagic</groupId>
<artifactId>simplemagic</artifactId>
<version>1.17</version>
</dependency>
通过扩展名得到mimeType,代码如下:
//根据扩展名取出mimeType
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");
String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字节流
完善上边的代码 如下:
@Test
public void upload() {
//根据扩展名取出mimeType
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");
String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字节流
if(extensionMatch!=null){
mimeType = extensionMatch.getMimeType();
}
try {
UploadObjectArgs testbucket = UploadObjectArgs.builder()
.bucket("testbucket")
// .object("test001.mp4")
.object("001/test001.mp4")//添加子目录
.filename("D:\\develop\\upload\\1mp4.temp")
.contentType(mimeType)//默认根据扩展名确定文件内容类型,也可以指定
.build();
minioClient.uploadObject(testbucket);
System.out.println("上传成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("上传失败");
}
}
删除文件
下边测试删除文件
参考:https://docs.min.io/docs/java-client-api-reference#removeObject
@Test
public void delete(){
RemoveObjectArgs testbucket = RemoveObjectArgs
.builder()
.bucket("testbucket")
.object("1.png")
.build();
try {
minioClient.removeObject(testbucket);
System.out.println("删除成功");
} catch (Exception e) {
e.printStackTrace();
System.out.println("删除失败");
}
}
查询文件
通过查询文件查看文件是否存在minio中。
参考:https://docs.min.io/docs/java-client-api-reference#getObject
//查询文件,并把文件保存到本地
@Test
public void getFile(){
GetObjectArgs getObjectArgs = GetObjectArgs
.builder()
.bucket("testbucket")
.object("001/1.png")
.build();
try {
//获取到目标文件的输入流对象
FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
//建立输出流对象,将文件输出到本地磁盘
FileOutputStream outputStream = new FileOutputStream(new File("B:\\workspace\\xuecheng\\minio\\1.png"));
IOUtils.copy(inputStream,outputStream);
}catch (Exception e){
e.printStackTrace();
}
}
校验文件的完整性,对文件计算出md5值,比较原始文件的md5和目标文件的md5,一致则说明完整
//校验文件的完整性对文件的内容进行md5
FileInputStream fileInputStream1 = new FileInputStream(new File("D:\\develop\\upload\\1.mp4"));
String source_md5 = DigestUtils.md5Hex(fileInputStream1);
FileInputStream fileInputStream = new FileInputStream(new File("D:\\develop\\upload\\1a.mp4"));
String local_md5 = DigestUtils.md5Hex(fileInputStream);
if(source_md5.equals(local_md5)){
System.out.println("下载成功");
}
在springboot程序中使用minio上传文件
在yaml中进行配置
minio:
endpoint: http://192.168.101.65:9000
accessKey: minioadmin
secretKey: minioadmin
bucket:
files: mediafiles
videofiles: video
写一个配置类将配置读出来
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.minioadmin}")
private String minioadmin;
public MinioClient minioClient(){
MinioClient minioClient = MinioClient
.builder()
.endpoint(endpoint)
.credentials(accessKey, minioadmin)
.build();
return minioClient;
}
}