2015-12-14 63 views
1

考慮一個PHP腳本(可能調用其他腳本中的函數)。我想確保它的某些部分一次只能由一個請求執行。例如:如何以請求間的方式鎖定部分代碼?

doSomething(); 
doSomethingElse(); // Lock this: Can only be executed by one request at a time 
yetAnotherThing(); 

所以,如果請求的是目前「內部」 doSomethingElse(),我想任何更遠的請求的代碼調用此函數前行排隊。

我還沒有找到這個在線的解決方案,因爲我談論的是請求之間的鎖定,而不是作爲相同請求的一部分執行的單獨線程的鎖定。我正在使用Apache服務器。

回答

0

您需要通過設置一個標誌來指示應該發生或不發生,以防止執行。

您可以存儲在任何其他的存儲,這是跨請求持久的保護狀態:數據庫,會話,平面文件...

你能做的最基本的事情就是寫一個標誌文件。 當文件存在時,這將排除處理doSomethingElse()的所有後續請求。但是,當文件不存在時,下一個請求將再次執行doSomethingElse()


您可以使用flock()http://php.net/manual/en/function.flock.php) 或您自己的平面文件鎖定的方法。只是概念:

添加file_put_contents(__DIR__.'/doSomethingElse.processing.flag', 'processing');

doSomethingElse()開始,並在函數結束時將其刪除。

然後包執行到狀態檢查:

doSomething(); 
if(! is_file(__DIR__.'/doSomethingElse.processing.flag')) { 
    doSomethingElse(); 
} 
yetAnotherThing(); 

構建隊列

嗯,你可以擴展給定的想法或使用準備好的庫/工具作業。

爲建設一個「排隊」,您將需要擴大鎖定理念和:

  • 添加處理ID,
  • 添加一個堆棧來查找用於處理當前最低的ID,
  • 並且查找和處理邏輯本身
    • 包括「鎖定」爲資源處理

隊列鎖定要處理的資源並且只允許最低的ID。 鎖通常被稱爲信號量。 (它實際上可能是最高的ID,這取決於您的處理邏輯 - 基本上是LIFO或FIFO堆棧處理。)

創建一個隊列並將作業放入,然後添加一個作爲cronjob或守護程序運行的worker。工作人員將作業從隊列中取出,對其進行處理,並返回狀態標記爲「已完成」的結果。您可能會定期輪詢隊列以查看工作是否完成。您可以爲隊列使用數據庫,選擇一個支持鎖定的數據庫。

while(1) { 
    begin new transaction; 
    remove item from queue; 
    process item; 
    save new state of item; 
    commit; 
} 

不知道你在哪裏前進,但你有很多的選項來實現:

+0

感謝您的回答。但是,這使得任何更遠的請求「跳過」「鎖定」部分,而我希望它們在它之前「排隊」。你知道一個辦法達到這個目標嗎?或者有沒有辦法擴展您提出的解決方案以實現這一目標? –

+0

啊,好的。我已經更新了我的答案。 –

相關問題