数据库事务存文件的云等效方案:如何实现云存储操作的事务性?
云端对象存储事务处理的行业落地最佳实践
低代码量、高性价比的通用方案(90%以上业务场景适用)
这个方案核心逻辑是把对象存储的操作和数据库事务解耦,用状态字段做中间缓冲,完全避免了跨系统事务的问题,代码实现成本极低:
上传流程
- 后端收到用户带文件的请求后,先生成全局唯一的对象存储Key(建议用UUID+文件后缀,避免重名)
- 开启数据库事务,写入用户记录、关联的文件Key到对应业务表,给文件记录加
status字段,初始值设为pending - 数据库事务提交成功后,再执行S3/对象存储的上传操作,把文件写入生成的Key地址
- 上传成功后,单独更新数据库中对应文件记录的
status为active即可
异常场景自动兜底
- 如果数据库事务提交失败,根本不会触发存储上传操作,没有任何残留数据
- 如果存储上传失败,业务逻辑统一过滤掉
status=pending的记录,用户完全感知不到失败的上传任务,后续清理任务直接回收即可 - 如果上传成功后更新数据库状态失败,存储里的文件不会被业务侧引用,同样交给清理任务处理
删除流程
- 开启数据库事务,把对应文件记录的
status改为deleted(软删除),提交事务 - 事务提交成功后,再异步触发存储的对象删除操作即可
- 业务侧统一过滤
status=deleted的记录,哪怕存储删除操作失败,用户也不可能再访问到该文件
清理任务优化(解决全量扫描成本高的问题)
完全不需要遍历整个存储桶的文件,清理任务只需要扫描数据库中的两类记录即可:
- 创建时间超过24小时且
status=pending的文件记录 - 删除时间超过7天(可根据业务需求调整回收窗口)且
status=deleted的文件记录
拿到这些记录对应的存储Key,直接调用存储接口删除对应对象即可,单次任务执行成本极低,哪怕任务中断多日,重启后也能覆盖所有历史待清理数据,不会有冗余残留。
提升用户体验的进阶优化
如果不想让用户等待后端上传文件的耗时,可以改用预签名URL方案:
- 后端生成唯一Key、写入
pending状态的文件记录、提交事务后,直接返回存储服务的预签名上传URL给前端 - 前端直接用这个URL把文件直传到存储服务,上传完成后回调后端更新文件状态为
active
这种方案后端不需要承载文件上传的流量和耗时,用户上传完成就能立即看到文件,不会出现占位图的问题。
复杂方案的适用场景
你提到的DocumentLog表、异步队列消费的方案,只有在单天上传/删除文件量超过100万级的超大规模场景下才需要使用,普通中小规模业务用上述方案完全可以满足需求,整体新增代码量不超过200行,稳定性也有足够保障。
内容的提问来源于stack exchange,提问作者S. ten Brinke
相关产品推荐
相关产品推荐

