云相册删除功能设计:乐观删除、事务安全与存储清理

3 阅读4分钟

大家好,我是 EthanYuan。今天来复盘一下我在云相册项目中完整的删除功能设计与实现

相册系统的删除看着简单,实则藏了很多细节:前端体验、数据库数据安全、云存储文件清理、权限控制、并发额度、级联操作、缓存一致性全都要兼顾。如果设计粗糙,很容易出现文件删不干净、额度错乱、脏数据、误删他人资源、并发数据异常等问题。结合项目落地经验,把整套方案完整分享给大家。

一、乐观删除策略,兼顾体验与性能

项目整体采用前端乐观删除 + 后端异步清理的架构设计,极大优化了用户操作体验。

用户点击删除图片或相册后,前端不会阻塞等待接口全部执行完毕,而是即时从页面视图中移除对应数据,给用户毫秒级的操作反馈。后端收到请求后,会优先同步完成数据库层面的删除逻辑、相册容量额度更新等核心业务,保证数据一致性。而云存储上的原图、缩略图文件清理,则放到异步任务中处理,不阻塞本次接口响应。

这样设计最大的优势,就是删除速度完全不受文件大小影响。经过前端体验实际测试:删除 10 张 300KB 的图片整体耗时约 2.64 秒,删除 10 张 5~7MB 的大图耗时仅 2.65 秒,耗时几乎无差别,用户完全感知不到后台文件清理的开销。

二、逻辑删除 + 物理删除双重兜底,引用计数防误删

为了兼顾数据可恢复、存储空间释放、资源安全,项目采用数据库逻辑删除 + 云存储物理删除双层策略。

数据库层面,基于 MyBatis-Plus 的 @TableLogic 注解实现逻辑删除,仅修改 isDelete 删除标记位,不直接从数据表中删除原始记录,方便后续数据回溯、恢复与审计。云存储层面,通过自定义 CosManager 完成真实文件删除,同时兼容原始图片、WebP 缩略图两种资源。

同时加入图片引用计数机制避免误删共享资源:当一张图片被多条业务记录引用时,引用计数大于 1,系统不会清理云存储文件;只有当最后一处关联引用被删除后,才会真正释放存储空间,杜绝共享资源被提前删除导致的展示异常。

三、严格权限校验 + Spring 事务,保证数据原子性

删除属于高危操作,权限管控和事务一致性是重中之重。权限上做了严格隔离:私有相册内的图片,仅相册创建本人可删除;公共图库资源仅限管理员执行批量删除。同时相册删除增加二次确认输入校验,防止用户手滑误删,管理员操作除外。

数据层面依托 Spring 声明式事务保证原子性:图片删除、相册总容量、图片总数额度更新,全部在同一个事务内执行,任意一步异常直接整体回滚,杜绝数据残缺。

操作完成后,系统会自动清理本地 Caffeine 缓存与 Redis 分布式缓存,从源头避免缓存脏数据导致前端展示异常、额度显示错误等问题。

四、批量删除与相册级联删除,解决并发数据竞争

功能上支持单张删除、批量多选删除两种常用模式。相册删除采用完整级联删除逻辑:先遍历查询相册内全部图片 ID,统一调用批量删除接口处理所有关联图片及云存储资源,全部处理完毕后,再删除相册本身记录。批量删除时会统一校验:所有待删除图片必须归属同一个相册,拦截跨相册违规操作,防止误删。

针对相册容量并发问题,额度更新不采用内存加减,而是直接通过 SQL 差值更新:totalSize = totalSize - 删除图片总大小从数据库层面直接计算更新,完美规避多用户并发操作带来的数据竞态问题,保证容量统计长期准确。

总结

整套云相册删除功能,围绕体验、安全、数据一致、存储干净、并发可靠五个核心点设计:乐观删除提升前端交互流畅度;逻辑删除保数据、物理删除清存储;引用计数防止共享资源误删;权限 + 事务守住数据安全底线;批量与级联删除规范操作链路;数据库原生更新解决并发额度问题。看似简单的删除接口,把前后端、数据库、云存储、缓存、业务边界全部考虑到位,生产环境运行稳定,没有出现过脏数据、额度错乱、文件残留等问题。