我正在编写一个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:
感谢Paul和Plahcinski,我得到了一个新主意。我将投票作为对象存储在他们自己的模型中(用户选项关系)。当有人投票选项时,它会从此模型创建一个对象,允许我计算一个选项有多少票。这使系统免于投票并发问题,因此可以并行执行。
我正在考虑使用 CELERYBEAT_SCHEDULE 来根据Vote.objects.get(pk=pk).count()
的结果来更新轮询选项。也许我可以每小时执行一次,或者对那些获得新选票的选项进行部分更新......
但是,如何实时向客户提供更新的选项? 正如Plahcinski所说,我可以在Redis(或任何其他mem-cached系统?)中为我的选项设置一个缓存值,并使用它暂时存储这些值,为任何新请求提供缓存值。
如何将它与django模型中的标准值混合使用?有人可以给我一些代码参考或提示吗? 我是好的还是我犯了错误?
答案 0 :(得分:0)
我要做的是删除数据库的增量并转到redis并使用数据库模型作为缓存值。有一个celery beat,它会将最近增加的redis密钥更新到您的数据库
答案 1 :(得分:0)
如果只有一个简单的模型存储投票-1 / + 1整数,然后是一个芹菜任务,它将那些与FK对象进行协调以进行原子事务和更新?