如何避免芹菜任务的竞争条件?
How to avoid race conditions on celery tasks?
考虑以下任务:
@app.task(ignore_result=True)
def withdraw(user, requested_amount):
if user.balance >= requested_amount:
send_money(requested_amount)
user.balance -= requested_amount
user.save()
如果这个任务被同时执行两次,会导致用户余额为负...我该如何解决?这只是种族的一个例子,但我的代码中有很多这样的情况..
您可以使用 this Celery cookbook recipe to implement a Lock which will make sure that only one task is run at a time, and then perhaps implement retry 逻辑稍后再尝试第二个任务。像这样;
def import_feed(self, feed_url):
# The cache key consists of the task name and the MD5 digest
# of the feed URL.
feed_url_hexdigest = md5(feed_url).hexdigest()
lock_id = '{0}-lock-{1}'.format(self.name, feed_url_hexdigest)
logger.debug('Importing feed: %s', feed_url)
with memcache_lock(lock_id, self.app.oid) as acquired:
if acquired:
return Feed.objects.import_feed(feed_url).url
self.retry(countdown = 2)
考虑以下任务:
@app.task(ignore_result=True)
def withdraw(user, requested_amount):
if user.balance >= requested_amount:
send_money(requested_amount)
user.balance -= requested_amount
user.save()
如果这个任务被同时执行两次,会导致用户余额为负...我该如何解决?这只是种族的一个例子,但我的代码中有很多这样的情况..
您可以使用 this Celery cookbook recipe to implement a Lock which will make sure that only one task is run at a time, and then perhaps implement retry 逻辑稍后再尝试第二个任务。像这样;
def import_feed(self, feed_url):
# The cache key consists of the task name and the MD5 digest
# of the feed URL.
feed_url_hexdigest = md5(feed_url).hexdigest()
lock_id = '{0}-lock-{1}'.format(self.name, feed_url_hexdigest)
logger.debug('Importing feed: %s', feed_url)
with memcache_lock(lock_id, self.app.oid) as acquired:
if acquired:
return Feed.objects.import_feed(feed_url).url
self.retry(countdown = 2)