主题
26 · MinIO 对象存储
目标:用 MinIO 跑通 Bucket、上传/下载与预签名 URL,对齐 S3 语义与 Journal COS 概念。
前置:22 · Docker · 24 · Asynq(导出落盘)
官方:MinIO Docs · Go:minio-go · AWS S3 API 兼容说明见官方
1. 为何需要对象存储
| 做法 | 问题 |
|---|---|
| 文件存 API 本机磁盘 | 多副本不一致;扩容噩梦 |
| 经业务机中转大文件 | 带宽与内存被拖垮 |
| 对象存储 + 预签名 | 客户端直传;服务只签发与记账 |
Journal 生产用腾讯云 COS;练手仓用 MinIO(私有 S3),API 心智可迁移。
2. Compose 起 MinIO
yaml
minio:
image: minio/minio:RELEASE.2024-12-18T13-15-44Z # 钉一个你验证过的版本
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
volumes:
minio_data:1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
控制台:http://127.0.0.1:9001 → 建 bucket,如 notes。
3. 最小可跑 demo
bash
go get github.com/minio/minio-go/v7
go get github.com/minio/minio-go/v7/pkg/credentials1
2
2
go
cli, err := minio.New("127.0.0.1:9000", &minio.Options{
Creds: credentials.NewStaticV4("minioadmin", "minioadmin", ""),
Secure: false, // 本地 http
})
fail(err)
ctx := context.Background()
exists, err := cli.BucketExists(ctx, "notes")
fail(err)
if !exists {
fail(cli.MakeBucket(ctx, "notes", minio.MakeBucketOptions{}))
}
_, err = cli.FPutObject(ctx, "notes", "exports/n1.pdf", "./n1.pdf", minio.PutObjectOptions{
ContentType: "application/pdf",
})
fail(err)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
预签名上传(推荐路径)
go
url, err := cli.PresignedPutObject(ctx, "notes", "uploads/"+objectKey, 15*time.Minute)
// 把 url 返回给前端;PUT 二进制直传,不经 API 体1
2
2
下载同理:PresignedGetObject。DB 只存 bucket + objectKey + 元数据。
4. 与业务分层
text
客户端 --预签名PUT--> MinIO
│
└─完成回调/主动确认--> API 写 DB(url/key、归属 userId)
Worker 导出 --> PutObject --> 写 key --> 通知用户1
2
3
4
2
3
4
权限:对象 key 带 userId/ 前缀;校验归属在 API,不在「知道 URL 就能访」的永久公开链(除非刻意 public)。
5. 动手清单
- [ ] Compose 起 MinIO;控制台建 bucket
- [ ] Go:
PutObject/FGetObject成功 - [ ] 预签名 PUT:curl/前端直传
- [ ] 预签名 GET:限时可下
- [ ] 能对照:Journal COS 预签名与本篇的差异仅在厂商 SDK
6. 项目驱动
| 场景 | 做法 |
|---|---|
| 手帐图片 / 附件 | 预签名上传 + 缩略图 Asynq |
| PDF 导出 | Worker 生成 → Put → 返回下载链 |
| 清理 | Cron 扫过期临时前缀(25) |
7. 常见坑 + AI 审查
| 坑 | 说明 |
|---|---|
| 密钥写进镜像 | 环境变量注入 |
| 永久 public bucket 练手当生产 | 学习可;生产最小权限 |
| 对象 key 用用户原始文件名 | 用 UUID;文件名放 metadata |
AI 用业务机 multipart 收 200MB | 优先预签名直传 |
| 路径风格 / 虚拟主机 | 本地注意 endpoint 与 bucket DNS |
8. 下一篇
全文检索:
→ 27 · Elasticsearch 搜索
