MinIO 对象存储服务

目录

MinIO 对象存储服务

MinIO 介绍

容器化支持

MinIO核心概念

Drive和Set

MinIO核心流程

数据编码

存储形式

上传和下载流程

MinIO的局限

局限1、搭建集群后,不允许扩容

局限2、大集群最大节点数为32

Docker容器启动

minIO spring boot starter

依赖

配置

 创建bucket

 存储文件

删除文件

获取文件

获取输入流

下载


 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

  1. 使用minIO单bucket存储获取删除对象(文件)
  2. 也可以获取对象输入流、直接写入输出流
  3. 支持多个bucket,也兼容v1.0.0的配置默认bucket
  4. 可创建删除bucket
  5. 可以删除文件
  6. 可自定义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

 存储文件

删除文件

获取文件

获取输入流

下载

 

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐