2013-02-26 79 views
18
# 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() 

在我的應用程序的地方我有類似:應該將django模型對象實例傳遞給芹菜?

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() 
  • 芹菜泡菜p來將其發送到工人的權利?
  • 如果工作人員在多臺機器上運行,整個人是否會通過網絡傳輸對象(連同主要不需要的龐大text_blob)?有沒有辦法避免它?
  • 如何將人員記錄有效均勻地分配給多臺機器上運行的員工?

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

    # 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() 
    
+0

使用任務延遲,並把它的計時器 – catherine 2013-02-26 00:43:29

+0

@catherine計時器如何幫助我在這種情況下? – 2013-02-26 00:52:25

+0

對不起,這個計時器我的錯誤,這只是任務延遲。當這個人擁有數百萬條記錄時,芹菜會延遲任務並通過逐一發送 – catherine 2013-02-26 00:57:05

回答

1

是。如果數據庫中有數百萬條記錄,那麼這可能不是最好的辦法,但是由於你必須經歷數百萬條記錄,所以無論你做什麼,你的數據庫都會被打得漂亮硬。

以下是一些替代方案,其中沒有一個我稱之爲「更好」,只是不同而已。

  1. 爲你的Person類實現pre_save信號處理程序,它執行.title()的東西。這樣,您的first_name/last_names將始終正確地存儲在數據庫中,您不必再次執行此操作。
  2. 使用採用某種分頁參數的管理命令...也許使用姓氏的第一個字母來分割人員。因此運行./manage.py my_task a會更新姓氏以「a」開頭的所有記錄。很顯然,你必須運行幾次才能瀏覽整個數據庫。
  3. 也許你可以用一些有創意的sql來完成。我甚至不會在這裏嘗試,但它可能是值得調查的。

請記住,.save()將會對數據庫造成更大的「打擊」,然後實際選擇數百萬條記錄。

+0

所以.title()是這裏的一個示例操作,我想在它的幫助下指出,並不是對象所具有的所有內容都被my_task()使用。 – 2013-02-26 00:54:38

+0

分批保存可以減少'命中'的強度,不是嗎?但是,如何有效地批量發送? – 2013-02-26 00:57:13

10

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

由於this文章說:

由於芹菜是一個分佈式系統,你可以不知道在哪個過程中,甚至在任務將運行什麼機器。所以你不應該把Django模型對象作爲參數傳遞給任務,它總是更好地從數據庫中重新獲取對象,因爲可能存在競爭條件。

相關問題