1.技术简介
1.1Minio
MinIO 是在 GNU Affero 通用公共许可证 v3.0 下发布的高性能对象存储。 它是与 Amazon S3 云存储服务兼容的 API。 使用 MinIO 为机器学习、分析和应用程序数据工作负载构建高性能基础架构。
1.2docker-compose
Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。 Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡。 Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。 使用一个Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。 Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
2.搭建过程
2.1运行环境
- docker
- docker-compose
2.2分布式Minio的有点
在大数据领域,通常的设计理念都是无中心和分布式。Minio分布式模式可以帮助你搭建一个高可用的对象存储服务,你可以使用这些存储设备,而不用考虑其真实物理位置。
- 数据保护
分布式Minio采用 纠删码来防范多个节点宕机和位衰减bit rot。
分布式Minio至少需要4个硬盘,使用分布式Minio自动引入了纠删码功能。 - 高可用
单机Minio服务存在单点故障,相反,如果是一个有N块硬盘的分布式Minio,只要有N/2硬盘在线,你的数据就是安全的。不过你需要至少有N/2+1个硬盘来创建新的对象。
例如,一个16节点的Minio集群,每个节点16块硬盘,就算8台服務器宕机,这个集群仍然是可读的,不过你需要9台服務器才能写数据。
注意,只要遵守分布式Minio的限制,你可以组合不同的节点和每个节点几块硬盘。比如,你可以使用2个节点,每个节点4块硬盘,也可以使用4个节点,每个节点两块硬盘,诸如此类。 - 一致性
Minio在分布式和单机模式下,所有读写操作都严格遵守read-after-write一致性模型。
2.2 编写Docker-compose.yml
- 构建4个服务8个硬盘的minio集群
version: '3.7'
services:
minio1:
image: minio/minio
volumes:
- data1-1:/data1
- data1-2:/data2
ports:
- "9001:9000"
- "8001:8000"
environment:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
command: server http://minio{1...4}/data{1...2} --console-address ":8000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
minio2:
image: minio/minio
volumes:
- data2-1:/data1
- data2-2:/data2
ports:
- "9002:9000"
- "8002:8000"
environment:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
command: server http://minio{1...4}/data{1...2} --console-address ":8000"
healthcheck:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
minio3:
image: minio/minio
volumes:
- data3-1:/data1
- data3-2:/data2
ports:
- "9003:9000"
- "8003:8000"
environment:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
command: server http://minio{1...4}/data{1...2} --console-address ":8000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
minio4:
image: minio/minio
volumes:
- data4-1:/data1
- data4-2:/data2
ports:
- "9004:9000"
- "8004:8000"
environment:
MINIO_ACCESS_KEY: minio
MINIO_SECRET_KEY: minio123
command: server http://minio{1...4}/data{1...2} --console-address ":8000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
## By default this config uses default local driver,
## For custom volumes replace with volume driver configuration.
volumes:
data1-1:
data1-2:
data2-1:
data2-2:
data3-1:
data3-2:
data4-1:
data4-2:
- 创建对应的
docker-compose.yml
使用docker-compose
编排启动容器。
- 集群需要
MINIO_ACCESS_KEY
和MINIO_SECRET_KEY
保持一致,才能确保集群通信正常,因此每个容器内的MINIO_ACCESS_KEY
和MINIO_SECRET_KEY
环境变量一致。 - api端口
9001
,9002
,9003
,9004
- 控制台端口为
8001
,8002
,8003
,8004
2.3 控制台验证集群功能
- 登录控制台
- 上文设置MINIO_ACCESS_KEY 和MINIO_SECRET_KEY就是账号和密码
- 创建bucket
- 上传文件
- 验证集群内是否都有
- 进入这个文件夹 因为数据卷没指定位置
- 两个服务端内均有test
bucket
和aa7.png
2.4 java SDK 验证
- maven 依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
- 代码
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException {
try {
String endpoint = "http://127.0.0.1:9001/";
String accessKey = "minio";
String secretKey = "minio123";
String bucketName = "test111";
String uploadFilePath = "D:\\book\\result.txt";
MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);
boolean isExist = minioClient.bucketExists(bucketName);
if (isExist) {
System.out.println("Bucket already exists.");
} else {
minioClient.makeBucket(bucketName);
}
File file = new File(uploadFilePath);
if (!file.exists()) {
System.out.println("上传文件不存在");
}
//上传到服务器
minioClient.putObject(bucketName, file.getName(), uploadFilePath, null);
//获取文件写入本地
minioClient.getObject(bucketName, file.getName(), "D://" + file.getName());
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
}