【发布时间】:2016-03-15 01:05:50
【问题描述】:
我正在编写一个 django 应用程序来进行投票,该应用程序使用 celery 来控制投票系统。现在,我有两个队列,默认队列和轮询队列,第一个队列的 concurrency 设置为 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:
感谢Paul 和Plahcinski,我有了一个新想法。我将投票作为对象存储在他们自己的模型中(用户-选项关系)。当有人投票一个选项时,它会从这个模型中创建一个对象,让我计算一个选项有多少票。这将系统从 voting-concurrency 问题中解放出来,因此它可以并行执行。
我正在考虑使用 CELERYBEAT_SCHEDULE 来 cron 一项根据 Vote.objects.get(pk=pk).count() 的结果更新轮询选项的任务。也许我可以每小时执行一次,或者对那些获得新投票的选项进行部分更新......
但是,我如何实时向客户提供更新的选项? 正如Plahcinski 所说,我可以在 Redis(或任何其他内存缓存系统?)中为我的选项设置一个缓存值,并使用它临时存储这些值,为任何新请求提供缓存值。
如何将其与 django 模型中的标准值混合使用?任何人都可以给我一些代码参考或提示吗? 我做得好还是犯了错误?
【问题讨论】:
标签: django dynamic concurrency queue celery