簡體   English   中英

django模型對象實例應該傳遞給芹菜嗎?

[英]Should django model object instances be passed to celery?

# models.py
from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    text_blob = models.CharField(max_length=50000)

# tasks.py
import celery
@celery.task
def my_task(person):
    # example operation: does something to person 
    # needs only a few of the attributes of person
    # and not the entire bulky record
    person.first_name = person.first_name.title()
    person.last_name = person.last_name.title()
    person.save()

在我的應用程序的某個地方我有類似的東西:

from models import Person
from tasks import my_task
import celery
g = celery.group([my_task.s(p) for p in Person.objects.all()])
g.apply_async()
  • 芹菜泡菜將它發送給工人嗎?
  • 如果工作人員在多台計算機上運行,​​那么整個人對象(以及主要不需要的龐大的text_blob)是否會通過網絡傳輸? 有沒有辦法避免它?
  • 如何有效且均勻地將Person記錄分發給在多台機器上運行的工作人員?

  • 這可能是一個更好的主意嗎? 如果Person有幾百萬條記錄,難道不會壓倒db嗎?

     # tasks.py import celery from models import Person @celery.task def my_task(person_pk): # example operation that does not need text_blob person = Person.objects.get(pk=person_pk) person.first_name = person.first_name.title() person.last_name = person.last_name.title() person.save() #In my application somewhere from models import Person from tasks import my_task import celery g = celery.group([my_task.s(p.pk) for p in Person.objects.all()]) g.apply_async() 

我相信通過PK而不是整個模型對象更好更安全。 由於PK只是一個數字,序列化也更簡單。 最重要的是,您可以使用更安全的sarializer(json / yaml而不是pickle),並且可以放心,您在序列化模型時不會遇到任何問題。

由於文章說:

由於Celery是一個分布式系統,因此您無法知道在哪個進程中運行,甚至無法知道運行任務的機器。 因此,您不應該將Django模型對象作為參數傳遞給任務,而是從數據庫中重新獲取對象幾乎總是更好,因為可能存在競爭條件。

是。 如果數據庫中有數百萬條記錄,那么這可能不是最好的方法,但由於你必須經歷所有數百萬條記錄,那么無論你做什么,你的數據庫都會受到很大影響。硬。

以下是一些替代方案,其中沒有一個我稱之為“更好”,只是不同。

  1. 為你的Person類實現一個pre_save信號處理程序,它執行.title()的東西。 這樣,您的first_name / last_names將始終正確存儲在數據庫中,您不必再次執行此操作。
  2. 使用帶有某種分頁參數的管理命令...也許使用姓氏的第一個字母來分割人員。 所以運行./manage.py my_task a會更新姓氏以“a”開頭的所有記錄。 顯然你必須多次運行才能通過整個數據庫
  3. 也許你可以用一些創造性的SQL來做到這一點。 我甚至不打算在這里嘗試,但它可能值得調查。

請記住,.save()將更難“擊中”數據庫,然后實際選擇數百萬條記錄。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM