1. MinIO介绍

MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。

​ MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。

​ 官方文档:http://docs.minio.org.cn/docs 旧一点

https://docs.min.io/

2. MinIO应用场景

2.1 单主机单硬盘模式

2.2 单主机多硬盘模式

2.3 多主机多硬盘分布式

3. MinIO特点

高性能:作为高性能对象存储,在标准硬件条件下它能达到55GB/s的读、35GB/s的写速率

可扩容:不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并跨越多个数据中心

云原生:容器化、基于K8S的编排、多租户支持

Amazon S3兼容:Minio使用Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI访问Minio服务器。

可对接后端存储: 除了Minio自己的文件系统,还支持DAS、 JBODs、NAS、Google云存储和Azure Blob存储。

SDK支持: 基于Minio轻量的特点,它得到类似Java、Python或Go等语言的sdk支持

Lambda计算: Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。

有操作页面

功能简单: 这一设计原则让MinIO不容易出错、更快启动

支持纠删码:MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据

4. 存储机制

Minio使用纠删码erasure code和校验和checksum。 即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据。

纠删码是一种恢复丢失和损坏数据的数学算法

5. docker安装MinIO

  • 首先下载MinIO的Docker镜像:

    先说下版本选择,这个可以自己去dockerhub上查看版本

    由于minio更新迭代比较快,所以根据自己需要来选择版本,我用的是RELEASE.2022-09-22T18-57-27Z.fips这个版本

    docker pull minio/minio:RELEASE.2022-09-22T18-57-27Z.fips

  • 下载完成后使用如下命令运行MinIO服务,注意使用--console-address指定MinIO Console的运行端口(否则会随机端口运行):
  • docker run \
      -p 9000:9000 \
      -p 9001:9001 \
      --name minio \
      -d --restart=always \
      -e "MINIO_ROOT_USER=admin" \
      -e "MINIO_ROOT_PASSWORD=admin123456" \
      -v /mydata/minio/data:/data \
      -v /mydata/minio/config:/root/.minio \
      minio/minio:RELEASE.2022-09-22T18-57-27Z.fips server /data --console-address ":9001"
    

    6. docker-compose安装MinIO

    version: '3'
    services:
      minio:
        image: minio/minio:RELEASE.2022-09-22T18-57-27Z.fips
        container_name: minio
        environment:
          MINIO_ROOT_USER: admin
          MINIO_ROOT_PASSWORD: admin123456
        command:  server /data --console-address ":9001"
        volumes:
          - /mydata/minio/data:/data
          - /mydata/minio/config:/root/.minio
        ports:
          - 9000:9000
          - 9001:9001
    
  • 运行成功后就可访问MinIO Console的管理界面了,输入账号密码admin:admin123456即可登录,访问地址:http://192.168.86.101:9000

    7. MinIO Console使用

    MinIO Console是MinIO自带的可视化管理工具,新版的功能还是很强大的。不仅支持了存储桶、文件的管理,还增加了用户、权限、日志等管理功能。

    8. 客户端使用

    其实对于对象存储来说,MinIO Console的功能还是不够用的,所以官方还提供了基于命令行的客户端MinIO Client(简称mc),下面我们来讲讲它的使用方法。

    8.1 常用命令

    我们先来熟悉下mc的命令,这些命令和Linux中的命令有很多相似之处。

  • 运行完成后我们需要进行配置,将我们自己的MinIO服务配置到客户端上去,配置的格式如下
  • mc config host add <ALIAS> <YOUR-S3-ENDPOINT> <YOUR-ACCESS-KEY> <YOUR-SECRET-KEY>
    
  • 对于我们的MinIO服务可以这样配置
  • mc config host add minio http://192.168.86.101:9000 admin admin123456
    

    8.3 常用操作

    下面这些就用macro大神的教程,我就不继续实操了,我本地没有装客户端,因为通过console控制台管理足够日常使用了

  • 查看存储桶和查看存储桶中存在的文件
  • # 查看存储桶
    mc ls minio
    # 查看存储桶中存在的文件
    mc ls minio/blog
    
  • 创建一个名为test的存储桶
  • mc mb minio/test
    
  • 共享avatar.png文件的下载路径
  • mc share download minio/blog/avatar.png
    
  • 查找blog存储桶中的png文件
  • mc find minio/blog --name "*.png"
    
  • 设置test存储桶的访问权限为只读
  • # 目前可以设置这四种权限:none, download, upload, public
    mc policy set download minio/test/
    # 查看存储桶当前权限
    mc policy list minio/test/
    

    9. 兼容AWS S3

    当我们对接第三方服务要用到对象存储时,这些服务往往都是支持AWS S3的。比如说一个直播的回放功能,需要对象存储来存储回放的视频,由于MinIO兼容AWS S3的大多数API,我们可以直接拿它当AWS S3来使用。

  • 我们可以下载个AWS S3的客户端来试试,MinIO到底能不能支持S3的API,这里使用的是S3 Browser,下载地址:https://s3browser.com/
  • 安装好S3 Browser之后,添加一个Account,输入相关登录信息,注意选择Account类型为S3 Compatible Storage
  • 连接成功后,我们可以看见之前我们创建的存储桶和上传的文件
  • S3 Browser这个工具功能还是很强大的
  • 如果你想修改存储桶的访问权限的话直接通过Permissions标签修改即可。
  • 10. 利用Java客户端调用MinIO

    参考文档:https://docs.min.io/docs/java-client-api-reference.html

    10.1 引入依赖

    在service-product模块中添加依赖

    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.2.0</version>
    </dependency>
    

    10.2 添加配置文件

    minio:
      endpointUrl: http://IP:9000
      accessKey: admin
      secreKey: admin123456
      bucketName: file
    

    10.3 编写java程序

    @RestController
    @RequestMapping("admin/product")
    public class FileUploadController {
        //  获取文件上传对应的地址
        @Value("${minio.endpointUrl}")
        public String endpointUrl;
        @Value("${minio.accessKey}")
        public String accessKey;
        @Value("${minio.secreKey}")
        public String secreKey;
        @Value("${minio.bucketName}")
        public String bucketName;
        //  文件上传控制器
        @PostMapping("fileUpload")
        public Result fileUpload(MultipartFile file) throws Exception{
            //  准备获取到上传的文件路径!
            String url = "";
            // 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
            // MinioClient minioClient = new MinioClient("https://play.min.io", "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG");
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(endpointUrl)
                            .credentials(accessKey, secreKey)
                            .build();
            // 检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if(isExist) {
                System.out.println("Bucket already exists.");
            } else {
                // 创建一个名为asiatrip的存储桶,用于存储照片的zip文件。
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(bucketName)
                        .build());
            //  定义一个文件的名称 : 文件上传的时候,名称不能重复!
            String fileName = System.currentTimeMillis()+ UUID.randomUUID().toString();
            // 使用putObject上传一个文件到存储桶中。
            //  minioClient.putObject("asiatrip","asiaphotos.zip", "/home/user/Photos/asiaphotos.zip");
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                            file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());
            //  System.out.println("/home/user/Photos/asiaphotos.zip is successfully uploaded as asiaphotos.zip to `asiatrip` bucket.");
            //  文件上传之后的路径: http://192.168.86.101:9000/file/xxxxxx
            url = endpointUrl+"/"+bucketName+"/"+fileName;
            System.out.println("url:\t"+url);
            //  将文件上传之后的路径返回给页面!
            return Result.ok(url);