MinIo对象存储学习笔记

521 阅读4分钟

简要说明

最近在重构毕业设计,但是阿里云oss对接的服务器没有续费所以oss回调不能用,然后就找了另外的一个oss对象存储来代替阿里云的oss。

MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。

MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。

MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。

在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品。

以上是引用自官网的一段概述MinIo官方网站

搭建

笔者是基于docker进行服务搭建的,执行以下命令即可完成搭建。

docker pull minio/minio

docker run --name myminio -p 8789:9000 -itd 
--restart=always  
-v /etc/localtime:/etc/localtime
-v /home/mycontainers/myminio/data:/data
-v /home/mycontainers/myminio/config:/root/.minio --net mynetwork
-e "MINIO_ACCESS_KEY=minio" 
-e "MINIO_SECRET_KEY=minio123"
minio/minio:RELEASE.2021-06-17T00-10-46Z server /data

第一步:拉取MinIo镜像

第二步:docker启动minio容器

参数说明:

--restart:是否随着docker服务启动而启动

-v:将宿主机的目录挂载到容器里面,格式--》宿主机目录:容器内目录

-e:环境,此处指定了使用者的ACCESS_KEYSECRET_KEY

启动成功后,访问你对应的IP和端口即可,如下图

image.png

此UI界面非常的简洁。输入上面的key进入内部,如下图:

image.png

左边的是桶的名字,右边的文件是当前桶的对象文件,右下角是创建桶

依赖

基于传统Spring Boot架构的基础上仅仅添加一些以下依赖即可。

<!-- https://mvnrepository.com/artifact/io.minio/minio -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.0.3</version>
</dependency>

基础配置

@Configuration
public class minioConfig {
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;
    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder().endpoint(endpoint).credentials(accessKey,secretKey).build();
    }
}

基础接口

1. 验证桶是否存在

    @Test
    void bucketExists() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(minioFinal.bucketName).build();
        System.out.println(minioClient.bucketExists(bucketExistsArgs));
    }

2. 创建桶

 @Test
    void MakeBucketArgs() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        /**
         * 桶名字不能有大写
         */
        MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket("testbucket").build();
        minioClient.makeBucket(makeBucketArgs);

    }

ps:桶的名字不能大写,笔者尝试过驼峰命名,api会报异常,或者可以尝试一下在图型界面创建桶包含大写字母也会报错。

3. 列出所有的桶

 @Test
    void BucketList() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        List<Bucket> list = minioClient.listBuckets();
        for (Bucket bucket : list) {
            System.out.println(bucket.name());
        }
    }

4. 删除桶

 @Test
    void removeBucket() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        //必须桶为空才能删
        RemoveBucketArgs removeBucketArgs = RemoveBucketArgs.builder().bucket("temp").build();
        minioClient.removeBucket(removeBucketArgs);
    }

5. 列出某个存储桶中的所有对象

@Test
    void listObjects() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(minioFinal.bucketName).build();
        Iterable<Result<Item>> list = minioClient.listObjects(listObjectsArgs);
        for (Result<Item> result : list) {
            //获取到对象
            Item item = result.get();
            System.out.println(item.objectName());
            System.out.println(item.size());
        }
    }

6. 获取到对象

@Test
    void getObject() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(minioFinal.bucketName).object("新建文本文档.txt").build();
        InputStream stream = minioClient.getObject(getObjectArgs);
        // 读取输入流直到EOF并打印到控制台。
        byte[] buf = new byte[16384];
        int bytesRead;
        while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
            System.out.println(new String(buf, 0, bytesRead));
        }
        // 关闭流。
        stream.close();
    }

7. 下载对象

 @Test
    void downloadObject() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        DownloadObjectArgs downloadObjectArgs = DownloadObjectArgs.builder().bucket(minioFinal.bucketName).object("86231487_p0.jpg")
                .filename("D:\\86231487_p0.jpg").build();
        minioClient.downloadObject(downloadObjectArgs);
    }

8. 上传对象

 @PostMapping("/upload")
    public String upload(List<MultipartFile> file){
        try {
            for (MultipartFile f :file) {
                PutObjectArgs objectArgs = PutObjectArgs.builder().object(f.getOriginalFilename())
                        .bucket(minioFinal.bucketName)
                        .contentType(f.getContentType())
                        .stream(f.getInputStream(),f.getSize(),-1).build();
                minioClient.putObject(objectArgs);
            }
            return "ok";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

9. 复杂桶对象

@Test
    void copyObject() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        CopyObjectArgs copyObjectArgs = CopyObjectArgs.builder()
                //目标桶名
                .bucket(minioFinal.bucketName2)
                //目标对象名
                .object("justic2353.jpg")
                .source(
                        CopySource.builder()
                                //源桶名
                                .bucket(minioFinal.bucketName)
                                //源目标名称
                                .object("justic.jpg")
                                .build()
                ).build();
        minioClient.copyObject(copyObjectArgs);
    }

10. 删除对象

@Test
    void removeObject() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(minioFinal.bucketName2).object("justic2353.jpg").build();
        minioClient.removeObject(removeObjectArgs);
    }

11. 批量删除对象

 @Test
    void removeObjects() throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        List<DeleteObject> list = new ArrayList<>();
        list.add(new DeleteObject("006ywv2aly1h0x03vp341j31ww2pg7wh.jpg"));
        list.add(new DeleteObject("nacos_config_export_20220707215727.zip"));
        RemoveObjectsArgs removeObjectArgs = RemoveObjectsArgs.builder()
                .bucket(minioFinal.bucketName2)
                .objects(list).build();
        Iterable<Result<DeleteError> > results = minioClient.removeObjects(removeObjectArgs);
        System.out.println(results.iterator());
        for (Result<DeleteError> result : results) {
            System.out.println(result);
            DeleteError error = result.get();
            System.out.println(
                    "Error in deleting object " + error.objectName() + "; " + error.message());
        }
    }