基于异步处理框架的音视频平台–整体框架细节补充

高总 2024-3-9 310 3/9

一、数据库设计

本项目的数据库主要分为:

1.任务配置表:存储任务配置记录,即某一种任务类型有些什么配置记录。核心字段包括:任务类型、一次拉取多少个任务、每次拉取时隔多长时间、处于执行中的最大时间、最大重试次数、重试间隔。其余像是创建任务时间、修改任务时间等为非核心字段,只是为了规范。

2.任务位置表:作为分表的辅助表,核心字段是比如说我们之前提到过的begin和end指针。

3.任务信息表:存储具体任务,分为两个维度,一个维度按照任务类型分类。

涉及到的核心字段:taskid(返回给客户端,查询当前任务状态等信息)、tasktype(任务类型)、task_stage(当前任务处于哪一个阶段,因为本框架实现的是多阶段处理)、status(任务状态,区别于stage,本框架的任务状态只有四种,待执行,执行中,成功,完全失败(区别于在重试的任务,当任务的重试次数没有超出阈值时,将任务重新置为待执行状态,而非失败状态。))、priority(优先级 )、task_context(任务上下文,比方说上面提到的阶段,此时记录前一阶段执行的输出与后一阶段的输入)、order_time(调度时间,越小调度越优先)。

非核心字段:userid、crt_retry_num(已经重试次数)、max_retry_num(最大重试次数)、max_retry_intercal(最大重试间隔)、schedule_log(调度记录)、create_time、 modify_time

索引:task_id为唯一索引,status和order_time组成的联合索引

再一个维度按照同一任务类型表的不同大小再分新表,这里指的   是当某一个表中的数据超过阈值时。

二、分布式环境面临的挑战

1.worker的分布式环境挑战:和前文说的一样,如果两个worker像同一个flowsvr请求任务,可能会被分配到同样的任务。这样一个会造成资源的浪费,再一个同一个任务执行两次,会造成未知后果,因此在业务上一般做幂等操作,即一个操作执行一次或多次,不影响结果。

解决方案:分布式锁。

2.flowsvr上升到分布式环境所面临的挑战:首先讲一下这里需要用到Nginx, 用来给多个flowsvr做负载均衡,worker将流量给Nginx,Nginx分发给不同的flowsvr。最简单的就是轮询的负载均衡,比如第一个请求给flowsvr1,第二个请求给二等等。

3.特殊情况的处理:服务治理。可以理解为一个进程,说白了就是针对服务的某些特殊情况进行特殊处理,而不放在常规流程里,

本项目的服 务治理:①创建新表(滚动分表):定期扫描所有任务类型,对应的end_pos表,查看是否需要分表(表中记录数据的量是否超出阈值,若超出则创建新表,end_pos++)

②消费表下标移动:定期扫描所有任务类型对应的begin_pos表,查看表中所有任务是否均冷却完毕(只包含成功和失败状态),如果是,begin_pos++

③任务超时检查:定期扫描所有任务类型对应的begin_pos表,然后将处于长时间执行的任务(超出最大执行时间)拉回正轨(任务状态置为pending,待调度/待执行)

三、多阶段处理

不同阶段对应不同的处理逻辑,类似switch case语句

举例说明阶段:①调用腾讯云视频审核能力,其实就是调用http请求,并且将状态设置为下个阶段,同时存储task_context,以及return

nil(这个操作1.worker调用flowsvr的更新任务接口2.flowsvr访问DB,将 任务更新到DB,此时return结束,下一次做需要到下一个worker通过Nginx调用某一个flowsvr再次拉取任务,访问DB,拉取 到更新过任务状态的任务,再通过阶段判断)

②通过上一个阶段的Taskid查询任务结果,也就是调用http找腾讯云查询结果,没完成 ,直接return,回头再调度,相当于 返回Nginx再分发给flowsvr,等待下次worker查询。若审核未通过且没有重试次数,则状态直接设置为失败,若有重试次数,则区分是否违规(涉黄等)。审核完成并通过,则发起转码任务(调用腾讯云接口),并将taskid写入Transcode中,并将状态置为转码阶段。

③与前文相同的是,在这一阶段首先要查询任务结果,查询本阶段任务是否完成,未完成还是和之前一样的操作,直接return。若完成,则存储一些数据到数据库,什么数据业务自己定义,此处可以是转码后的url。然后将状态置为成功。

四、优先级设计

1.绝对优先级:没有order_time ,只有priority。核心是将priority加入排序参数,做联合排序,这种高频操作同时需要建立联合索引。

优点:简单

缺点:1.需要将priority加入联合索引,影响性能,并且大多数时候的priority都是一样的,这个开销是不划算的。

2.priority是固定的,不够灵活,比如优先度搞得任务,即使任务失败后,马上又是最先被调度的,占据资源还容易堵死普通任务。

2.相对优先级

利用order_time,在创建任务时,order_time=当前时间-priority,始终维持着优先秒数

但是如果不是第一次创建,而是在调度之后,这时重试间隔不等于0,设置了重试间隔后order_time=当前时间+算出来的重试间隔,因为这里就是要让他等一会在调度,优先级就没用了。

优点:解耦:不用加入联合索引,足够灵活适合框架。

明显相对优先级的性能友好,且同时在多阶段情况下,让低优先级任务也有更多被调度的机会,整体更加灵活,耦合更小。但是用户也可以定义绝对高优先级,例如定义priority为一天。

- THE END -

高总

3月09日16:47

最后修改:2024年3月9日
0

非特殊说明,本博所有文章均为博主原创。