2010-03-25 51 views
1

我有一個PHP腳本,用於從外部服務獲取數據並將數據保存到我的數據庫。我需要這個腳本每分鐘爲系統中的每個用戶運行一次(我預計其中有數千個用戶)。我的問題是,每分鐘每個用戶運行這個最有效的方式是什麼?起初我以爲我會有一個函數從數據庫中抓取所有的用戶ID,迭代ID併爲每個ID執行任務,但我認爲隨着用戶數量的增長,這將需要更長的時間,並且不再落在1分鐘之內。也許我應該排隊用戶ID,併爲每一個單獨執行任務?在這種情況下,我實際上不確定如何繼續。需要關於在一個非常大的過程中工作的建議

在此先感謝您的任何建議。

編輯

要回答Oddthinking的問題:

我想在同一時間開始爲每個用戶的進程。當每個用戶的進程完成時,我想等待1分鐘,然後再次開始該進程。所以我想爲每個用戶每個過程應該是異步的 - 針對用戶1的過程中不應該在乎過程,用戶2

要回答模擬人生的問題:

我沒有對外部服務無法控制,並且外部服務的用戶與我的數據庫中的用戶不同。恐怕我不知道任何其他腳本語言,所以我需要使用PHP來做到這一點。

+0

希望你有一個健壯的數據庫服務器:P – Matt 2010-03-25 00:41:45

+0

@Matt,使我們兩個人:) – 2010-03-25 00:43:56

回答

1

因此,讓我明白這一點:您每分鐘爲數據庫中的每個用戶查詢外部服務(什麼?SOAP?MYSQL?),並將結果存儲在同一個數據庫中。那是對的嗎?

這似乎是一個設計問題。

如果外部服務上的用戶與數據庫中的用戶相同,則可能應該對這兩個用戶進行更加緊密的配置。我不知道PHP是否需要同步這些數據。如果您提供更多細節,我們可以考慮另一種解決方案。如果你在控制外部服務,你可能希望讓該服務轉儲它的數據,甚至直接寫入數據庫。其他一些同步機制可能會更好。

編輯

看來你正在對於然後可以按時間順序查看用戶存儲數據的應用程序。否則,你可能只是在用戶請求時獲取數據。

  1. 獲取所有用戶標識。

  2. 迭代遍歷它們(假設所提取的數據對每個用戶都是唯一的)和(因爲PHP線程不存在AFAIK,您必須在這裏創意)AFIK會爲您的每個請求調用一個流程希望它們全部同時執行,並且如果一個用戶不返回數據,則不會延遲。

  3. 上述過程應該在返回數據庫後立即插入返回的數據。

至於cron的是適合這份工作:只要你有足夠強大的服務器可以處理數千個同時運行的上述cron作業的,你應該罰款。

您可以通過幾個PHP腳本獲得創意。我不確定,但是如果每個CLI調用PHP啓動一個新的PHP過程,那麼你可以這樣做。

foreach ($users as $user) 
{ 
    shell_exec("php fetchdata.php $user"); 
} 

這一切都非常沉重,你不應該期望用PHP快速完成它。做一些測試。不要聽我的話。

2

我是否正確彙總?

您想每分鐘完成數千個任務,但您不確定是否可以及時完成所有任務?

您需要決定什麼時候開始按計劃運行。

  • 你繼續走下去,直到你完成,然後立即重新開始?
  • 你繼續走下去,直到你完成,然後等待一分鐘,然後重新開始?
  • 你是否中止了進程,無論它到了哪裏,然後重新開始?
  • 你是否減慢頻率(例如從現在開始,每隔2分鐘)?
  • 您是否有兩個進程同時運行,並希望下一次運行會更快(如果您第一次清理積壓,這可能會起作用,因此第二次運行將會很快運行。)

這些問題的答案取決於應用程序。根據答案,Cron可能不適合您。永久運行和安排自己的過程可能會更好。

+0

我不知道我的選擇是否有一個永久的過程,而不是克朗。實際上,這是一個計劃任務,因爲它是一臺Windows機器。我還有什麼其他選擇? – 2010-03-25 01:09:45

+1

其他一些選項包括:(1)首選:使其成爲自動啓動的Windows服務(= Unix守護程序),以便在機器啓動時自動在後臺運行 - 即使在任何人登錄之前,(2)僅運行一個應用程序完成這項工作並讓它繼續運行。 (3)有一個預定的作業,檢查另一個副本是否已在運行,如果是,則關閉自己(因此偶爾會發生崩潰)。無論選擇什麼,這個過程都會完成它的工作,然後睡覺,直到它再次到期。 – Oddthinking 2010-03-25 13:10:06

1

數據庫一次處理記錄的大量數據庫。如果你正在逐一處理它們,那麼你正在尋找麻煩。您需要找到一種方法來批量處理「每分鐘」任務,以便通過執行SINGLE(複雜)查詢,檢索所有受影響的用戶的信息;那麼,你會對結果進行PHP處理;然後,在另一個單個查詢中,將結果重新壓入數據庫。

1

基於你的大圖描述,聽起來你有一個死衚衕的設計。如果你現在能夠正常工作,它很可能非常脆弱,而且根本不會擴展。

我在猜測,如果你對外部服務沒有控制權,那麼這個外部服務可能不會樂意被這樣的腳本敲打。你有沒有用你的總體計劃與他們聯繫?

您是否真的需要每次都做所有的用戶?是否有任何時間戳可以用來更加精確地選擇哪些用戶需要「更新」?也許如果你能更好地描述這個目標,我們可能會給出更具體的建議。

1

鑑於你想同時運行用戶的處理澄清...

跳轉想到的是讓每個用戶一個線程最簡單的解決方案。在Windows上,線程比進程便宜得多。

但是,無論您使用線程還是進程,都有數千個同時運行的程序幾乎肯定無法使用。

相反,有一個的線程。游泳池的大小取決於您的機器一次可以舒適地處理多少線程。我希望像30-150這樣的數字儘可能地大到你想要去的地方,但是這很大程度上取決於硬件的容量,而且我可能會出現另一個數量級。

每個線程都會抓取下一個用戶,這是因爲要從共享隊列處理,處理它,並將其放回到隊列的末尾,也許在該日期之前它不應該被處理。

(取決於量和加工的類型,這可能在一個單獨的盒來完成到數據庫中,以確保數據庫不被非數據庫相關處理過載。)

這種解決方案確保您始終可以儘可能地處理儘可能多的用戶,而不會使設備過載。隨着用戶數量的增加,他們處理的頻率會降低,但總是和硬件一樣快。