我正在编写一个处理作业的应用程序。一个作业做两件非事务性的事情:A 部分和 B 部分。两者都是幂等的。
一个职位有三种状态:
- 已创建
- A 部分_完成
- B 部分_完成
逻辑看起来像这样:
BEGIN;
let jobId = randomUUID
INSERT INTO jobs (id, status) VALUES (jobId, 'Created');
COMMIT;
BEGIN;
do partA in application code (make HTTP request)
UPDATE jobs SET status = 'PartA_Done' WHERE id=?
COMMIT;
BEGIN;
do partB in application code (make HTTP request)
UPDATE jobs SET status = 'PartB_Done' WHERE id=?
COMMIT;
PartA 可能会成功,但无法更新jobs
表。重试 cron 作业将重试完成PartB_Done
。
如果我要添加多个 cron 作业(即同时运行),则存在 cron 作业执行重复工作的风险。特别是,两个 cron 作业都可以重复执行PartA
,PartB
或者都可以重复执行同一个作业。我想避免这种情况。
有什么方法可以让我执行, 同时在我添加的新行上的后续事务中COMMIT
保持锁定?FOR UPDATE
jobs
我认为这COMMIT AND CHAIN
会起作用,但我不知道该怎么做。
您无法在提交期间保持行锁。我有两个想法:
processing_since
添加类型为 的附加列timestamp with time zone
。当无人从事该工作时,该列为 NULL。每当进程开始处理作业时,它都会将该列设置为current_timestamp
,并且当它完成一部分时,它不仅会更改status
,还会设置processing_since
为 NULL。如果作业
processing_since
为 NULL 或早于某个时间间隔(该时间间隔比完成部分作业可能需要的时间更长),则该作业可供抢夺。这样,“锁”在一段时间后就会过期。使用咨询锁。这些锁的寿命比事务长,并且不会导致自动清理问题。不幸的是,您正在使用 UUID,否则您可能会采用
jobid
咨询锁。您可以bigint
为此目的向表中添加另一列。