2017-09-02 170 views
0

我有一個網站,在同一時間,可以有多個用戶同時寫入同一個文件。我的代碼示例如下。多個用戶同時使用PHP寫入同一個文件使用PHP

PHP 5.6.20

<?php 
$root=realpath($_SERVER["DOCUMENT_ROOT"]); 
$var=time()."|"; 
echo $var."<br/>"; 
$filename=$root."/Testing/Testing/test1.txt"; 

$myfile=fopen($filename,"a"); 
fwrite($myfile,$var); 
fclose($myfile); 

$myfile=fopen($filename,"r"); 
$contents = fread($myfile, filesize($filename)); 
echo $contents; 
fclose($myfile); 
?> 

我讀到,在PHP如果多個用戶試圖寫在同一文件相同的文件,有數據損壞的機會,我的當然不希望有一個可能導致長期數據損壞的代碼。

我試着在我的瀏覽器上幾乎同時運行上面的代碼來模擬多個用戶同時寫入同一個文件,並且它沒有對正在寫入的文件產生錯誤或任何數據損壞,但我仍然不確定未來的數據損壞情況。

我讀過我可以使用flock確保2個用戶不能同時寫入文件,但是由於我測試了上述代碼,並且沒有產生數據損壞,所以我不確定是否應該用羊羣更新我的代碼或保持原樣。

我的問題是:

1)是否有上述代碼破壞文件,它的寫入的任何機會呢?

2)如果是,使用flock會解決這個問題嗎?如果是的話,我應該如何在上面的代碼中實現羊羣?

編輯:

我知道,這種不確定性可以通過使用數據庫來解決,但這種情況下,最好使用純文本,所以請不要建議我使用DB。

在此先感謝。

+0

此代碼可能會導致文件損壞。您正在附加到該文件,以便它可以。如果你使用這個作爲日誌文件,那麼它會沒事的。使用羣集將導致代碼等待,並導致延遲到使用它。 – ryantxr

+0

你是什麼意思,我追加到文件,所以它可能會好嗎?什麼時候不好?是用「w」寫入文件的時候,因爲我嘗試過,並且沒有數據損壞。 –

+0

您的用戶是否有原因不能寫入數據庫?文件非常適合閱讀(通過包括等),但是你是對的,你可能會在權利爭奪。這可能甚至不能用數據庫解決 - 例如,如果你使用MySQL的舊MyISAM表類型。但是如果你堅持使用InnoDB,那麼你就一切都準備好了。所以只是想知道爲什麼你要首先選擇一個文件。抱歉不解決你的問題,但。 –

回答

0

這是很多編程語言中許多Web應用程序的常見理論問題。

答案是肯定的,會引起麻煩。但是,如果您添加到文件中的內容不是很大,並且流量不大,那麼這是一個非常理論化的問題。當今的操作系統和文件系統非常優化(緩存,懶惰寫作等),當你在使用它們後立即關閉你的文件句柄時,它不太可能發生。

如果遇到錯誤(在使用其他語言編寫PHP/catch例外之前檢查訪問權限),可以添加類似緩衝區的內容,並在延遲後重試或將緩衝區寫入臨時文件併合並它與另一個過程 - 你有幾種可能性。

是的,flock()是一個功能,可以用於這些目的,但我認爲,這將已經過度設計。

+0

根據這個「,它是不太可能發生,當你使用它們後立即關閉你的文件句柄。」我只能告訴你,我一直認爲cron在我的服務器上同時運行兩次PHP腳本。這是配置不好的任務,但它發生了。 –

+0

很好的例子。但是對於cronjob來說,編寫鎖定會很容易;-) – iquellis

+0

@iquellis使用flock可以確保我不會將損壞的數據傳輸到文件中?如果是的話,你可以編輯你的答案與羣添加到代碼? –

0

您需要將保存機制從簡單文件更改爲包含事務的任何數據庫。

+0

我不想使用數據庫,我想使用純文本。 –

+1

我明白你想要什麼,但你需要知道你不能完全控制PHP腳本中的任何文件。以上所有技巧都以99%的效率工作,但無法控制這1%。這就是爲什麼在數據庫中我們有一個交易機制。 –

0

如果兩個腳本試圖同時寫入文件。當在一個文件上調用fopen()函數時,並不會阻止同一文件被另一個腳本打開,這意味着您可能會發現一個腳本正在從另一個文件中讀取文件,或者更糟糕的是,兩個腳本正在寫入同一個文件。所以使用flock()是很好的。 您可以通過http://www.hackingwithphp.com/8/11/0/locking-files-with-flock獲取更多幫助。 對於您的代碼可以使用的羊羣()作爲

<?php 
$root=realpath($_SERVER["DOCUMENT_ROOT"]); 
$var=time()."|"; 
echo $var."<br/>"; 
$filename=$root."/Testing/Testing/test1.txt"; 

$myfile=fopen($filename,"a"); 
if (flock($myfile, LOCK_EX)) {   
    fwrite($myfile,$var); 
    flock($fp, LOCK_UN); // unlock the file 
} else { 
    // flock() returned false, no lock obtained 
    print "Could not lock $filename!\n"; 
} 

fclose($myfile); 

$myfile=fopen($filename,"r"); 
if (flock($myfile, LOCK_EX)) {   

    $contents = fread($myfile, filesize($filename)); 
    echo $contents; 
    flock($fp, LOCK_UN); // unlock the file 
} else { 
    // flock() returned false, no lock obtained 
    print "Could not lock $filename!\n"; 
} 
fclose($myfile); 
?> 
+0

爲什麼在讀取文件時使用LOCK_EX,不應該使用LOCK_SH,以便多個用戶可以同時讀取文件,這會導致文件發生任何數據損壞。你怎麼看, ? –

+0

是的,您可以在閱讀文件時使用LOCK_SH。但在編寫代碼時,您必須使用LOCK_EX,因爲一次只能編寫一個進程。 –

0

我不熟悉的羊羣,但我首先想到的是鎖定或排隊機制。如果寫入的數據不必使用或回看用戶,那麼工作隊列將是最佳選擇。將數據寫入基於redis或memcached的系統,sql或其他類型的排隊系統,或者將具有有趣內容的唯一時間戳文件轉儲到工作人員可以按升序聚合到maste文件中的目錄中。

對於寫入的數據觸發某些用戶需要獲取報告或結果,響應或其他反饋的用例,如果無法重新構建異步堆棧,則鎖定可能是方式最終一致。知道併發用戶的負載和數量,服務器的數量等也很難知道。

相關問題