官网友情链接: wecomapi.com
企微自动化系统任务越来越多以后,会出现一种非常典型的并发问题:同一个任务可能同时被多个执行者处理。
例如一个群发子任务失败后,系统自动补偿正在运行。
与此同时,运营人员在后台看到失败,手工点击“重新执行”。
另外一个定时补偿程序也刚好扫描到这条任务。
如果没有并发控制,同一个外部群可能收到两次相同消息。
这类问题并不是接口本身失败,而是任务系统缺少“占用锁”。
企业微信API能力接入以后,只要涉及异步队列、自动重试、人工重试,就需要明确:
同一业务任务同一时刻只能被一个执行者真正执行。
WeComApi 可以作为企微API接入层,提供外部群、消息、客户和相关能力。本地任务系统则通过任务锁、租约、幂等和状态机保证并发安全。
一、为什么只检查 status = pending 不够
很多任务消费者会:
查询 pending;
修改 running;
执行。
如果两个Worker几乎同时查询。
两边都看到:
pending。
都开始执行。
所以“先查再改”不是原子的。
必须保证:
抢占任务这个动作只有一个人成功。
二、可以使用原子状态更新
例如:
UPDATE task
SET status = running, worker_id = W1
WHERE id = T100 AND status = pending
如果影响行数 = 1:
抢占成功。
另一个Worker更新影响行数 = 0:
不能执行。
这比先SELECT再UPDATE可靠。
三、一个具体例子
群发目标 G100。
任务 T500。
自动补偿Worker A开始抢占。
成功:
status = running;
worker=A。
运营人员同时点重试。
后台尝试创建或执行。
发现:
任务正在被A处理。
提示:
“该任务正在执行,请稍后查看结果。”
避免重复发送。
四、为什么还需要租约
如果Worker A抢到锁以后突然宕机。
任务永远:
running。
就无法恢复。
所以锁应该有:
lease_until。
Worker执行过程中续租。
超过租约没有续约:
认为执行者失联。
任务可以进入:
recovery_pending。
五、租约不是等于任务超时
任务超时回答:
业务任务最晚什么时候完成。
租约回答:
当前Worker是否仍然活着。
两者用途不同。
六、WeComApi 在这里的位置
WeComApi负责:
真正企微API调用。
任务系统在调用前负责:
抢锁;
校验状态;
幂等。
接入层不会替业务系统解决并发执行问题。
七、发送动作还必须有结果幂等
即使任务锁做得很好,极端情况下仍可能出现:
API发送成功;
系统还没更新成功状态;
Worker宕机。
租约过期后另一个Worker接管。
如果直接重发,会重复。
所以客户可见动作还要使用:
business_idempotency_key。
例如:
task_id + target_group_id + content_version。
执行前查询是否已有成功发送记录。
八、人工重试不要绕过任务系统
有些后台“重试按钮”直接调用API。
这是非常危险的。
人工重试也应该:
生成补偿任务;
进入统一锁和幂等体系。
所有执行路径统一。
九、自动补偿和人工补偿可以有优先级
人工明确处理:
可以提高优先级。
但仍然不能和正在执行任务并发。
如果当前任务已经running:
人工可以选择:
等待;
或者管理员取消后重新创建。
不要直接抢占正在执行的Worker。
十、取消任务也存在并发
运营点击取消。
Worker同时准备发送。
必须原子判断。
例如执行前状态从:
running_pre_send → sending
同时取消只能在:
pending / waiting_retry
状态成功。
已经进入真正发送阶段后,取消可能只能阻止后续目标。
状态机要明确。
十一、大批量群发锁粒度怎么选
不能一个主任务锁住几小时。
更适合:
主任务调度锁;
批次锁;
目标锁。
不同粒度承担不同职责。
这样多批可以安全并行,又避免同一目标重复执行。
十二、任务锁也适用于客户同步
同一客户同时触发:
实时同步;
人工重新同步;
全量对账补偿。
不能三条任务同时覆盖客户。
可以使用:
customer_sync_lock。
或者版本控制。
十三、锁等待时间要有限
不要所有任务无限等待锁。
拿不到锁可以:
短暂重试;
或者检测已有任务结果。
如果同一任务已经成功:
直接结束。
十四、日志必须记录锁信息
排查:
为什么任务一直没执行?
系统能看到:
谁占用;
何时开始;
租约到几点;
续租次数;
是否发生接管。
这对于异步系统非常重要。
十五、死锁和异常占用
如果代码Bug导致锁长期不释放。
后台需要:
超时回收;
管理员释放。
但管理员强制释放属于高风险动作,需要审计。
十六、数据看板
可以监控:
running任务;
租约过期;
任务接管次数;
重复执行拦截;
人工重试冲突。
如果接管次数突然增加,说明Worker稳定性有问题。
十七、权限
普通运营只能发起重试。
技术管理员可以查看锁。
强制释放锁需要更高权限。
避免业务人员误操作造成并发。
十八、总结
企业微信API自动化真正进入多Worker、补偿和人工操作并存的阶段以后,任务“有没有状态”已经不够。
WeComApi 可以提供企业微信底层能力,但本地任务系统必须保证同一个业务动作在同一时刻只有一个执行者。
任务占用锁解决并发抢任务。
租约解决Worker宕机。
业务幂等解决发送成功后状态没来得及更新的极端情况。
三者结合,群发、客户同步、标签和补偿任务才能真正做到“可以安全重试,而不会重复执行”。
真正成熟的自动化,不是永远不重试,而是无论自动重试、人工重试还是故障接管,最终业务动作都只生效一次。