全栈开发那些事

全栈开发那些事

MinIO对象存储

2024-06-26
MinIO对象存储

1、MinIO简介

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

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


官方文档:

2、MinIO三种部署架构

  • 单主机单硬盘模式

    image-20230326230441846

  • 单主机多硬盘模式

    image-20230326230539064

  • 多主机多硬盘分布式

    image-20230326230611493

3、MinIO特点

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

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

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

  • Amazon S3兼容:Minio使用Amazon S3 v2 / v4 API。可以使用Minio SDKMinio ClientAWS SDKAWS CLI访问Minio服务器。

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

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

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

  • 有操作页面

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

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

4、存储机制

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

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


5、Docker安装MinIO

拉取镜像

docker pull minio/minio

之后查看下镜像是否拉取成功

docker images

image-20230326231351522

启动MinIO容器:

docker run \
  -p 9000:9000 \
  -p 9001:9001 \
  --name minio \
  -d --restart=always \
  -e "MINIO_ROOT_USER=admin" \
  -e "MINIO_ROOT_PASSWORD=admin123456" \
  -v /home/data:/data \
  -v /home/config:/root/.minio \
  minio/minio server /data --console-address ":9001"

image-20230326231452618

浏览器访问:http://localhost:192.168.159.141:9000/minio/login

image-20230326231545686

我们在上边容器启动的命令中指定了用户名为admin,密码为admin123456,这里输入点击登录,主界面如下

image-20230326231646204

这里能看到有Buckets是因为我之前创建过了。

6、利用Java客户端调用MinIO

参考文档:

https://docs.min.io/docs/java-client-api-reference.html

https://minio-java.min.io/

6.1 引入依赖

在自己的微服务模块中添加如下依赖:

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

6.2 添加配置文件

minio:
  endpointUrl: http://192.168.159.141:9000
  accessKey: admin
  secreKey: admin123456
  bucketName: gmall

我这里将配置文件写在了Nacos配置中心里面。

image-20230326232155766

6.3 创建FileUploadController控制器

@Api(tags = "文件上传控制器")
@RestController
@RequestMapping("/admin/product")
public class FileUploadController {

    //读取配置文件中的配置
    @Value("${minio.endpointUrl}")
    private String endpointUrl;

    @Value("${minio.accessKey}")
    private String accessKey;

    @Value("${minio.secreKey}")
    private String secreKey;

    @Value("${minio.bucketName}")
    private String bucketName;

    @ApiOperation("MinIO文件上传")
    @PostMapping("/fileUpload")
    public Result fileUpload(MultipartFile file) {
        String url="";

        try {
            // 创建minioClient客户端对象
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(endpointUrl)
                            .credentials(accessKey, secreKey)
                            .build();

            // 判断指定的桶是否存在
            boolean found =
                    minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                // 如果不存在指定的桶,创建
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            } else {
                System.out.println("Bucket " + bucketName + " already exists.");
            }
            //文件名称
            String fileName = System.currentTimeMillis() + UUID.randomUUID().toString();

            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                            file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());

            //拼接一个文件路径
             url=endpointUrl+"/"+bucketName+"/"+fileName;
            System.out.println("图片的路径:"+url);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.ok(url);
    }

}

这个控制器主要就是先检查有没有Buckets(存储桶),没有就先创建,然后执行文件上传操作,最后我们Controller需要将图片的访问路径返回给前端。

6.4 测试

其实这一步就基本写完了,后面的业务代码我就不放了,我直接用Swagger UI测试下,展示下效果就行。

image-20230326232545794

选择一个图片点击上传,响应结果如下:

image-20230326232653881

可以看到,data属性返回了我们的图片访问路径

我们在浏览器中直接访问这个url

image-20230326232752098

可以看到,没有任何的问题

我们在Buckets中也同样可以找到刚才上传的图片

image-20230326232920262


好了,到这一步,MinIO对象存储的基本使用就介绍完了,只剩下结合我们自己的业务去写邪物代码就行。

其实如果嫌自己搭建对象存储服务太麻烦的话,我以前也写过阿里云OSS和腾讯云OSS相关的文章,这些方式也非常方便。