1. 程式人生 > >PHP檔案鎖

PHP檔案鎖

一、檔案鎖是什麼 ?

        顧名思義,對檔案上鎖。

        可以通過“進門”的實際情況來理解:

        有多個人要通過一個大門到食堂裡吃飯,但食堂只有一個座位,食堂管理員A不希望讓人坐地上吃飯,所以就通知大家在門外排隊,一個人進來吃完後,下一個人才允許進來,所以當第一個人進大門後,管理員A把大門鎖上,等第一個人吃完後,再解鎖開啟大門讓第二個人進來,這就是阻塞型檔案鎖

        食堂管理員B卻有點偷懶,不想等那麼久,就告訴大家,中午都可以來食堂吃飯,但是要跑快點才行,只有一個座位,第一個到的人就可以在食堂吃飯,然後我就會鎖門,其他人看到門鎖上了就哪來的回哪去吧,這就是非阻塞新檔案鎖

二、檔案鎖有什麼作用 ?        

        鎖機制之所以存在是因為併發導致的資源競爭,為了確保操作的有效性和完整性,可以通過鎖機制將併發狀態轉換成序列狀態。作為鎖機制中的一種,PHP的檔案鎖也是為了應對資源競爭。

        假設一個應用場景,在存在較大併發的情況下,通過fwrite向檔案尾部多次有序的寫入資料,不加鎖的情況下會發生什麼?多次有序的寫入操作相當於一個事務,我們此時需要保證這個事務的完整性,所以加鎖具有一定的必要性。

三、實際使用效果展示

1. 不使用檔案鎖

<?php
    $lock_file='temp.lock';
    $fp=fopen($lock_file,'a+');
    fwrite($fp, "打點:".date("Y-m-d H:i:s",time())."\n");
    sleep(1);
    fclose($fp);

使用ab壓力測試器執行檔案十次,檢視temp.lock:

  

2. 使用非阻塞型檔案鎖

<?php
	$p_file = "temp.lock";
	$fp = fopen($p_file, 'a+');
	if ( !flock($fp, LOCK_EX + LOCK_NB) ) {
		exit;
	}else {
	  	flock($fp, LOCK_EX + LOCK_NB);
	  	fwrite($fp, "打點:".date("Y-m-d H:i:s",time())."\n");
		sleep(1);
	    flock($fp,LOCK_UN);
	    fclose($fp);
	}

  使用ab壓力測試器執行檔案十次,檢視temp.lock:

  

3. 使用阻塞型檔案鎖

<?php
    $lock_file='temp.lock';
    $fp=fopen($lock_file,'a+');
    if( flock($fp,LOCK_EX) ){
        fwrite($fp, "打點:".date("Y-m-d H:i:s",time())."\n");
        sleep(1);
        flock($fp,LOCK_UN);
        fclose($fp);
    }else{
	    unlink($lock_file);
	}

使用ab壓力測試器執行檔案十次,檢視temp.lock:

  

四、總結

       通過上面三個簡單程式碼示範,可以很清楚看到使用檔案鎖和不使用檔案鎖的區別,非阻塞型檔案鎖和阻塞型檔案鎖的區別。 

       在不使用檔案鎖時,十個併發訪問,同時執行插入操作,而且在這種情況下還會丟失3條請求連線。

       在使用非阻塞型檔案鎖時,又會出現的問題是隻能有一條請求通過,其他的在併發的同時訪問到檔案已經加鎖,只好斷開請求。

       阻塞型檔案鎖的結果很明顯地得到十條資料,並且按照1秒的順序插入,這也是我們想得到的效果。

      所以,在併發量較小的一些場景,可以考慮使用阻塞型檔案鎖,但是如果只是要得到一條有效資料,其他的都可以忽略的話,那也可以使用非阻塞型檔案鎖。

       檔案鎖的使用會增加伺服器 I/O 的消耗,因此還是儘量少用,訪問量較小、併發量小的情況下,可以考慮使用檔案鎖。

       如果涉及資料庫操作順序的話,可以使用mysql鎖,但如果併發量太大的話,就要考慮使用快取鎖,利用快取的時間來進行加鎖控制。簡單提提,後面有時間再做專門的整理。

ps:不熟悉ab壓力測試工具的朋友參考我這篇文章:ab壓力測試工具