最近梳理其他同事以前写的 job 后有点想法,记录下。
一、业务场景
在大多数的系统都有类似这样的逻辑,比如下单了给用户赠送积分,用户在论坛上发表了帖子,给用户增加积分等等。
下单赠送积分,那么一个订单肯定不能重复赠送积分,所以需要一些状态来比较来哪些是已赠送的,哪些是没有赠送的。或许可以在订单表里加个字段来标记是否赠送了积分。
有时候,业务人员出于营销的需要,可能要搞个某某时间段内下单返券的活动。难道又在订单表里加个字段?肯定不能,谁知道还要搞多少活动呢。
二、实现
为了使核心的业务流程尽可能简单高效,赠送积分、返券(后面简称为task)之类的逻辑应该通过异步的job来处理。
因为 task 的处理状态不能放在核心的业务表里,所以,可以另外建一个表示异步任务的 async_task 表,结构如下:
-- 业务job处理 任务
create table async_task (
id number(11) primary key,
key_work varchar2(32), -- 不同业务逻辑的task用不同的keyword
biz_id char(32), -- 业务数据 ID,比如订单号
biz_data varchar2(256), -- 核心的业务数据,用于避免关联业务表;具体结构取决于keyword
status number, -- 任务的处理状态; -2:未处理, -1:处理中, 0:已处理, 大于 0 的数字表示失败次数
create_tm date, -- 任务的创建时间
modify_tm date -- 任务的修改时间
);
处于性能考虑,可以在 key_work 字段上建立分区,在 biz_id 上建立索引。
当业务表有需要处理的数据时,就往 async_task 插入一条相应的记录(可以异步插入),异步 job 再从 async_task 表里取数据来处理。
注意:处理 task 时,要保证数据的一致性。所在的项目组曾出现过,下单返券的活动里,送券与更新状态的操作没有放在同一个事务里,出现券送了,状态没更新,重复送券的问题。一定要注意事务的正确处理。
继续阅读 →