素材资源服务
素材 10 万个(约 1TB) · 接入 15 个左右产品线 · 单 app 日请求 1 万-20 万 · 查询 70-80ms
背景与结果
做这个服务之前,公司各产品线的素材(图片/音频/视频/动画工程文件)分散在各自产品里维护,存在重复存储、版本不一致、素材更新需各产品分别处理的问题。素材资源服务把素材统一收口为一站式中台:一处管理、按 app 个性化分发,各产品通过统一接口接入,不再各自建设素材模块——每个接入产品平均省下 1-2 周的素材模块开发。
初版 2020.04 - 2020.10(6 个月上线),此后长期迭代开发(非简单维护)至 2026.07,逐步补齐管理功能与新增能力(ES 搜索、数据统计等)。一人独立负责需求收集、架构设计与开发实现(服务端 + Vue3 管理后台)。
结果数据:素材 10 万个(约 1TB);接入 15 个左右产品线;单 app 日请求量 1 万 - 20 万;资源搜索响应 70-80ms。
部署架构:单机部署,但内部实现均采用分布式方案(分布式锁等),支持平滑扩展到多机部署、代码无需改动;配合 app 侧缓存策略扛住请求量。
技术方案
接入与鉴权
产品在管理后台注册 → 获取 token → 凭 token 请求素材接口。token 为自研方案,校验走 Redis——管理后台可主动停用/作废/重置 token,即时生效。
素材个性化(多租户配置)
素材按 app 维度个性化:不同 app 获取到的素材分类、名称可以不同。配置存储在数据库;支持业务方提供配置 JSON 文件,服务提供接口解析并存储——接入方按自己的体系组织素材树,中台不改内部数据结构。
上传与删除链路
- 双通道上传:① 管理后台操作上传到 OSS;② 业务方获取 STS 临时凭证后前端直传 OSS——服务端不承载数据流
- 删除收敛至管理后台统一管控:配合软删除机制——逻辑删除,OSS 文件移入类"回收站"目录,定时脚本清理超 30 天的文件(默认 30 天内可恢复)
素材变更通知(缓存一致性)
业务方注册时提供通知地址(回调 URL);素材被修改时服务主动推送通知,业务方收到后自行决定是否更新本地缓存。配合业务端本地缓存:用户使用素材并非每次回源(无 CDN,靠 app 缓存扛量)——单机中台支撑全公司素材供给的关键一环。
资源搜索(Elasticsearch)
- 搜索维度:名称、标签、关键字
- 数据同步:独立定时同步程序 MySQL → ES。素材表
esupdatetime字段记录上次同步时间,同步后刷新,定时程序按此增量拉取;全量写入约 2000 条/秒,10 万素材全量重建约 50 秒 - 可靠性兜底:服务内定时检查,资源变更超 1 小时未同步 → 邮件通知管理员
- 查询性能:请求到响应约 70-80ms
管理后台(Vue3)
- 素材管理:上传、编辑、停用、删除;批量导入/导出
- 权限:角色配置,登录按角色返回可操作面板
- 操作日志:重要操作(删除素材/分类等)记录日志
- 数据统计面板:统计每天哪个分类/类型/素材被请求使用最多;数据由业务方按天汇总、晚上定时推送上报,另有定时程序次日检查前一天是否有业务方未上报(邮件告警兜底)
- 短信/邮件能力:调用统一消息服务(本人开发的另一内部服务)
迭代与取舍
- 为什么单机够用:读多写少的素材数据 + 业务方本地缓存扛量 + 非实时强一致的变更通知,使单机足以支撑 15 个产品线;但内部全按分布式实现(锁、无状态),扩容路径始终敞开
- 为什么不用 Canal 监听 binlog 做 ES 同步:时间戳增量同步实现简单、可观测(字段对账)、依赖少;Canal 引入组件运维成本,对本场景的同步时效要求(小时内级)收益有限
- 软删除回收站:从"直接删"演进为"可恢复"——素材误删影响面是全产品线,30 天可恢复窗口把误操作的事故半径降为零