媒资管理服务
详情查看:媒资管理服务 (opens new window)
# 1. 介绍
目前媒资管理的主要管理对象是视频、图片等,包括:媒资文件的查询、文件上传、视频处理等
主要功能:
- 媒资查询:教学机构查询自己所拥有的的媒资信息
- 文件上传:包括上传图片、上传视频
- 视频处理:视频上传成功,系统自动对视频进行编码处理
- 文件删除:教学机构删除自己上传的媒资文件
数据模型:
- media_files:存储文件信息,包括图片、视频、文档等,(审核状态)
- media_process:待处理视频表(需要转码的视频)
- media_process_history:视频处理历史表,记录已经处理成功的视频信息
# 2. 业务流程
上传图片
教学机构人员在课程信息编辑页面上传课程图片,课程图片统一记录在媒资管理系统
上传视频
教学机构人员进入媒资管理列表查询自己上传的媒资文件 教育机构用户在媒资管理页面中点击上传视频按钮 选择要上传的文件,自动执行文件上传到分布式文件系统中 视频上传成功会自动处理,处理完成后可以预览视频
处理视频
对需要转码处理的视频,系统会自动对齐处理,处理后生成视频的URL
审核媒资
运营用户登入运营平台,并进入媒资管理界面,查找待审核媒资 点击列表中媒资名称链接,可以预览该媒资,若是视频,则播放视频 点击列表中某媒资后的审核按钮,即完成媒资的审批过程
绑定媒资
课程计划创建好后需要绑定媒资文件,比如:如果课程计划绑定了视频文件,进入课程在线学习界面后,点课程计划名称则在线播放视频 如何将课程计划绑定媒资呢?
教育机构用户进入课程管理页面编辑某一课程,在课程大纲编辑页的某一小节后,可以添加媒资信息, 点击添加视频,会弹出对话框,可通过输入视频关键字搜索已审核通过的视频媒资, 选择视频媒资,点击提交,完成课程计划绑定媒资流程
# 3. 分布式文件系统
一个计算机无法存储海量的文件,通过网络将若干计算机组织起来共同去存储海量的文件,去接收海量用户的请求,这些组织起来的计算机通过计算机网络通信
本项目采用MinIO构建分布式文件系统,MinIO是一个非常轻量的服务,可以很简单的和其他应用结合使用。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等
它的一大特点就是轻量,使用简单、功能强大,支持各种平台,单个文件最大5TB,兼容提供了Java、Python、GO等多版本SDK支持,MinIO采用去中心化共享架构,每个节点是对等关系,通过Nginx可对MinIO进行负载均衡访问
MinIO使用纠删码技术来保护数据,它是一种恢复丢失和损坏数据的数学算法,它将数据分块,冗余地分散存储在各个节点的磁盘上,所有可用的磁盘组成一个集合,上图由8块硬盘组成一个集合,当上传一个文件时,会通过纠删码算法计算对文件进行分块存储,除了将文件本身分成4个数据块,还会生成4个校验块,数据块和校验开会分散的存储在这8块硬盘上 使用纠删码的好处是即便丢失一半数量(N/2)的硬盘,仍可以恢复数据。例如上面集合中有4个以内的硬盘损害,仍可保证数据恢复,不影响上传和下载;但如果多余一半的硬盘损坏,则无法恢复。
# 4. 视频断点续传
上传视频前,后端会检查视频文件是否已经存在,不存在,前端才会对视频进行分块,后端收到分块后,会先检查该分块是否已经上传,未上传才会进行将分块存储到MinIo中,等到前端上传完所有的分块后,后端开始从MinIo中获取并合并分块
# 5. 分布式任务调度——视频转码
如果存在大量需要转码的视频,一台机器服务的能力是有限的
任务调度,顾名思义就是对任务的调度,它是指系统为了完成特定业务,基于给定时间点,给定时间间隔或者给定执行次数自动执行任务
XXL-JOB是一个轻量级分布式任务调度平台,其核心设计是开发迅速、学习简单、轻量级、易扩展,现已开放源代码并接入多家公司线上产品线,开箱即用
XXL-JOB主要由调度中心、执行器、任务组成
执行流程
- 任务执行器根据配置的调度中心的地址,自动注册到调度中心
- 达到任务触发条件,调度中心下发任务
- 执行器基于线程池执行任务,并把执行结果放入内存队列、把执行日志写入日志文件中
- 执行器消费内存队列中的执行结果,主动上报给调度中心
- 当用户在调度中心查看任务日志,调度中心请求任务执行器,任务执行器读取任务日志文件并返回日志详情
使用分片广播方案时,当任务添加成功后,对于要处理的任务,会添加到待处理任务表中,现在启动多个执行器实例去查询这些待处理任务,此时如何保证多个执行器不会重复执行任务?
- 调度中心按分片广播的方式去下发任务
- 执行器收到作业分片广播的参数:分片总数(shardTotal)和分片序号(shardIndex),计算任务id % 分片总数(taskId % shardTotal),如果结果等于分片序号,就去执行这个任务(taskId % shardTotal = shardIndex)。这样就可以保证不同的执行器执行不同的任务
- 配置调度过期策略为忽略,避免同一个执行器多次重复执行同一个任务
- 配置任务阻塞处理策略为丢弃后续调度,注意:丢弃也没事,下一次调度还可以执行
- 另外还要保证任务处理的幂等性,执行过的任务可以打一个状态标记已完成(上面的代码设置status=2即为完成),下次再次调度该任务时,判断该任务已完成,就不再执行