继MinIO替代汇总(一):SeaweedFS、RustFS、Ceph
GlusterFS
官网,开源(GitHub,5.2K Star,1.1K Fork)文件系统,特别适合需要POSIX文件系统语义的场景。无元数据服务器:独特的无中心架构。
实战
3节点部署脚本:
bash
#!/bin/bash
# GlusterFS 3节点集群快速部署脚本
# 在三个节点上执行类似命令
# 节点1:
gluster peer probe node2
gluster peer probe node3
# 创建分布式卷(数据分散在所有节点)
gluster volume create gv0 disperse 3 node1:/data/brick1 node2:/data/brick1 node3:/data/brick1
# 或创建复制卷(数据在所有节点复制)
gluster volume create gv1 replica 3 node1:/data/brick2 node2:/data/brick2 node3:/data/brick2
# 启动卷
gluster volume start gv0
gluster volume start gv1
# 在客户端挂载
mount -t glusterfs node1:/gv0 /mnt/glusterfs
Java
Java SDK集成:
java
public class GlusterFSExample {
private Path glusterMountPoint;
public GlusterFSExample(String mountPath) {
this.glusterMountPoint = Paths.get(mountPath);
// 验证挂载点
if (!Files.exists(glusterMountPoint)) {
thrownew IllegalArgumentException("GlusterFS挂载点不存在: " + mountPath);
}
System.out.println("GlusterFS挂载点: " + mountPoint.toAbsolutePath());
}
// 写入文件 - GlusterFS自动处理数据分布
public void writeFile(String filename, String content) throws IOException {
Path filePath = glusterMountPoint.resolve(filename);
// 创建父目录(如果需要)
if (filePath.getParent() != null) {
Files.createDirectories(filePath.getParent());
}
// 写入文件
Files.write(filePath,
content.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("文件已写入GlusterFS: " + filePath);
}
// 读取文件
public String readFile(String filename) throws IOException {
Path filePath = glusterMountPoint.resolve(filename);
if (Files.exists(filePath)) {
byte[] content = Files.readAllBytes(filePath);
returnnew String(content, StandardCharsets.UTF_8);
}
return null;
}
// 列出目录内容
public List<String> listFiles(String directory) throws IOException {
Path dirPath = glusterMountPoint.resolve(directory);
if (Files.exists(dirPath) && Files.isDirectory(dirPath)) {
try (Stream<Path> stream = Files.list(dirPath)) {
return stream
.filter(Files::isRegularFile)
.map(Path::getFileName)
.map(Path::toString)
.collect(Collectors.toList());
}
}
return Collections.emptyList();
}
// 获取文件信息
public void printFileInfo(String filename) throws IOException {
Path filePath = glusterMountPoint.resolve(filename);
if (Files.exists(filePath)) {
BasicFileAttributes attrs = Files.readAttributes(filePath, BasicFileAttributes.class);
// logging
}
}
}
适用场景
- 需要标准文件系统接口的应用
- 媒体处理、日志存储等场景
- 已有大量基于文件API的遗留系统
Garage
官网,源自法国国立计算机与自动化研究所(INRIA),Deuxfleurs(法国非营利集体)维护、Rust编写、开源(GitHub,4.3K Star,163 Fork)S3兼容分布式对象存储系统。
主打跨地域(Geo-Distributed)小型集群,适合自托管、跨多地异构廉价硬件部署,是MinIO、Ceph、SeaweedFS的轻量替代方案。为跨不同城市/机房、公网高延迟链路的小规模集群设计;不依赖K8s,单二进制,低资源占用,可跑在树莓派、老旧笔记本、廉价VPS上。
特点:
- 轻量级:单二进制部署,无复杂依赖,可二进制/容器运行;
- 低内存开销:资源消耗少,节点最低约1GB RAM,ARM原生支持;
- 网络容错:跨公网高延迟、临时断网,恢复后自动同步;
- 支持单节点模式(副本因子=1,仅测试);
- 去中心化设计:无单点故障,生产推荐≥3节点、跨3个Zone;
- 支持分片上传、Bucket策略、路径风格、兼容S3 API、虚拟主机风格S3访问;
- 数据
scrub后台巡检,自动检测坏块;
架构
- 无中心主节点,对等节点架构:所有节点对等,使用类Raft协议做元数据协同;内置Zone(区域/机房)感知,强制副本分散到不同Zone,避免单区域断电断网丢数据。推荐
replication_factor=3(3副本),3个节点分属3个不同区域,任一区域故障集群仍可读写,最多同时挂掉2个区域才会丢数据。 - 数据模型:分块+元数据分离
- 对象拆成固定大小Block(默认1MB),块数据落盘
- 元数据用LMDB本地数据库存储(每个节点独立维护元数据)
- 一致性模式可选:
eventual:最终一致性,consistent:强一致性
- API
- 主接口:S3 API(子集),兼容AWS CLI、rclone、restic、Immich、Nextcloud、Mastodon、PeerTube;
- 额外:内置静态网站托管(Bucket直接托管静态站点)
- 管理:Garage CLI+管理API(3903 端口)
- 端口默认:
- 3900:S3 API
- 3901:节点间 RPC
- 3903:管理 API
限制
- 仅副本复制,不支持纠删码(Erasure Coding)
- 3副本需要3倍原始磁盘容量,大容量场景成本高,适合中小容量备份/图片,不适合PB级存储;
- S3 API是子集:不支持对象版本、生命周期策略、Object Lock;
- 没有内置TLS,S3 API裸HTTP,需前置Nginx、Caddy做HTTPS反向代理;
- 没有细粒度IAM,权限模型简单(AccessKey绑定Bucket读写权限)。
实战
3节点集群部署示例docker-compose.yml
yml
version:'3.8'
services:
garage1:
image: dxflrs/garage:v0.9.0
command: "garageserver"
environment:
-GARAGE_NODE_NAME=node1
-GARAGE_RPC_SECRET=my-secret-key
-GARAGE_BIND_ADDR=0.0.0.0:3901
-GARAGE_RPC_BIND_ADDR=0.0.0.0:3902
-GARAGE_REPLICATION_MODE=3
volumes:
-./data/garage1:/var/lib/garage
ports:
-"3901:3901"
-"3902:3902"
garage2:
image: dxflrs/garage:v0.9.0
command: "garageserver"
environment:
-GARAGE_NODE_NAME=node2
-GARAGE_RPC_SECRET=my-secret-key
-GARAGE_BIND_ADDR=0.0.0.0:3901
-GARAGE_RPC_BIND_ADDR=0.0.0.0:3902
-GARAGE_SEED=garage1:3902
volumes:
-./data/garage2:/var/lib/garage
garage3:
image: dxflrs/garage:v0.9.0
command: "garageserver"
environment:
-GARAGE_NODE_NAME=node3
-GARAGE_RPC_SECRET=my-secret-key
-GARAGE_BIND_ADDR=0.0.0.0:3901
-GARAGE_RPC_BIND_ADDR=0.0.0.0:3902
-GARAGE_SEED=garage1:3902
volumes:
-./data/garage3:/var/lib/garage
Java SDK集成示例:
java
public class GarageExample {
// Garage完全兼容S3 API,可直接使用AWS SDK
private AmazonS3 garageClient;
public void initGarageConnection() {
// Garage的配置与Minio非常相似
AWSCredentials credentials = new BasicAWSCredentials(
"GK...", // Garage生成的访问密钥
"..." // 对应的秘密密钥
);
garageClient = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(
"http://localhost:3900", // Garage的S3 API端口
"garage" // 区域名称可自定义
)
)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withPathStyleAccessEnabled(true)
.build();
}
// 创建存储桶并设置策略
public void createBucketWithPolicy(String bucketName) {
//创建存储桶
garageClient.createBucket(bucketName);
// Garage支持灵活的存储策略配置
String bucketPolicy = """
{
"version": "2026-08-01",
"statement": [
{
"effect": "Allow",
"principal": "*",
"action": "s3:GetObject",
"resource": "arn:aws:s3:::%s/*"
}
]
}
""".formatted(bucketName);
garageClient.setBucketPolicy(bucketName, bucketPolicy);
System.out.println("存储桶创建完成,已设置公开读取策略");
}
// 上传文件并生成访问URL
public String uploadAndGenerateUrl(String bucketName, String objectKey, InputStream inputStream) {
ObjectMetadata metadata = new ObjectMetadata();
// 设置内容类型等元数据
metadata.setContentType("application/octet-stream");
PutObjectRequest request = new PutObjectRequest(
bucketName, objectKey, inputStream, metadata
);
garageClient.putObject(request);
// 生成预签名URL(Garage支持此功能)
java.util.Date expiration = new java.util.Date();
long expTimeMillis = expiration.getTime();
expTimeMillis += 1000 * 60 * 60;
expiration.setTime(expTimeMillis);
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(bucketName, objectKey)
.withMethod(HttpMethod.GET)
.withExpiration(expiration);
return garageClient.generatePresignedUrl(
generatePresignedUrlRequest).toString();
}
}
适用场景
- 去中心化应用或区块链项目
- 需要轻量级对象存储的场景
Free FS
官网,开源(GitHub,305 Star,69 Fork)文件管理系统:基于Spring Boot 3.5、MyBatis Flex、MySQL、Redis的企业级网盘系统。支持分片上传、断点续传、秒传、文件分享、在线预览。集成阿里云OSS、七牛云Kodo、MinIO、本地存储等多种存储方式。提供文件管理、用户权限、存储配额、回收站等完整功能。适用于企业网盘、文件管理、云存储、资源管理等场景。
左侧简洁的导航栏,右侧文件网格,支持分类筛选、多存储后端、秒传续传...甚至连UI风格都和我的原型相差无几。
功能
- 多种上传方式:基于MD5校验,相同文件秒级完成,GB级大文件支持断点续传、分片上传
- 多存储支持:原生支持阿里云OSS、七牛云、MinIO及本地存储,插件化架构灵活扩展
- Sa-Token认证:集成成熟的权限体系,不是玩具项目,真能上生产环境
- 前后端分离:前端现代感十足的界面,后端低内存高并发