当我们使用数据库来管理异步任务时,更新服务怎么保证任务中断后还能继续执行?
假设我们有个表
-- TaskStatusInit = 0
-- TaskStatusDoing = 1
-- TaskStatusDone = 2
-- TaskStatusFailed = 3
create table task
(
id serial
primary key,
task_info jsonb,
task_status smallint,
created_at timestamp default CURRENT_TIMESTAMP,
updated_at timestamp default CURRENT_TIMESTAMP,
);
当更新应用或者有意外情况导致task_status一直处于TaskStatusDoing,导致无法继续执行.这时我们可以这样
create table task
(
id serial
primary key,
task_info jsonb,
task_status smallint,
heartbeat bigint, -- 添加一个心跳字段
created_at timestamp default CURRENT_TIMESTAMP,
updated_at timestamp default CURRENT_TIMESTAMP,
);
添加一个心跳字段,在执行过程中定时去更新他,如果超过一定的时间没有更新就说明这个任务已经中断了.这时候我们就可以放心的把状态重置为我们想要的状态了.
如何避免多个进程争抢一个任务
比如两个进程同时获取到了一个任务,那怎么让一个进程去执行,而不是两个一起执行呢?最简单的办法就是利用状态机的思维
画出状态转移图 比如状态有
TaskStatusInit
TaskStatusDoing
TaskStatusDone
TaskStatusFailed
执行
TaskStatusInit-->TaskStatusDoing
完成
TaskStatusDoing-->TaskStatusDone
失败
TaskStatusDoing-->TaskStatusFailed
重试
TaskStatusFailed-->TaskStatusInit
状态严格按照状态转移来变 就比如如果想要变为执行那么
update task set task_status=1 where id=xx and task_status=0;
这样,只有一个进程的影响行数是1, 那么影响行数是1的执行,其他的放弃执行
总得来说就是需要其他进程知道已经有进程在执行了从而放弃执行就可以了