Overview
最近在部署webserver,同一个应用(生产者)部署在3个机器上,3个机器都启用了Celery来启动定时任务,执行文件的增删。
可以看到在mq和celery worker阶段都可以做到高可用。但是在user application阶段,存在single point failure的情况,如果单点故障,定时任务就发送不到broker了。
而为了消除user application的SPF或者增加整体吞吐量,一般会部署多个application
,而这样的情况,每个application都会发送相同的定时任务到broker,导致同一时间就会有多个task。
虽然增删的底层是原子性的,但是多个API同时执行,最后通过conflict来确认是不妥当的。为了解决这个问题,可以采用以下方式,
- 分布式定时队列
- 类似oozie,由一个master来控制metadata
- 将task不写在user application里面,将其再往上抽象一层
- api发送定时任务到broker之前,先过一层分布式锁,获得锁的application才能发送,
- mysql字段
- zookeeper
- 优点: 模型简单,其临时顺序节点天然支持释放锁和node crash
- 缺点: ZAB的全部同步,写性能较低
- redis(Redission), etcd
- 优点: 高性能(10w级)
- 缺点: 实现复杂,需要考虑加锁与超时的原子性,低效的等锁自旋
- mq去重,以相同的task id(时间)发送task到mq,然后mq抓取后进行去重(延迟)
其中分布式锁已经有了一个celery-once,celery-singleton的实现。