2016-03-28 33 views
0

在我們的網站,我們希望爲我們的用戶創造每小時報告,我們的第一個解決方案是這樣的(我用芹菜爲):有效的方式來掃描整個表芹菜

這裏是我用來創建爲單個用戶報告:

@app.task 
def create_report(user): 
    # this method creates report for given user 
    pass 

,然後我創造了這個定期任務,芹菜運行任務每60分鐘:

@app.task 
def report_cron(): 
    for user in User.objects.all(): 
     create_report.delay(user) 

這soultion將用戶添加到隊列芹菜的整個表(我們正在使用rabbitmq)。

目前這個解決方案工作正常(我們沒有太多的用戶),但你能幫助解決這個問題的更好的解決方案嗎?

回答

1

我將不得不猜測一些事情,因爲你的問題沒有很多信息。

假設您的報告是模型,您可以創建它們而不保存它們,然後使用bulk_create來獲得單個請求。

假設您需要訪問用戶模型的外鍵,您應該使用select_relatedprefetch_related來優化您的請求。理想情況下,您的任務不應對您的所有用戶提出一個以上的請求,而且還需要爲您需要的每個對多個字段提供一個請求,另一個用於創建所有報告。

這就是我可以建議沒有更多的信息。也許你應該在每個用戶迭代中添加一個測試,以確保你的任務不需要一個多小時的時間來完成,所以如果它發生的話,你不會感到驚訝。

+0

感謝您的迴應。我想我沒有足夠好地描述我的問題。創建單個報表並不是我主要關心的問題(它可能需要儘可能多的時間和db查詢)問題是每次芹菜運行'report_cron'時,它將讀取整個用戶表並將其推送到rabbitmq隊列。讀取整個表並將其推送到隊列的過程可能是耗費時間/資源的。我想知道我該如何處理問題的這一方面。 – aliva

2

這種方法沒有什麼特別的錯,儘管它取決於每個報告需要多長時間。例如,如果每個報告需要一毫秒,那麼它將花費絕大部分時間將消息放入隊列中和脫離隊列並進行數據庫連接。關於唯一的調整是允許批處理,所以你可以調整每個任務生成多少報告。然後,您可以嘗試不同的批次大小以找到最佳平衡。

以這種方式使用隊列也很棒,因爲您可以通過添加更多工作人員進行縮放。

缺點是報告不會精確到小時,這取決於消息等待處理的時間長短。

+0

感謝您的回覆。批次是一個好主意,我沒有想到這一點。 創建報告並不是一個高優先級的操作,所以我並不堅持在60米之後創建它們(它可以有所不同) – aliva

+0

正如您所提到的,將整個用戶表放入隊列可能需要一點時間。當我在大量用戶(500萬)的本地測試我們的代碼時,我的系統停止響應幾秒鐘(當芹菜將用戶添加到隊列中時),我們當前的用戶羣比這少得多,但我怎樣才能避免停機時間未來? – aliva

+0

使用另一個芹菜任務來創建其他任務。你想讓你長時間運行的任務進入後臺。所以你在主線程上創建了1個任務(創建1個任務的速度很快),當它運行時創建所有其他任務(這需要一段時間,但這並不重要,因爲它作爲一個芹菜任務運行,而不是持有其他任何事情)。 – Darren