MinIO-入门

1. 简介

高性能对象存储,高性能,可扩展性,云的原生支持

官方网站:http://www.minio.org.cn/

英文官网:https://min.io/

中文文档:http://docs.minio.org.cn/docs/

2. 单机版docker安装

1
2
3
4
5
6
7
8
docker run -d \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-v /home/dockerdata/minio/data:/data \
-e "MINIO_ROOT_USER=root" \
-e "MINIO_ROOT_PASSWORD=aacopy.cn" \
minio/minio server /data --console-address ":9001"

3. 基础概念

  • Object
    • 存储到MinIO的基本对象,如文件
  • Bucket
    • 用来存放Object的空间,每个Bucket之间的数据是相互隔离的,相当于文件的顶层目录
  • Drive
    • 存储数据的磁盘
  • Set
    • 一组Drive集合,分布式部署,根据集群规模划分一个或多个Set,每个Set中的Drive分布在不同的位置。
    • 一个对象存储在一个set上
    • 一个集群划分为多个Set
    • 一个Set包含的Drive数量是固定的,默认根据集群规模自动计算
    • Set中的Drive尽可能的分布在不同的节点上

4. 纠错码EC

  • MinIO通过纠错码来保证数据高可用,使用highwayhash来处理数据损坏。通过算法将丢失的数据进行还原。
  • 将n份原始数据,增加m份,并能够通过m+n份文件中的任意n份数据还原数据

5. 纠删码模式启动

1
2
3
4
5
6
7
8
9
10
11
12
13
podman run \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-v /mnt/data1:/data1 \
-v /mnt/data2:/data2 \
-v /mnt/data3:/data3 \
-v /mnt/data4:/data4 \
-v /mnt/data5:/data5 \
-v /mnt/data6:/data6 \
-v /mnt/data7:/data7 \
-v /mnt/data8:/data8 \
minio/minio server /data{1...8} --console-address ":9001"

6. MinIO-Client

在Java中使用minio

  • 导入依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.2.2</version>
    </dependency>
  • MinioConfig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @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();
    }
    }
  • FileComponent

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    @Component
    public class FileComponent {

    @Autowired
    private MinioClient minioClient;
    @Value("${minio.defaultBucket}")
    private String defaultBucket;
    @Value("${minio.endpoint}")
    private String endpoint;

    /**
    * 上传文件
    * @param multipartFile
    */
    public String upload(MultipartFile multipartFile, String filename) {
    try {
    PutObjectArgs putObjectArgs = PutObjectArgs.builder()
    .bucket(defaultBucket)
    .object(filename)
    .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
    .contentType(multipartFile.getContentType())
    .build();
    ObjectWriteResponse objectWriteResponse = minioClient.putObject(putObjectArgs);
    System.out.println(objectWriteResponse);
    return endpoint+"/"+defaultBucket+"/"+filename;
    } catch (Exception e) {
    e.printStackTrace();
    throw new BizException(BizCodeEnum.FILE_UPLOAD_FAIL);
    }
    }

    public void download(HttpServletResponse response, String fileName) {
    try (InputStream inputStream = minioClient.getObject(
    GetObjectArgs.builder()
    .bucket(defaultBucket)
    .object(fileName)
    .build())) {
    IOUtils.copy(inputStream, response.getOutputStream());
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
  • 配置文件

    1
    2
    3
    4
    5
    minio:
    endpoint: http://192.168.80.128:9000
    accessKey: root
    secretKey: aacopy.cn
    defaultBucket: test
  • 测试接口

    1
    2
    3
    4
    @PostMapping("/user_img/upload")
    public JsonData uploadUserImg(@RequestPart("file") MultipartFile file) {
    return JsonData.buildSuccess(accountService.uploadUserImg(file));
    }

    accountService

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Override
    public String uploadUserImg(MultipartFile file) {
    LocalDateTime now = LocalDateTime.now();
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    String folder = "user/" + dateTimeFormatter.format(now);
    String filename = CommonUtil.generateUUID();
    String originalFilename = file.getOriginalFilename();
    String extension = originalFilename.substring(originalFilename.lastIndexOf("."));

    String wholeFilename = folder + "/" + filename + extension;
    return fileComponent.upload(file, wholeFilename);
    }