Spring Boot与异步审核构建仿小红书源码内容发布全流程

📅 2026/7/11 8:51:46
Spring Boot与异步审核构建仿小红书源码内容发布全流程
仿小红书源码中的内容发布并不是把标题、正文和图片写入数据库后就结束了。一篇图文笔记从用户选择图片开始需要经过文件上传、媒体信息记录、草稿保存、内容审核、状态更新、搜索索引和内容分发。短视频发布还会增加视频封面、播放时长、文件转码、异步审核等处理步骤。如果把所有操作都放在一个接口中同步执行只要文件存储、内容审核或搜索服务响应变慢整个发布接口就会被拖慢。用户可能长时间停留在提交页面数据库连接和应用线程也会持续被占用。更合理的处理方式是把内容发布拆成多个独立环节媒体文件先上传业务数据后提交草稿与正式作品分开处理审核任务异步执行内容通过后再进入搜索和推荐。在这套流程中Spring Boot 负责业务编排对象存储负责图片和视频文件内容审核服务负责识别不合规信息Quartz 负责异常任务补偿EasyES 负责公开内容检索。从用户点击发布开始后台发生了什么以一篇包含六张图片、两个话题标签的图文笔记为例用户点击发布后后台并不是只执行一条插入语句。整个链路可以拆成以下步骤选择图片或视频 ↓ 获取文件上传凭证 ↓ 上传至对象存储 ↓ 返回文件地址、宽高和资源标识 ↓ 提交正文、分类、话题及媒体列表 ↓ 创建待审核内容 ↓ 执行文字、图片或视频审核 ↓ 审核通过后公开展示文件上传和内容发布分离后媒体上传失败不会直接影响正文数据。用户上传三张图片后临时退出也可以把现有内容保存到草稿箱。再次进入发布页面时系统读取草稿中的正文、图片顺序、分类和话题不需要重新选择所有文件。对于短视频文件上传独立处理后还可以继续完成封面生成、视频时长读取、清晰度检查和文件转码。发布接口不直接接收文件流在仿小红书源码中一篇内容可能包含多张高清图片也可能包含体积较大的短视频。如果客户端把文件流、正文、话题标签和分类信息一次性提交接口会长时间占用连接。网络出现波动时还可能出现正文提交成功但部分图片上传失败的情况。因此内容发布接口更适合只接收已经上传完成的媒体信息。{ title: 城市周边徒步记录, contentText: 整理了几处适合周末散步和拍照的位置。, contentType: IMAGE_TEXT, categoryId: 8, topicIds: [16, 31], mediaList: [ { fileUrl: /content/image/2026/07/001.jpg, mediaType: IMAGE, width: 1080, height: 1440, sortNumber: 1 }, { fileUrl: /content/image/2026/07/002.jpg, mediaType: IMAGE, width: 1080, height: 1350, sortNumber: 2 } ] }媒体数据不能只保存文件地址。仿小红书源码的发现页通常采用双列瀑布流布局客户端需要根据封面图片宽高比例提前计算卡片高度。如果接口只返回图片地址页面需要等待图片加载完成后才能确定高度容易出现卡片跳动和布局重排。多图内容还要保存排序字段。用户在发布页面调整图片顺序后内容详情、作品编辑和个人主页都必须按照相同顺序展示。短视频媒体可以额外保存以下信息视频时长视频宽高视频封面文件大小转码状态审核状态播放地址。草稿与正式发布不是同一个流程草稿保存强调灵活正式发布强调完整。用户保存草稿时可能只输入一段正文还没有选择分类也可能上传了两张图片但准备稍后继续补充。此时不应该要求所有字段完整更不需要立即进入内容审核。草稿阶段只需要检查基础数据校验项目处理目的用户身份防止未登录状态保存文件归属防止引用其他用户资源媒体数量避免超过系统限制文件类型阻止不支持的格式草稿状态避免修改已删除数据用户点击正式发布后再执行完整校验包括正文长度、内容分类、话题标签、媒体数量、内容类型和可见范围。草稿保存后只出现在个人主页的作品管理中不进入发现页、关注页、附近页、话题页和内容搜索结果。用状态流转管理内容生命周期一篇图文或短视频从创建到公开往往会经历多个阶段。如果内容表只有“正常”和“删除”两个状态无法区分草稿、待审核、审核失败和后台下架等场景。可以将内容状态划分为状态说明DRAFT草稿只有作者可见WAIT_AUDIT已提交等待审核AUDITING审核任务处理中PUBLISHED已公开展示REJECTED审核未通过HIDDEN作者主动隐藏OFFLINE后台下架DELETED逻辑删除状态划分后不同页面可以使用明确的查询条件。发现页、关注页、附近页、内容搜索和话题聚合只返回PUBLISHED状态的数据。个人作品管理则可以展示草稿、审核中、已发布和审核未通过的作品。收藏管理和浏览记录可以保留历史关系但内容已经删除或下架时不能继续返回完整详情。Spring Boot只负责提交核心业务数据正式发布时核心事务只处理内容主表、媒体表、话题关系和审核任务不应在事务中等待审核结果。Transactional(rollbackFor Exception.class) public Long publish(ContentPublishDTO dto, Long userId) { validatePublishRequest(dto, userId); Content content new Content(); content.setUserId(userId); content.setTitle(dto.getTitle()); content.setContentText(dto.getContentText()); content.setContentType(dto.getContentType()); content.setCategoryId(dto.getCategoryId()); content.setStatus(ContentStatus.WAIT_AUDIT); content.setCreateTime(LocalDateTime.now()); contentMapper.insert(content); contentMediaService.saveBatch( content.getId(), dto.getMediaList() ); contentTopicService.bindTopics( content.getId(), dto.getTopicIds() ); auditTaskService.create(content.getId()); return content.getId(); }这里的关键点是数据库事务只创建审核任务不直接执行远程审核请求。内容审核属于外部调用响应时间不可控。如果审核过程被放进数据库事务只要调用超时数据库连接就会长时间无法释放。核心数据先完成入库再由审核任务继续处理可以降低事务复杂度也方便记录失败原因和执行次数。图文与短视频采用不同审核节奏图文内容和短视频内容虽然共用发布入口但审核方式并不相同。图文内容分段审核一篇图文笔记通常包含标题、正文、话题标签和多张图片。可以按照以下顺序处理标题与正文审核 ↓ 话题文字审核 ↓ 多张图片并行审核 ↓ 汇总全部审核结果 ↓ 更新作品最终状态只有文字和所有图片都通过作品才能进入公开状态。如果六张图片中有一张审核未通过审核任务需要记录对应媒体 ID 和失败原因。用户进入作品编辑页面后可以直接定位问题图片并完成替换。短视频异步审核短视频审核通常耗时更长不适合让发布接口同步等待。系统提交视频审核任务后可以保存审核任务编号通过回调接口或定时查询获取结果。视频封面和发布文案可以先完成审核但视频结果没有确定前内容不能公开。审核任务表可以保存业务内容 ID审核类型任务状态外部任务编号已重试次数失败原因创建时间下次执行时间完成时间。Quartz补偿长期未完成的审核任务文件存储、内容审核和网络通信都可能发生异常。例如审核请求已经发出但系统在保存结果前重启或者视频审核已经完成回调接口暂时不可用。此时内容可能长期停留在审核中。Quartz 可以定时扫描异常任务长时间处于等待审核状态的内容已创建但尚未执行的审核任务调用失败且未达到重试上限的任务已提交但尚未取得结果的视频任务审核通过但后续处理未完成的内容。Component public class AuditTaskRetryJob { Resource private AuditTaskService auditTaskService; Scheduled(cron 0 */5 * * * ?) public void retryAuditTask() { ListAuditTask tasks auditTaskService.findRetryTasks(100); for (AuditTask task : tasks) { try { auditTaskService.execute(task.getId()); } catch (Exception exception) { auditTaskService.markFailed( task.getId(), exception.getMessage() ); } } } }补偿任务不能无限重试。任务表应记录最大重试次数和下次执行时间。第一次失败后可以间隔一分钟第二次间隔五分钟后续逐步延长避免短时间内频繁调用审核服务。超过重试上限后任务可以转为人工处理状态同时保留错误信息和执行记录。应用部署多个节点时还需要增加数据库锁或 Redis 分布式锁避免同一条任务被多个节点重复处理。审核通过后才进入公开内容体系审核通过并不只是把内容状态改成PUBLISHED。后台还需要继续完成搜索索引、话题聚合、发现页分发和关注通知等操作。建立EasyES内容索引内容搜索如果一直使用数据库模糊查询数据量增长后会对主库产生较大压力也很难完成关键词相关度排序。审核通过后可以将以下字段写入 EasyES内容标题正文摘要作者信息内容分类话题名称发布时间内容类型点赞数量评论数量收藏数量。用户搜索关键词时可以同时匹配标题、正文和话题标签再结合发布时间与互动热度排序。待审核、审核失败、隐藏和下架内容不能进入搜索索引。作品状态失效后也要及时删除对应索引避免内容继续出现在搜索结果中。更新话题聚合用户发布内容时添加的话题标签只能在审核通过后计入公开作品数量。一篇作品可以关联多个话题。例如同时加入“城市徒步”和“周末生活”审核通过后这篇作品会出现在两个话题页面中。作品隐藏、删除或下架后话题聚合数据也要同步更新。加入发现页候选内容发现页虽然采用双列瀑布流布局但决定内容顺序的是后台推荐逻辑。初期可以根据发布时间、点赞数、评论数、收藏数和浏览完成度计算内容热度。用户近期浏览过的分类、收藏过的话题和关注的作者也可以作为推荐信号。已浏览内容可以适当降低推荐权重减少发现页反复出现相同作品。互动操作必须先验证作品状态仿小红书源码中的公开作品支持点赞、评论、回复、收藏和关注作者。但用户每次执行互动前后台都要检查作品是否仍处于公开状态。已经被作者隐藏、后台下架或逻辑删除的内容不应该继续接受新的点赞和评论。否则页面虽然无法访问互动数量却还在持续增加。评论表通常需要记录字段作用content_id所属作品user_id评论用户parent_id父评论reply_user_id被回复用户content_text评论正文image_url评论图片audit_status评论审核状态create_time创建时间一级评论和回复可以使用同一张表通过parent_id区分层级通过reply_user_id标记被回复用户。评论成功后生成评论通知回复则生成回复通知。点赞、关注和系统消息也应写入通知记录。WebSocket 只负责实时推送不能替代数据库存储。用户离线期间产生的评论通知、点赞提醒和关注提醒需要在下次登录后重新读取。单聊消息也遵循相同原则。文字、图片和表情消息先写入消息表再通过 WebSocket 推送。接收方进入会话后后台更新消息已读状态。Redis只缓存热点不保存最终状态发现页、内容详情、热门搜索和用户主页属于高频访问区域可以使用 Redis 降低数据库压力。适合缓存的数据包括热门作品 ID内容详情基础信息用户主页统计话题热度热门搜索词点赞、评论和收藏数量推荐候选内容未读消息数量。但作品是否审核通过、内容是否删除、商品是否上架、订单是否支付等最终状态仍然要以数据库为准。Redis 数据可能过期或丢失系统必须能够从数据库恢复真实业务状态。热门搜索可以使用 ZSet 保存关键词和搜索次数Quartz 定期汇总近期搜索数据过滤无效词和重复词再形成热门搜索列表。内容素材与商品素材复用基础服务带有商城功能的仿小红书源码还会涉及商品分类、商品列表、商品详情、商品搜索、购物车、立即购买、订单管理和在线支付。商品图片与内容图片都可以使用统一的文件上传和对象存储服务也可以复用图片压缩、格式校验和内容审核能力。但两类业务状态必须分开。内容的PUBLISHED表示允许公开阅读商品的ON_SALE表示允许下单购买。商品即使可以展示也可能因为库存不足无法购买内容则不存在库存和支付问题。基础能力可以复用业务模块仍然保持独立公共基础服务 ├─ 文件上传 ├─ 对象存储 ├─ 内容审核 ├─ 短信服务 └─ 搜索服务 业务模块 ├─ 内容发布与互动 ├─ 即时通讯 ├─ 商品与库存 └─ 订单与支付EasyES 可以分别建立内容索引和商品索引。内容搜索关注标题、正文、作者和话题商品搜索则关注商品名称、分类、价格、库存和上下架状态。Shiro同时处理权限与数据归属用户可以在个人主页管理作品、草稿、收藏、浏览记录、关注列表和粉丝列表但只能操作属于自己的数据。前端隐藏编辑或删除按钮并不能代替服务端权限校验。用户仍然可能通过修改接口参数尝试操作其他人的作品。Shiro 可以在接口层判断用户角色和访问权限业务服务还要继续验证数据归属。例如普通用户只能修改自己的作品内容审核人员可以处理审核任务内容管理员可以下架公开内容商品管理员可以维护商品信息订单管理员可以处理订单状态系统管理员可以管理账号和权限。常见权限标识可以包括content:publish content:update content:delete content:audit content:offline goods:create goods:update order:manage system:notice用户拥有content:update权限并不代表可以修改所有内容。业务层仍然要比较当前用户 ID 与作品作者 ID。如何判断一篇内容真正发布完成数据库插入成功只能说明主数据已经保存不能代表作品已经进入公开内容体系。一篇图文或短视频真正完成发布需要满足以下条件媒体文件上传完整 内容主数据写入成功 分类与话题关系有效 文字、图片或视频审核通过 内容状态更新为公开 EasyES搜索索引创建完成 发现页和话题页能够正常读取任何一个环节出现异常系统都要保留明确状态并通过任务重试或定时补偿继续处理。经过这样的拆分图文发布、短视频发布、多图上传、草稿保存、话题标签、内容搜索和双列瀑布流不再是相互独立的页面功能而是围绕同一套内容生命周期运行。Spring Boot负责编排业务流程对象存储处理媒体文件内容审核服务控制公开范围Quartz修复异常任务EasyES负责内容检索Redis加速热点数据Shiro限制操作权限。各项技术保持清晰边界后仿小红书源码的内容发布链路才能具备更好的可维护性和扩展能力。系统模块关系的结构梳理湖南宠友信息技术有限公司是一家专注社区交友类产品、企业即时通信软件开发为企业提供即时通信工具、垂直类内容圈子自主研发的业界知名友猫产品拥有广大的企业用户群体https://chongyou.info/1/product/xhs.html