MinIO 对象存储服务
MinIO 对象存储服务目录MinIO 对象存储服务MinIO 介绍Docker容器启动minIO spring boot starter依赖配置创建bucket存储文件删除文件获取文件获取输入流下载MinIO 介绍MinIO 是一个Golang 编写基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频
MinIO 对象存储服务
目录
MinIO 介绍
MinIO 是一个Golang 编写基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。
性能 MinIO号称是世界上速度最快的对象存储服务器。在标准硬件上,对象存储的读/写速度最高可以达到183 GB/s和171 GB/s
容器化支持
MinIO提供了与k8s、etcd、docker等容器化技术深度集成方案,可以说就是为了云环境而生的。这点是FastDFS不具备的。
MinIO核心概念
Drive和Set
- Drive:可以理解为一块磁盘
- Set:一组Drive的集合
- 默认由系统根据集群规模自动计算得出
- MINIO_ERASURE_SET_DRIVE_COUNT
- 一个对象存储在一个Set上
- 一个集群划分为多个Set
- 一个Set包含的Drive数量是固定的
- 一个SET中的Drive尽可能分布在不同的节点上
上图中,每一行是一个机器节点,这里有32个集群,每个节点里有一个小方块,我们称之为Drive,Drive可简单地理解为磁盘。一个节点有32个Drive,相当于32个磁盘。
Set是另外的概念,Set是一组Drive的集合,所有红色标识的Drive组成了一个Set。一个对象最终是存储在一个Set里面的。
MinIO核心流程
数据编码
Erasure Code:冗余编码
- 将一个对象编码成若干个数据块和校验块
- Reed-Solomon算法
- 低冗余、高可靠
MinIO的编码方式,我们简称为Erasure Code码,是通过算法还原数据的方法。MinIO使用Reed-Solomon算法,该算法把对象编码成若干个数据块和校验块。
为了表述方便,把数据库和校验块统称为编码块,之后我们可以通过编码块的一部分就能还原出整个对象。
如上图,如我们所知,一个对象存储在一个Set上面,这个Set包含16个Drive,其中灰色的一半是数据库,橙色的一半是校验块,这种方式最多能忍受一半的编码丢失或损坏。所有编码块的大小是原对象的2倍,跟传统多副本存储方案相比,他只冗余存了一份,但可靠性更高。
存储形式
上图直观地展示了每个节点上的数据存放形式。所有对象的编码块和meta信息,最终是以目录和文件的形式,存储在文件系统上的。
比如My Bucket就是在所有节点的顶级目录创建了对应的目录叫My Bucket。然后当我们上传一个对象的时候,就会在这个对象所对应的Set上面创建一个目录叫My Object,之后把所有编码块的数据跟meta信息都保存在此目录下面,这就是MinIO的真实存储数据的方式。
meta数据是json文件,编码块是part.1文件。黑色的右图是meta信息示例图,里面除了包含正常的meta信息外,还包括了怎样做ec编码,以便之后可以解码出来。
上传和下载流程
1、上传流程:
1)先根据对象名去做一个Hash,计算出对应的Set,然后来创建临时目录。创建临时目录的目的是为了确保数据强一致性,所以中间数据都会被写入到这个临时目录里(直到所有数据写完后,再统一把目录写入到最终的路径上)
2)接下来读数据编码,每次最多读10M的数据处理,然后做编码,再被写入到磁盘上,循环的过程就是把数据保存下来。
3)数据保存完后,再写meta信息。
4)然后挪到最终的位置上,删除临时目录。
2、读取流程:
1)先根据对象名做Hash,找到对象对应的Set
2)然后去读取meta信息,通过meta信息来获得编码的方式,然后去解码。它是以10M数据做EC编码,读的时候也是逐个part解析,每个part给他做解码,然后写入到一个io write里面。
备注:我们刚刚说了,做EC码时,只要一半的编码块就能还原整个对象,所以读meta时读了N份,但是读数据时只要读N/2就可以了。
MinIO的局限
局限1、搭建集群后,不允许扩容
MinIO一旦集群搭建成功后,就不可以更改集群节点数。因为存在在MinIO的对象到底存储在哪个Set,是通过名字做Hash去找的,一旦节点数变了落点就错乱了。
局限2、大集群最大节点数为32
MinIO实现了一个峰值锁叫DSync。它在节点数量少时,性能非常高;但节点数量过多时,性能就下降了。功能实现的最大节点就是32,所以导致MinIO单个集群的最大节点数也是32。
Docker容器启动
docker pull minio/minio
docker run -p 9000:9000 minio/minio server /data
启动后默认登录名为 minioadmin,密码为 minioadmin,也可以设置环境变量配置用户名、密码。
docker run -p 9000:9000 -e "MINIO_ACCESS_KEY=minioadmin" -e "MINIO_SECRET_KEY=minioadmin" -v /etc/localtime:/etc/localtime --name minio -d minio/minio server /data
访问 http://127.0.0.1:9000 .MinIO 的界面清爽、干净,体现了 MinIO 的极简理念。
minIO spring boot starter
https://gitee.com/yawensilence/minio-spring-boot-starter
- 使用minIO单bucket存储获取删除对象(文件)
- 也可以获取对象输入流、直接写入输出流
- 支持多个bucket,也兼容v1.0.0的配置默认bucket
- 可创建删除bucket
- 可以删除文件
- 可自定义minio客户端和缓存清理
依赖
<dependency>
<groupId>com.jvm123</groupId>
<artifactId>minio-spring-boot-starter</artifactId>
<version>1.2.1</version>
</dependency>
配置
file:
store:
minio:
endpoint: http://127.0.0.1:9000
bucket: test
access-key: minioadmin
secret-key: minioadmin
tmp-dir: ./tmp/
tmp-clean: true
tmp-first-clean-time: 2020-1-17 11:45:00
tmp-clean-period: 12960000
tmp-alive-duration: 12960000
如果不配置默认bucket,则需要在使用时指定。存储时指定的bucket如果不存在,则会自动创建。tmp-dir 为api中返回File类型的缓存目录,这个目录会按照FIFO规则定时清理。如果使用返回InputStream的api,则不会有缓存。
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
public class TestController {
@Autowired
MinioFileService fileStoreService;
@GetMapping("test2")
public void test2(HttpServletResponse response) throws IOException {
String bucketName = "demo-bucket";
// 创建bucket
boolean created = fileStoreService.createBucket(bucketName);
// 存储文件
String saved = fileStoreService.save(bucketName, new File("/Users/panjianl/Desktop/a.txt"), "a.txt");
// 删除文件
boolean deleted = fileStoreService.delete(bucketName, "a.txt");
// 获取文件
File file = fileStoreService.getFile(bucketName, "a.txt");
// 获取输入流
InputStream inputStream = fileStoreService.getStream(bucketName, "a.txt");
// 下载
response.addHeader("Content-Disposition","attachment;filename=a.txt");
ServletOutputStream os = response.getOutputStream();
fileStoreService.writeTo(bucketName, "a.txt", os);
}
}
创建bucket
存储文件
删除文件
获取文件
获取输入流
下载
更多推荐
所有评论(0)