229 lines
5.8 KiB
Markdown
229 lines
5.8 KiB
Markdown
# 截图存储方案对比
|
||
|
||
## 方案对比总览
|
||
|
||
| 特性 | 文件系统存储 | 数据库 Base64 存储 ✅ |
|
||
| ---------------- | ------------------- | ------------------------- |
|
||
| **数据一致性** | ❌ 可能不一致 | ✅ 完全一致 |
|
||
| **备份恢复** | ❌ 需要分别备份 | ✅ 只需备份数据库 |
|
||
| **部署复杂度** | ❌ 需要配置文件服务 | ✅ 无需额外配置 |
|
||
| **多服务器部署** | ❌ 需要共享存储 | ✅ 无需共享存储 |
|
||
| **维护成本** | ❌ 需要清理孤立文件 | ✅ 自动管理 |
|
||
| **数据大小** | ✅ 原始大小 | ⚠️ 增加 33% |
|
||
| **查询性能** | ✅ 不影响 | ✅ 不影响(LONGTEXT优化) |
|
||
|
||
## 架构对比
|
||
|
||
### 旧方案:文件系统存储
|
||
|
||
```
|
||
┌─────────────┐
|
||
│ 前端 │
|
||
└──────┬──────┘
|
||
│ 1. 上传图片
|
||
▼
|
||
┌─────────────────┐
|
||
│ 后端 API │
|
||
│ - 保存到文件 │──────┐
|
||
│ - 返回路径 │ │ 2. 写入文件
|
||
└──────┬──────────┘ ▼
|
||
│ ┌──────────────┐
|
||
│ 3. 保存路径 │ 文件系统 │
|
||
▼ │ /uploads/... │
|
||
┌─────────────────┐ └──────────────┘
|
||
│ 数据库 │
|
||
│ screenshots: │
|
||
│ ["/static/..."] │
|
||
└─────────────────┘
|
||
|
||
问题:
|
||
❌ 数据库和文件系统可能不一致
|
||
❌ 删除记录时文件可能残留
|
||
❌ 文件被删除但数据库仍有记录
|
||
```
|
||
|
||
### 新方案:数据库 Base64 存储
|
||
|
||
```
|
||
┌─────────────┐
|
||
│ 前端 │
|
||
└──────┬──────┘
|
||
│ 1. 上传图片
|
||
▼
|
||
┌─────────────────────┐
|
||
│ 后端 API │
|
||
│ - 转换为 Base64 │
|
||
│ - 返回 Data URL │
|
||
└──────┬──────────────┘
|
||
│ 2. 保存 Base64
|
||
▼
|
||
┌─────────────────────┐
|
||
│ 数据库 │
|
||
│ screenshots: │
|
||
│ ["data:image/..."] │
|
||
└─────────────────────┘
|
||
|
||
优势:
|
||
✅ 数据完全一致
|
||
✅ 删除记录时图片自动删除
|
||
✅ 备份恢复只需处理数据库
|
||
```
|
||
|
||
## 数据流对比
|
||
|
||
### 上传流程
|
||
|
||
**旧方案**:
|
||
|
||
```
|
||
图片文件 → 保存到磁盘 → 生成路径 → 存入数据库
|
||
(可能失败) (返回前端) (可能失败)
|
||
```
|
||
|
||
**新方案**:
|
||
|
||
```
|
||
图片文件 → 转换 Base64 → 存入数据库
|
||
(一次性完成)
|
||
```
|
||
|
||
### 读取流程
|
||
|
||
**旧方案**:
|
||
|
||
```
|
||
查询数据库 → 获取路径 → 配置静态服务 → 前端请求文件
|
||
(可能不存在) (需要配置) (可能 404)
|
||
```
|
||
|
||
**新方案**:
|
||
|
||
```
|
||
查询数据库 → 获取 Base64 → 前端直接显示
|
||
(一定存在) (无需额外请求)
|
||
```
|
||
|
||
## 实际案例
|
||
|
||
### 问题场景(旧方案)
|
||
|
||
```
|
||
用户报告:GET /static/uploads/screenshots/bd232714-58ac-472b-b3d0-18e7e768afe0.jpg 404
|
||
|
||
原因分析:
|
||
1. 数据库中有记录:screenshots: ["/static/uploads/screenshots/bd232714..."]
|
||
2. 但文件系统中文件不存在
|
||
3. 可能原因:
|
||
- 手动清理了上传目录
|
||
- 服务器迁移时未同步文件
|
||
- 磁盘故障导致文件丢失
|
||
```
|
||
|
||
### 解决方案(新方案)
|
||
|
||
```
|
||
数据库记录:
|
||
{
|
||
"screenshots": [
|
||
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
|
||
]
|
||
}
|
||
|
||
特点:
|
||
✅ 图片数据直接在数据库中
|
||
✅ 查询到记录就一定能显示图片
|
||
✅ 不会出现 404 错误
|
||
```
|
||
|
||
## 性能影响分析
|
||
|
||
### 存储空间
|
||
|
||
```
|
||
原始图片: 1 MB
|
||
Base64 编码: 1.33 MB (+33%)
|
||
|
||
示例:
|
||
- 5 张截图,每张 500 KB
|
||
- 文件系统: 2.5 MB
|
||
- Base64: 3.3 MB (+0.8 MB)
|
||
```
|
||
|
||
### 数据库性能
|
||
|
||
```sql
|
||
-- LONGTEXT 字段不影响其他字段查询
|
||
SELECT id, customer_name, created_at
|
||
FROM customers;
|
||
-- ✅ 不会加载 screenshots 字段
|
||
|
||
-- 只有明确查询时才加载
|
||
SELECT screenshots
|
||
FROM customers
|
||
WHERE id = 'xxx';
|
||
-- ⚠️ 会加载完整的 Base64 数据
|
||
```
|
||
|
||
### 网络传输
|
||
|
||
**旧方案**:
|
||
|
||
```
|
||
1. API 请求: 返回路径 (~100 bytes)
|
||
2. 图片请求: 下载文件 (1 MB)
|
||
总计: 2 次请求
|
||
```
|
||
|
||
**新方案**:
|
||
|
||
```
|
||
1. API 请求: 返回 Base64 (1.33 MB)
|
||
总计: 1 次请求
|
||
```
|
||
|
||
## 最佳实践建议
|
||
|
||
### ✅ 适合使用 Base64 存储的场景
|
||
|
||
- 截图、缩略图等小图片
|
||
- 需要保证数据一致性
|
||
- 简化部署和维护
|
||
- 单张图片 < 2 MB
|
||
- 每条记录图片数量 < 10 张
|
||
|
||
### ⚠️ 不适合的场景
|
||
|
||
- 高清大图(> 5 MB)
|
||
- 大量图片(> 20 张/记录)
|
||
- 需要图片处理(缩放、裁剪)
|
||
- 需要 CDN 加速
|
||
|
||
### 💡 推荐方案
|
||
|
||
```
|
||
小图片(截图、头像): Base64 存储 ✅
|
||
大图片(产品图、相册): 对象存储(OSS)+ URL 引用
|
||
```
|
||
|
||
## 迁移检查清单
|
||
|
||
- [x] 数据库字段升级为 LONGTEXT
|
||
- [x] 上传接口返回 Base64 Data URL
|
||
- [x] 前端代码兼容两种格式
|
||
- [ ] 测试上传功能
|
||
- [ ] 测试显示功能
|
||
- [ ] 验证数据库存储
|
||
- [ ] 性能测试
|
||
- [ ] 备份验证
|
||
|
||
## 总结
|
||
|
||
通过将截图存储从文件系统迁移到数据库 Base64 存储,我们:
|
||
|
||
1. **彻底解决了数据一致性问题** - 这是最重要的改进
|
||
2. **简化了部署和维护** - 无需管理文件系统
|
||
3. **提高了系统可靠性** - 不会出现文件丢失的情况
|
||
4. **付出了可接受的代价** - 存储空间增加 33%,但换来了更好的数据完整性
|
||
|
||
这是一个典型的**用空间换可靠性**的工程决策。
|