Celery:对象级别的动态队列

时间:2016-03-15 01:05:50

标签: django dynamic concurrency queue celery

我正在编写一个django应用程序来进行民意调查,使用芹菜来控制投票系统。现在,我有两个队列,默认和民意调查,第一个并发设置为8,第二个设置为1

$ celery multi start -A myproject.celery default polls -Q:default default -Q:polls polls -c:default 8 -c:polls 1

芹菜路线:

CELERY_ROUTES = {
    'polls.tasks.option_add_vote': {
        'queue': 'polls',
    },
    'polls.tasks.option_subtract_vote': {
        'queue': 'polls',
    }
}

任务:

@app.task
def option_add_vote(pk):
    """
        Updates given option id and its poll increasing vote number by 1.
    """

    option = Option.objects.get(pk=pk)

    try:
        with transaction.atomic():

            option.vote_quantity += 1
            option.save()
            option.poll.total_votes += 1
            option.poll.save()

    except IntegrityError as exc:
        raise self.retry(exc=exc)

option_add_vote方法(任务)更新poll-object vote-number值,将1加到前一个值。因此,为了避免并发问题,我将轮询队列并发设置为1.这允许系统处理成功完成的数千个投票请求。

正如我可以想象的那样,当系统成长时,问题就会出现瓶颈。

所以,我正在考虑某种动态队列,其中所有投票请求到某个轮询到自定义队列的某个轮询的任何选项。我认为这将使系统更加可靠和快速。

你怎么看?我该怎么做?

EDIT1:

感谢PaulPlahcinski,我得到了一个新主意。我将投票作为对象存储在他们自己的模型中(用户选项关系)。当有人投票选项时,它会从此模型创建一个对象,允许我计算一个选项有多少票。这使系统免于投票并发问题,因此可以并行执行。

我正在考虑使用 CELERYBEAT_SCHEDULE 来根据Vote.objects.get(pk=pk).count()的结果来更新轮询选项。也许我可以每小时执行一次,或者对那些获得新选票的选项进行部分更新......

但是,如何实时向客户提供更新的选项? 正如Plahcinski所说,我可以在Redis(或任何其他mem-cached系统?)中为我的选项设置一个缓存值,并使用它暂时存储这些值,为任何新请求提供缓存值。

如何将它与django模型中的标准值混合使用?有人可以给我一些代码参考或提示吗? 我是好的还是我犯了错误?

2 个答案:

答案 0 :(得分:0)

我要做的是删除数据库的增量并转到redis并使用数据库模型作为缓存值。有一个celery beat,它会将最近增加的redis密钥更新到您的数据库

http://redis.io/commands/INCR

答案 1 :(得分:0)

如果只有一个简单的模型存储投票-1 / + 1整数,然后是一个芹菜任务,它将那些与FK对象进行协调以进行原子事务和更新?