MinIO — 高性能对象存储
架构概览
MinIO 是高性能、S3 兼容的开源对象存储,适合私有化部署。
MinIO 分布式模式(4节点,每节点4块盘):
Node1: /data1 /data2 /data3 /data4
Node2: /data1 /data2 /data3 /data4
Node3: /data1 /data2 /data3 /data4
Node4: /data1 /data2 /data3 /data4
总驱动器:16
纠删码组:EC:8(8数据 + 8校验)
可容忍:最多8块盘故障纠删码(Erasure Coding)
MinIO 使用 Reed-Solomon 纠删码,比多副本更节省空间:
3副本方案:
存储 1TB 数据 → 需要 3TB 存储空间
纠删码 EC:4+4(4数据 + 4校验):
存储 1TB 数据 → 需要 2TB 存储空间
可容忍 4 块盘故障部署
单机模式(开发/测试)
bash
docker run -p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
-v /data/minio:/data \
minio/minio server /data --console-address ":9001"分布式模式
bash
# docker-compose.yml
version: '3.7'
services:
minio1:
image: minio/minio
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin123
command: server http://minio{1...4}/data{1...2} --console-address ":9001"
volumes:
- /data1:/data1
- /data2:/data2
ports:
- "9001:9001"
minio2:
# 类似配置...Java SDK 使用
java
MinioClient minioClient = MinioClient.builder()
.endpoint("http://minio:9000")
.credentials("minioadmin", "minioadmin123")
.build();
// 创建 Bucket
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket("my-bucket").build())) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket("my-bucket").build());
}
// 上传文件
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket("my-bucket")
.object("images/photo.jpg")
.filename("/local/path/photo.jpg")
.contentType("image/jpeg")
.build()
);
// 上传流
minioClient.putObject(
PutObjectArgs.builder()
.bucket("my-bucket")
.object("data/file.csv")
.stream(inputStream, inputStream.available(), -1)
.contentType("text/csv")
.build()
);
// 下载文件
InputStream stream = minioClient.getObject(
GetObjectArgs.builder()
.bucket("my-bucket")
.object("images/photo.jpg")
.build()
);
// 生成预签名 URL(临时访问链接)
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket("my-bucket")
.object("images/photo.jpg")
.expiry(1, TimeUnit.HOURS)
.build()
);
// 删除对象
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket("my-bucket")
.object("images/photo.jpg")
.build()
);存储桶策略
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": ["*"]},
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::public-bucket/*"]
}
]
}bash
# 设置公开读策略
mc policy set public myminio/public-bucket
# 设置自定义策略
mc policy set-json policy.json myminio/my-bucket生命周期管理
xml
<!-- 生命周期规则:30天后转为低频存储,90天后删除 -->
<LifecycleConfiguration>
<Rule>
<ID>archive-old-files</ID>
<Status>Enabled</Status>
<Filter>
<Prefix>logs/</Prefix>
</Filter>
<Transition>
<Days>30</Days>
<StorageClass>STANDARD_IA</StorageClass>
</Transition>
<Expiration>
<Days>90</Days>
</Expiration>
</Rule>
</LifecycleConfiguration>bash
mc ilm import myminio/my-bucket < lifecycle.xml
mc ilm ls myminio/my-bucket与 Spring Boot 集成
yaml
# application.yml
minio:
endpoint: http://minio:9000
access-key: minioadmin
secret-key: minioadmin123
bucket: my-bucketjava
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.access-key}")
private String accessKey;
@Value("${minio.secret-key}")
private String secretKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
@Service
public class FileStorageService {
@Autowired
private MinioClient minioClient;
@Value("${minio.bucket}")
private String bucket;
public String upload(MultipartFile file) throws Exception {
String objectName = UUID.randomUUID() + "/" + file.getOriginalFilename();
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucket)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
return objectName;
}
public String getPresignedUrl(String objectName) throws Exception {
return minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(objectName)
.expiry(7, TimeUnit.DAYS)
.build()
);
}
}故障处理案例
案例一:节点磁盘故障
现象:某节点磁盘损坏,MinIO 日志出现 IO 错误。
处理:
bash
# 查看集群健康状态
mc admin info myminio
# 查看磁盘状态
mc admin info myminio --json | jq '.info.servers[].drives'
# 替换故障磁盘后,MinIO 自动修复数据
mc admin heal myminio/my-bucket --recursive案例二:上传大文件超时
现象:上传大文件时连接超时。
解决:使用分片上传(Multipart Upload):
java
// MinIO SDK 自动处理分片上传(对象 > 5MB 时)
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket(bucket)
.object("large-file.zip")
.filename("/path/to/large-file.zip")
.build()
);
// SDK 内部自动使用 5MB 分片并发上传案例三:存储空间不足
bash
# 查看存储使用情况
mc admin info myminio
# 查看 Bucket 大小
mc du myminio/my-bucket
# 清理过期对象(配置生命周期策略)
# 或手动删除
mc rm --recursive --force myminio/my-bucket/old-logs/监控
bash
# 启用 Prometheus 指标
mc admin prometheus generate myminio
# 指标端点
curl http://minio:9000/minio/v2/metrics/cluster| 指标 | 说明 |
|---|---|
minio_cluster_capacity_usable_total_bytes | 可用容量 |
minio_cluster_capacity_usable_free_bytes | 剩余容量 |
minio_s3_requests_total | S3 请求总数 |
minio_s3_requests_errors_total | 错误请求数 |
minio_node_drive_offline_total | 离线磁盘数 |