【Java互联网技术】MinIO分布式文件存储服务

应用场景

互联网海量非结构化数据的存储

基本概念

Object:存储的基本对象,如文件、字节流等

Bucket:存储Object的逻辑空间,相当于顶层文件夹

Drive:存储数据的磁盘,在MinIO启动时,以参数的方式传入

Set:多个Drive的集合。分布式部署时划分一个或多个Set,一个Object存在Set上,Set中的每个Drive中都会有相同的Object

特点

  • 部署简单,整体只有一个二进制文件,还可支持各种平台
  • 支持海量存储,单个对象最大可达5TB
  • 兼容Amazon S3接口,充分考虑开发人员的需求和体验
  • 低冗余且磁盘损坏高容忍
  • 读写性能优异(HDD在16个结点的MinIO集群的读速度可达10GB/s,写速度可达8.5GB/s)

纠删码

Erasure Code(EC)。MinIO使用纠删码来保证高可靠性,使用highwayhash来处理数据损坏。n份原始数据保存后会生成m份纠删码算法转换后的数据,当有任意小于等于m份的数据损坏,就能通过剩下的额数据还原出来。

存储形式

文件上传到MinIO后,存储在对应的磁盘中,以Bucket名称为目录,文件名为下一级目录,这个目录下保存文件的编码数据块、校验块、元数据文件(json格式)

Docker部署MinIO(普通模式)

1、拉取镜像

docker pull minio/minio

2、创建挂载目录

mkdir /wanfeng/minio/data
mkdir /wanfeng/minio/config

3、运行容器

docker run -p 9000:9000 -p 9001:9001 --name wanfeng_minio --privileged=true \
-e "MINIO_ROOT_USER=登录用户名" \
-e "MINIO_ROOT_PASSWORD=登录密码" \
-v /wanfeng/minio/data:/data \
-v /wanfeng/minio/config:/root/.minio \
-d minio/minio server /data --console-address ":9001"
  • -p 9000:9000 -p 9001:9001:必须暴露出两个端口用户客户端和服务端
  • MINIO_ROOT_USER:用户名
  • MINIO_ROOT_PASSWORD:密码
  • /wanfeng/minio/data:/data:数据文件映射目录
  • /wanfeng/minio/config:/root/.minio:配置文件映射目录
  • –console-address “:9001”:指定服务端端口号(通过该端口访问minio服务)

Docker部署MinIO(纠删码模式)

纠删码的作用就是在上传一份数据后,会生成n个原始数据块和n个奇偶校验块,若任意丢失不超过n块盘,都可以进行数据恢复。

1、在docker启动时增加多块盘

docker run -p 9000:9000 -p 9001:9001 --name wanfeng_minio --privileged=true \
-e "MINIO_ROOT_USER=登录用户名" \
-e "MINIO_ROOT_PASSWORD=密码" \
-v /wanfeng/minio/config:/root/.minio \
-v /wanfeng/minio/data1:/data1 \
-v /wanfeng/minio/data2:/data2 \
-v /wanfeng/minio/data3:/data3 \
-v /wanfeng/minio/data4:/data4 \
-v /wanfeng/minio/data5:/data5 \
-v /wanfeng/minio/data6:/data6 \
-d minio/minio server /data{1...6} --console-address ":9001"

Docker部署MinIO(分布式集群)

分布式集群可以避免单台服务器故障带来的影响(单点故障),将minio

Java API整合MinIO

1、引入依赖

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

<!-- https://mvnrepository.com/artifact/me.tongfei/progressbar -->
<dependency>
    <groupId>me.tongfei</groupId>
    <artifactId>progressbar</artifactId>
    <version>0.5.3</version>
</dependency>

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.10.0</version>
</dependency>

2、API使用

@SpringBootTest
public class MinioApplicationTests {

    private MinioClient minioClient;

    public static final String IMAGE_FILE_NAME = "wallhaven01.jpg";
    public static final String TEXT_FILE_NAME = "笔记.txt";

    public static final String UPLOAD_FOLDER_PATH = "src/test/resources/upload";
    public static final String DOWNLOAD_FOLDER_PATH = "src/test/resources/download";

    @BeforeEach
    public void connectMinio(){
        minioClient = MinioClient.builder().endpoint(ServerConstant.CENTOS_IP_ADDRESS, 9000, false)
                .credentials(LoginConstant.MINIO_ROOT_USERNAME, LoginConstant.MINIO_ROOT_PASSWORD)
                .build();
    }

    /**
     * 本地文件上传
     */
    @Test
    public void uploadFile(){
        try {
            //判断bucket是否存在
            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("ectest").build());
            if(!bucketExists){
                minioClient.makeBucket(MakeBucketArgs.builder().bucket("ectest").build());
            }else{
                System.out.println("Bucket[ectest] already exists");
            }

            /**
             * bucket:指定上传的bucket
             * object:上传到minio的路径(到文件名)
             * filename:上传的本地文件路径(到文件名)
             */
            minioClient.uploadObject(UploadObjectArgs.builder()
                    .bucket("ectest")
                    .object(IMAGE_FILE_NAME)
                    .filename(UPLOAD_FOLDER_PATH + File.separator + IMAGE_FILE_NAME).build());

        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 上传流
     */
    @Test
    public void uploadInputStream() throws Exception {
        File file = new File(UPLOAD_FOLDER_PATH + File.separator + IMAGE_FILE_NAME);
        FileInputStream fileInputStream = new FileInputStream(file);

        minioClient.putObject(PutObjectArgs.builder()
                .bucket("ectest")
                .object("image_" + NumberFactory.getRandomNumber(5) + ".jpg" )
                .stream(fileInputStream, fileInputStream.available(), -1)
                .build());

        fileInputStream.close();
    }

    /**
     * 下载文件
     */
    @Test
    public void downloadFile(){
        try {
            //判断bucket是否存在
            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("ectest").build());
            if(!bucketExists){
                minioClient.makeBucket(MakeBucketArgs.builder().bucket("ectest").build());
            }else{
                System.out.println("Bucket[ectest] already exists");
            }

            /**
             * bucket:指定上传的bucket
             * object:minio中的文件路径
             * filename:下载到本地的路径(到文件名)
             */
            minioClient.downloadObject(DownloadObjectArgs.builder()
                    .bucket("ectest")
                    .object(IMAGE_FILE_NAME)
                    .filename(DOWNLOAD_FOLDER_PATH + File.separator + "minio_image_" + NumberFactory.getRandomNumber(8) + ".jpg").build());
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 下载流
     */
    @Test
    public void downloadInputStream() throws Exception{
        //获取流
        InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                .bucket("ectest")
                .object(IMAGE_FILE_NAME)
                .build());
        File file = new File(DOWNLOAD_FOLDER_PATH + File.separator + "image_aaa.jpg");
        FileUtils.copyInputStreamToFile(inputStream, file);
        inputStream.close();

        //直接把流保存到本地文件
        minioClient.downloadObject(DownloadObjectArgs.builder()
                .bucket("ectest")
                .object(IMAGE_FILE_NAME)
                .filename(DOWNLOAD_FOLDER_PATH + File.separator + "image_bbb.jpg").build());
    }


}

SpringBoot整合MinIO

本质就是把连接minio服务的参数放在配置文件中,并通过Bean对象在SpringBoor应用启动时生成MinioClient对象。

1、配置文件application.yml

minio:
  endpoint: http://ip:port
  rootUserName: 用户名
  rootPassword: 密码
  bucketName: bucket名称

2、读取配置属性的类

@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
    private String endpoint;
    private String rootUserName;
    private String rootPassword;
    private String bucketName;
}

3、生成MinioClient对象的类

@Configuration
public class MinioClientFactory {

    @Resource
    private MinioProperties minioProperties;

    @Bean
    public MinioClient getDefaultMinioClient(){
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getRootUserName(), minioProperties.getRootPassword())
                .build();
    }
}

4、编写controller测试

@RestController
@Slf4j
@RequestMapping("/minio")
public class MinioController {

    @Resource
    private MinioClient minioClient;

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

    @GetMapping("/list_object_name")
    public List<String> listObject() throws Exception {
        Iterable<Result<Item>> objectResults = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName).build());

        List<String> objectNameList = new ArrayList<>();
        for (Result<Item> objectResult : objectResults) {
            Item item = objectResult.get();
            objectNameList.add(item.objectName());
        }
        return objectNameList;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Minio分布式对象存储具有可推广性的优点。它的学习成本低,安装和运维简单,开箱即用。目前Minio论坛推广力度大,有问必答,并且提供了Java客户端和JS客户端。在数据保护方面,分布式Minio采用纠删码来防范多个节点宕机和位衰减bit rot。分布式Minio至少需要4个硬盘,使用分布式Minio自动引入了纠删码功能。在一致性方面,Minio分布式和单机模式下,所有读写操作都严格遵守read-after-write一致性模型。此外,Minio还支持联盟模式扩展集群。因此,Minio分布式对象存储具有良好的可推广性。\[1\]\[2\] #### 引用[.reference_title] - *1* [minio集群搭建以及与其他分布式存储系统对比](https://blog.csdn.net/liushuiziyouliu/article/details/106938160)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [盘点分布式文件存储系统____分布式文件存储系统简介](https://blog.csdn.net/qq_43842093/article/details/121867125)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晚风也很浪漫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值