详解minio分布式文件存储

 更新时间:2023年10月07日 10:55:48   作者:小月亮6  
MinIO 是一款基于 Go 语言的高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品,这篇文章主要介绍了minio分布式文件存储,需要的朋友可以参考下

基本介绍

什么是  MinIO        

 MinIO 是一款基于 Go 语言的高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品。基于 Apache License v2.0 开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如 NodeJS、Redis、MySQL 等。

官网:www.minio.org.cn/

MinIO  特点

  • 高性能:作为高性能对象存储,在标准硬件条件下它能达到55GB/s的读、35GG/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的磁盘也能恢复数据

docker 安装 minio

下载镜像(最新版本)

docker pull minio/minio

查看已经下载的镜像

docker images

创建并启动minIO容器:
这里的 \ 指的是命令还没有输入完,还需要继续输入命令,先不要执行的意思。
这里的9090端口指的是minio的客户端端口。虽然设置9090,但是我们在访问9000的时候,他也会自动跳到9090。
9000端口是minio的服务端端口,我们程序在连接minio的时候,就是通过这个端口来连接的。
-v就是docker run当中的挂载,这里的/usr/local/mydata/minio/data:/data意思就是将容器的/data目录和宿主机的/mydata/minio/data目录做映射,这样我们想要查看容器的文件的时候,就不需要看容器当中的文件了。
注意在执行命令的时候,他是会自动在宿主机当中创建目录的。我们不需要手动创建。
minio所上传的文件默认都是存储在容器的data目录下的!
假如删除容器了宿主机当中挂载的目录是不会删除的。假如没有使用-v挂载目录,那他在宿主机的存储位置的文件会直接删除的。
宿主机的挂载目录一定是根目录,如果是相对路径会有问题。还有容器当中的目录也是必须是绝对路径(根路径就是带/的)。
所谓的挂载其实就是将容器目录和宿主机目录进行绑定了,操作宿主机目录,容器目录也会变化,操作容器目录,宿主机目录也会变化。这样做的目的 可以间接理解为就是数据持久化,防止容器误删,导致数据丢失的情况。
MINIO_ACCESS_KEY:账号 MINIO_SECRET_KEY:密码 (正常账号应该不低于3位,密码不低于8位,不然容器会启动不成功)
–console-address 指定客户端端口
-d --restart=always 代表重启linux的时候容器自动启动
–name minio 容器名称

 docker run -p 9000:9000 -p 9090:9090  --name minio  -d --restart=always  -e "MINIO_ACCESS_KEY=minioadmin"  -e "MINIO_SECRET_KEY=minioadmin"  -v /usr/local/mydata/minio/data:/data  minio/minio server  /data --console-address ":9090" -address ":9000"

springboot集成minio

一、配置yml文件

#yml配置文件增加如下配置
minio:
  endpoint: http://ip:9000
  fileUploadUrl: http://ip:9000
  accessKey: minioadmin (用户名)
  secretKey: minioadmin (密码)
  bucketName: file (文件组:桶名)

二、引入pom(8与7的方法不适用,以下使用8.0.3)

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

三、系统加载minio配置

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;
    @Bean
    public MinioClient minioClient()  {
        MinioClient minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
        return minioClient;
    }
}

四、minio工具类(上传文件,返回访问链接)

package org;
import cn.hutool.core.io.FastByteArrayOutputStream;
import com.alibaba.fastjson.JSONObject;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
 * 功能描述 文件服务器工具类
 *
 * @author: 
 * @date: 
 */
@Component
public class MinioUtil {
    @Resource
    private MinioClient minioClient;
    /**
     * 查看存储bucket是否存在
     * @return boolean
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            //e.printStackTrace();
            return false;
        }
        return found;
    }
    /**
     * 创建存储bucket
     * @return Boolean
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 删除存储bucket
     * @return Boolean
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 获取全部bucket
     */
    public List<Bucket> getAllBuckets() {
        try {
            return minioClient.listBuckets();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 文件上传
     * @param file 文件
     * @return Boolean
     */
    public Boolean upload(String bucketName, String fileName, MultipartFile file, InputStream inputStream) {
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
                    .stream(inputStream,file.getSize(),-1).contentType(file.getContentType()).build();
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 预览图片
     * @param fileName
     * @return
     */
    public String preview(String fileName,String bucketName){
        // 查看文件地址
        GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(bucketName).object(fileName).method(Method.GET).build();
        try {
            String url = minioClient.getPresignedObjectUrl(build);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 文件下载
     * @param fileName 文件名称
     * @param res response
     * @return Boolean
     */
    public void download(String fileName,String bucketName, HttpServletResponse res) {
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
                .object(fileName).build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)){
            byte[] buf = new byte[1024];
            int len;
            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){
                while ((len=response.read(buf))!=-1){
                    os.write(buf,0,len);
                }
                os.flush();
                byte[] bytes = os.toByteArray();
                res.setCharacterEncoding("utf-8");
                //设置强制下载不打开
                //res.setContentType("application/force-download");
                res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                try (ServletOutputStream stream = res.getOutputStream()){
                    stream.write(bytes);
                    stream.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 查看文件对象
     * @return 存储bucket内文件对象信息
     */
    public List<Item> listObjects(String bucketName) {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).build());
        List<Item> items = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                items.add(result.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return items;
    }
    /**
     * 删除
     * @param fileName
     * @return
     * @throws Exception
     */
    public boolean remove(String fileName,String bucketName){
        try {
            minioClient.removeObject( RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
        }catch (Exception e){
            return false;
        }
        return true;
    }
    /**
     * 批量删除文件对象(没测试)
     * @param objects 对象名称集合
     */
    public Iterable<Result<DeleteError>> removeObjects(List<String> objects, String bucketName) {
        List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
        return results;
    }
    //上传文件,返回路径
    public Object upload(HashMap<String, Object> paramMap) {
        MultipartFile file=(MultipartFile)paramMap.get("file");
        if (file.isEmpty() || file.getSize() == 0) {
            return "文件为空";
        }
        try {
            if (!this.bucketExists("file")) {
                this.makeBucket("file");
            }
            InputStream inputStream = file.getInputStream();
            String fileName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString().replaceAll("-", "")
                    + fileName.substring(fileName.lastIndexOf("."));
            this.upload("file", newName,file, inputStream);
            inputStream.close();
            String fileUrl = this.preview(newName,"file");
            String fileUrlNew=fileUrl.substring(0, fileUrl.indexOf("?"));
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("url",fileUrlNew);
            return jsonObject.toJSONString();
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败";
        }
    }
}

项目中实践

到此这篇关于minio分布式文件存储的文章就介绍到这了,更多相关minio分布式文件存储内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go项目配置管理神器之viper的介绍与使用详解

    Go项目配置管理神器之viper的介绍与使用详解

    viper是一个完整的 Go应用程序的配置解决方案,它被设计为在应用程序中工作,并能处理所有类型的配置需求和格式,下面这篇文章主要给大家介绍了关于Go项目配置管理神器之viper的介绍与使用,需要的朋友可以参考下
    2023-02-02
  • Go中init()执行顺序详解

    Go中init()执行顺序详解

    go允许定义多个init(),多个init()会涉及到执行先后的问题,本文将详细讲解Go中init()执行顺序,感兴趣的朋友一起看看吧
    2022-09-09
  • Go 语言 JSON 标准库的使用

    Go 语言 JSON 标准库的使用

    今天通过本文给大家介绍Go 语言 JSON 标准库的使用小结,包括序列化和反序列化的相关知识,感兴趣的朋友跟随小编一起看看吧
    2021-10-10
  • Go依赖注入工具wire的具体使用

    Go依赖注入工具wire的具体使用

    本文主要介绍了Go依赖注入工具wire的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • vscode如何debug调试golang代码

    vscode如何debug调试golang代码

    古话说工欲善其事必先利其器,Go语言程序的开发者而言,当下最火的IDE应该非微软的Visual Studio Code莫属,本文主要介绍了vscode如何debug调试golang代码,感兴趣的可以了解一下
    2024-03-03
  • gin通过go build -tags实现json包切换及库分析

    gin通过go build -tags实现json包切换及库分析

    这篇文章主要为大家介绍了gin通过go build -tags实现json包切换及库分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 详解golang中bufio包的实现原理

    详解golang中bufio包的实现原理

    这篇文章主要介绍了详解golang中bufio包的实现原理,通过分析golang中bufio包的源码,来了解为什么bufio能够提高文件读写的效率和速度
    2018-01-01
  • Golang中实现数据脱敏处理的go-mask包分享

    Golang中实现数据脱敏处理的go-mask包分享

    这篇文章主要是来和大家分享一个在输出中对敏感数据进行脱敏的工作包:go-mask,可以将敏感信息输出的时候替换成星号或其他字符,感兴趣的小编可以跟随小编一起了解下
    2023-05-05
  • Go语言变量的声明实现示例

    Go语言变量的声明实现示例

    本文主要介绍了Go语言变量的声明实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-03-03
  • Go语言字符串基础示例详解

    Go语言字符串基础示例详解

    这篇文章主要为大家介绍了Go语言字符串基础的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11

最新评论