MinIO介绍部署与springboot集成

进入新的项目团队,在文件存储方面使用minio工具,因此网上查找相关资料以及结合项目对minio使用情况,学习minio相关知识、特性、应用场景、存储架构以及基础概念,并在此基础上,本地实际部署搭建minio服务,并集成进springboot项目进行使用,于此进行记录,以便后续深入学习,同时也为后来者提供参考借鉴,文中不免疏漏之处,望读者给予指正!

1. MinIO基本信息

MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从数KB到最大5TB都能很好的支持。开源并且用Go语言开发,有web操作界面,我们可以用它来搭建兼容S3协议的存储云服务。相比 hadoop hdfs 分布式存储服务轻量很多,且支持单节点部署。

对象存储:
对象存储服务OSS(Object Storage Service)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

2. MinIO特性

1)高性能
MinIO 是全球领先的对象存储先锋,目前在全世界有数百万的用户. 在标准硬件上,读/写速度上高达183 GB / 秒 和 171 GB / 秒。
对象存储可以充当主存储层,以处理Spark、Presto、TensorFlow、H2O.ai等各种复杂工作负载以及成为Hadoop HDFS的替代品。
MinIO用作云原生应用程序的主要存储,与传统对象存储相比,云原生应用程序需要更高的吞吐量和更低的延迟。而这些都是MinIO能够达成的性能指标。

2)可扩展性
MinIO利用了Web缩放器的来之不易的知识,为对象存储带来了简单的缩放模型。 这是我们坚定的理念 “简单可扩展.” 在 MinIO, 扩展从单个群集开始,该群集可以与其他MinIO群集联合以创建全局名称空间, 并在需要时可以跨越多个不同的数据中心。 通过添加更多集群可以扩展名称空间, 更多机架,直到实现目标。

3)云的原生支持
MinIO 是在过去4年的时间内从0开始打造的一款软件 ,符合一切原生云计算的架构和构建过程,并且包含最新的云计算的全新的技术和概念。 其中包括支持Kubernetes 、微服和多租户的的容器技术。使对象存储对于 Kubernetes更加友好。

4)与Amazon S3 兼容
亚马逊云的 S3 API(接口协议) 是在全球范围内达到共识的对象存储的协议,是全世界内大家都认可的标准。 MinIO 在很早的时候就采用了 S3 兼容协议,并且MinIO 是第一个支持 S3 Select 的产品. MinIO对其兼容性的全面性感到自豪, 并且得到了 750多个组织的认同, 包括Microsoft Azure使用MinIO的S3网关 - 这一指标超过其他同类产品的总和。

5)简单
极简主义是MinIO的指导性设计原则。简单性减少了出错的机会,提高了正常运行时间,提供了可靠性,同时简单性又是性能的基础。 只需下载一个二进制文件然后执行,即可在几分钟内安装和配置MinIO。 配置选项和变体的数量保持在最低限度,这样让失败的配置概率降低到接近于0的水平。 MinIO升级是通过一个简单命令完成的,这个命令可以无中断的完成MinIO的升级,并且不需要停机即可完成升级操作 - 降低总使用和运维成本。

3. 应用场景

MinIO 的应用场景除了可以作为私有云的对象存储服务来使用,也可以作为云对象存储的网关层,无缝对接 Amazon S3 或者 MicroSoft Azure 。
在这里插入图片描述

4. 存储架构

Minio针对不同应用场景也设置了对应的存储架构:

4.1 单主机,单硬盘模式

该模式下,Minio只在一台服务器上搭建服务,且数据都存在单块磁盘上,该模式存在单点风险,主要用作开发、测试等使用
启动的命令为:

minio --config-dir ~/tenant1 server --address :9001 /disk1/data/tenant1

4.2 单主机,多硬盘模式

该模式下,Minio在一台服务器上搭建服务,但数据分散在多块(大于4块)磁盘上,提供了数据上的安全保障

minio --config-dir ~/tenant1 server --address :9001 /disk1/data/tenant1 /disk2/data/tena

4.3 多主机、多硬盘模式(分布式)

该模式是Minio服务最常用的架构,通过共享一个access_key和secret_key,在多台(2-32)服务器上搭建服务,且数据分散在多块(大于4块,无上限)磁盘上,提供了较为强大的数据冗余机制(Reed-Solomon纠删码)。

export MINIO_ACCESS_KEY=<TENANT1_ACCESS_KEY>
export MINIO_SECRET_KEY=<TENANT1_SECRET_KEY>
minio --config-dir ~/tenant1 server --address :9001 http://192.168.10.11/data/tenant1 ht

分布式优点:
在大数据领域,通常的设计理念都是无中心和分布式。Minio分布式模式可以帮助搭建一个高可用的对象存储服务,你可以使用这些存储设备,而不用考虑其真实物理位置。
1)数据保护
分布式Minio采用 纠删码来防范多个节点宕机和位衰减bit rot。
分布式Minio至少需要4个硬盘,使用分布式Minio自动引入了纠删码功能。
2)高可用
单机Minio服务存在单点故障,相反,如果是一个有N块硬盘的分布式Minio, 只要有N/2硬盘在线,你的数据就是安全的。
不过你需要至少有N/2+1个硬盘来创建新的对象。

例如,一个16节点的Minio集群,每个节点16块硬盘,就算8台服務器宕机,这个集群仍然是可读的,不过你需要9台服務器才能写数据。

注意,只要遵守分布式Minio的限制,你可以组合不同的节点和每个节点几块硬盘。
比如,你可以使用2个节点,每个节点4块硬盘,也可以使用4个节点,每个节点两块硬盘,诸如此类。

3)一致性
Minio在分布式和单机模式下,所有读写操作都严格遵守read-after-write一致性模型。
4)MinIO的数据高可靠
Minio使用了Erasure Code 纠删码和 Bit Rot Protection 数据腐化保护这两个特性,所以MinIO的数据可靠性做的高。

5. 基础概念

1)Object:存储到 Minio 的基本对象,如文件、字节流,Anything…

2)Bucket:用来存储 Object 的逻辑空间。每个 Bucket 之间的数据是相互隔离的。对于客户端而言,就相当于一个存放文件的顶层文件夹。

3)Drive:即存储数据的磁盘,在 MinIO 启动时,以参数的方式传入。Minio 中所有的对象数据都会存储在 Drive 里。

4)Set
即一组 Drive 的集合,分布式部署根据集群规模自动划分一个或多个 Set ,每个 Set 中的 Drive 分布在不同位置。一个对象存储在一个 Set 上。(For example: {1…64} is divided into 4 sets each of size 16.)

一个对象存储在一个Set上
一个集群划分为多个Set
一个Set包含的Drive数量是固定的,默认由系统根据集群规模自动计算得出
一个SET中的Drive尽可能分布在不同的节点上

Set /Drive 的关系:
Set /Drive 这两个概念是 MINIO 里面最重要的两个概念,一个对象最终是存储在 Set 上面的。
一个节点机器可以包含多个硬盘,Drive为节点里的一块可以简单理解为一个硬盘,Set是一组跨节点的多个Drive 的集合.

5)Minio写入对象过程:
MINIO 是通过数据编码,将原来的数据编码成 N 份,N 就是一个 Set 上面 Drive 的数量,后面多次提到的 N 都是指这个意思。
对象被编码成N份之后,把每一份,写到对应的 Drive 上面,这就是把一个对象存储在整个 Set 上。
一个集群包含多个 Set,每个对象最终存储在哪个 Set 上是根据对象的名称进行哈希,然后影射到唯一的 Set 上面,这个方式从理论上保证数据可以均匀的分布到所有的 Set 上。

根据的观测,数据分布的也非常均匀,一个 Set 上包含多少个 Drive 是由系统自动根据集群规模算出来的,当然,也可以自己去配置。

一个 Set 的 Drive 系统会考虑尽可能把它放在多的节点上面,保证它的可靠性。

6. 部署

MinIO支持单机部署、多租户部署、分布式部署。支持原始文件存储已经纠删码模式存储。单机部署时,可使用minio的客户端工具进行备份。

6.1 二进制方式部署

部署环境:Ubuntu 20.04.2 LTS
系统架构:amd64(uname -a或arch命令可查看系统架构,注:x86_64,x64,AMD64基本上是同一个东西)

使用以下命令在运行 64 位 Intel/AMD 架构的 Linux 主机上运行独立的 MinIO 服务器。将/data 替换为您希望 MinIO 存储数据的驱动器或目录的路径。

wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
./minio server /data

64-bit Intel/AMD、64-bit ARM、64-bit PowerPC LE (ppc64le)、IBM Z-Series (S390X)不同架构对应的安装包在https://dl.min.io/server/minio/release/下自行查找

参数–console-address “:9001” 可指定浏览器访问端口
在这里插入图片描述

6.2 Docker方式部署

1)拉取镜像

docker pull minio/minio

2)运行镜像MinIO:

docker run -p 9000:9000 -p 9001:9001 --name minio \
  -v /etc/localtime:/etc/localtime \
  -v /data/minio/data:/data \
  -v /data/minio/config:/root/.minio \
  -d minio/minio server /data --console-address ":9001"

6.3 控制台访问设置

浏览器访问 http://192.168.109.130:44561/ 账户密码 minioadmin/minioadmin
在这里插入图片描述
在这里插入图片描述

1)创建桶:进入系统后,我们先要点击右下角的“+”按钮,创建一个文件桶(输入名称后,回车即可),在上传文件到这个文件桶中。Create bucket(创建文件桶)、Upload file(上传文件),这里我创建了一个桶test,上传了一张图片

在这里插入图片描述
2)上传的文件,在文件列表界面有一个分享按钮,点击分享将生成文件的访问URL地址,以指定链接的有效时间,有效时间最多7天,最小的单位是分钟。在有效时间过期后在访问图片时,会提示失效。
在这里插入图片描述
在这里插入图片描述
3)bucket访问策略
桶默认可以有三种Access Policy策略:public、custom、private
策略public:不经过任何认证可以直接访问资源
策略private:未经授权不能进行任何操作
策略customer:通过如下自定义Access Rules出现的,readonley/writeonly/readwrite

增加customer后 Access Policy自动设置为customer,customer全都删除后,Access Policy自动设置为private;

在这里插入图片描述
在这里插入图片描述

7. Springboot集成使用

7.1 引入jar包

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

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.6</version>
</dependency>

7.2 增加配置

platform:
  oss:
    endpoint: http://192.168.109.130:9000
    accessKeyId: minioadmin
    accessKeySecret: minioadmin
    bucketName: tduck-cloud
    domain: http://192.168.109.130:9000/tduck-cloud

7.3 代码集成

@Data
@Component
@Slf4j
@ConfigurationProperties(prefix = "platform.oss")
public class OssStorageConfig {

    /**
     * oss 类型
     * 参考 OssTypeEnum.java
     */
    private OssTypeEnum ossType;

    /**
     * 阿里云:endpoint
     */
    private String endpoint;

    /**
     * accessKeyId
     */
    private String accessKeyId;

    /**
     * accessKeySecret
     */
    private String accessKeySecret;

    /**
     * 桶名
     */
    private String bucketName;

    /**
     * 预览域名
     */
    private String domain;
    
    /**
     * 本地存储文件存放地址
     */
    private String uploadFolder;
    
    /**
     * 本地存储文件访问路径
     */
    private String accessPathPattern;
}


@Component
public class MIniOStorageService {

    private MinioClient client;

    public MIniOStorageService(OssStorageConfig config) {
        this.config = config;
        //初始化
        init();
    }

    private void init() {
        try {
            client = new MinioClient(config.getEndpoint(), config.getAccessKeyId(), config.getAccessKeySecret(), false);
        } catch (InvalidEndpointException e) {
            e.printStackTrace();
        } catch (InvalidPortException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String upload(InputStream inputStream, String path) {
        try {
            PutObjectOptions poo = new PutObjectOptions(inputStream.available(), -1);
            poo.setContentType(MimeTypeEnum.getContentType(path));
            client.putObject(config.getBucketName(), path, inputStream, poo);
        } catch (Exception e) {
            throw new StorageException("上传文件失败,请检查配置信息", e);
        }
        return config.getDomain() + "/" + path;
    }

    @Override
    public String upload(byte[] data, String path) {
        try {
            PutObjectOptions poo = new PutObjectOptions(data.length, -1);
            poo.setContentType(MimeTypeEnum.getContentType(path));
            client.putObject(config.getBucketName(), path, new ByteArrayInputStream(data), poo);
        } catch (Exception e) {
            throw new StorageException("上传文件失败,请检查配置信息", e);
        }
        return config.getDomain() + "/" + path;
    }

    @Override
    public void delete(String path) {
        try {
            client.removeObject(config.getBucketName(), path);
        } catch (Exception e) {
            throw new StorageException("删除文件失败", e);
        }
    }
}


    @Autowired
    private MIniOStorageService mIniOStorageService;

    /**
     * 上传用户文件
     * <p>
     * 用户Id MD5加密 同一个用户的文件放在一个目录下
     *
     * @param file
     * @param userId
     * @return
     * @throws IOException
     */
    @PostMapping("/user/file/upload")
    public Result<String> uploadUserFile(@RequestParam("file") MultipartFile file, @RequestAttribute Long userId) throws IOException {
        String path = new StringBuffer(SecureUtil.md5(String.valueOf(userId)))
                .append(CharUtil.SLASH)
                .append(IdUtil.simpleUUID())
                .append(CharUtil.DOT)
                .append(FileUtil.extName(file.getOriginalFilename())).toString();
        String url = mIniOStorageService.upload(file.getInputStream(),path);
        return Result.success(url);
    }

8. 参考资料

http://www.minio.org.cn/
http://docs.minio.org.cn/docs/
https://blog.csdn.net/lj15559275886/article/details/121441031
https://blog.csdn.net/crazymakercircle/article/details/120855464

猜你喜欢

转载自blog.csdn.net/shy871/article/details/121967656