解決多呼叫同時寫一個文件時我們會使用flock來解決些問題,這樣同一時間只有一個用戶可以寫文件,同時其它用戶進行等待隊列了,下面我來介紹一下flock解決多用戶讀寫文件沖空問題
一般的方案會是:
程式碼如下:
$fp = fopen("/tmp/lock.txt", "w+"); if (flock($fp, LOCK_EX)) { fwrite($fp, "Write something heren"); flock($fp, LOCK_UN); } else { echo "Couldn't lock the file !"; } fclose($fp);
但在PHP中,flock似乎運作的不是那麼好!在多並發情況下,似乎是經常獨佔資源,不即時釋放,或者是根本不釋放,造成死鎖,從而使伺服器的cpu佔用很高,甚至有時會讓伺服器徹底死掉。好像在很多linux/unix系統中,都會有這樣的情況發生。
所以使用flock之前,一定要慎重考慮。
那麼就沒有解決方案了嗎?其實也不是這樣的。如果flock()我們使用得當,完全可能解決死鎖的問題。當然如果不考慮使用flock()函數,也同樣會有很好的解法來解決我們的問題。
經過我個人的蒐集和總結,大致歸納了解決方案有以下幾種。
方案一:對檔案加鎖時,設定一個逾時時間.
大致實作如下:
程式碼如下:
if($fp = fopen($fileName, 'a')) { $startTime = microtime(); do { $canWrite = flock($fp, LOCK_EX); if(!$canWrite) usleep(round(rand(0, 100)*1000)); } while ((!$canWrite)&& ((microtime()-$startTime) < 1000)); if ($canWrite) { fwrite($fp, $dataToSave); } fclose($fp); }
逾時設定為1ms,如果這裡時間內沒有取得鎖,就反覆取得,直接取得到對文件操作權為止,當然。如果超時限制已到,就必需馬上退出,讓出鎖讓它進程來進行操作。
方案二:不使用flock函數,借用暫存檔案來解決讀寫衝突的問題。
大致原理如下:
1。將需要更新的文件考慮一份到我們的臨時文件目錄,將文件最後修改時間保存到一個變量,並為這個臨時文件取一個隨機的,不容易重複的文件名。
2。當這個臨時檔案更新後,再偵測原始檔案的最後更新時間和先前所儲存的時間是否一致。
3。如果最後一次修改時間一致,就將所修改的臨時文件重新命名到原始文件,為了確保文件狀態同步更新,所以需要清除一下文件狀態。
4。但是,如果最後一次修改時間和先前所保存的一致,這說明在這期間,原文件已經被修改過,這時,需要把臨時文件刪除,然後返回false,說明文件這時有其它進程在進行操作。
大致實作程式碼如下:
程式碼如下:
$dir_fileopen = "tmp"; function randomid() { return time().substr(md5(microtime()), 0, rand(5, 12)); } function cfopen($filename, $mode) { global $dir_fileopen; clearstatcache(); do { $id = md5(randomid(rand(), TRUE)); $tempfilename = $dir_fileopen."/".$id.md5($filename); } while(file_exists($tempfilename)); if (file_exists($filename)) { $newfile = false; copy($filename, $tempfilename); }else{ $newfile = true; } $fp = fopen($tempfilename, $mode); return $fp ? array($fp, $filename, $id, @filemtime($filename)) : false; } function cfwrite($fp,$string) { return fwrite($fp[0], $string); } function cfclose($fp, $debug = "off") { global $dir_fileopen; $success = fclose($fp[0]); clearstatcache(); $tempfilename = $dir_fileopen."/".$fp[2].md5($fp[1]); if ((@filemtime($fp[1]) == $fp[3]) || ($fp[4]==true && !file_exists($fp[1])) || $fp[5]==true) { rename($tempfilename, $fp[1]); }else{ unlink($tempfilename); //说明有其它进程 在操作目标文件,当前进程被拒绝 $success = false; } return $success; } $fp = cfopen('lock.txt','a+'); cfwrite($fp,"welcome to beijing.n"); fclose($fp,'on');
对于上面的代码所使用的函数,需要说明一下:
1.rename();重命名一个文件或一个目录,该函数其实更像linux里的mv。更新文件或者目录的路径或名字很方便。
但当我在window测试上面代码时,如果新文件名已经存在,会给出一个notice,说当前文件已经存在。但在linux下工作的很好。
2.clearstatcache();清除文件的状态.php将缓存所有文件属性信息,以提供更高的性能,但有时,多进程在对文件进行删除或者更新操作时,php没来得及更新缓存里的文件属性,容易导致访问到最后更新时间不是真实的数据。所以这里需要使用该函数对已保存的缓存进行清除。
方案三:对操作的文件进行随机读写,以降低并发的可能性。
在对用户访问日志进行记录时,这种方案似乎被采用的比较多。
先前需要定义一个随机空间,空间越大,并发的的可能性就越小,这里假设随机读写空间为[1-500],那么我们的日志文件的分布就为log1~到log500不等。每一次用户访问,都将数据随机写到log1~log500之间的任一文件。
在同一时刻,有2个进程进行记录日志,A进程可能是更新的log32文件,而B进程呢?则此时更新的可能就为log399.要知道,如果要让B进程也操作log32,概率基本上为1/500,差不多约等于零。
在需要对访问日志进行分析时,这里我们只需要先将这些日志合并,再进行分析即可。
使用这种方案来记录日志的一个好处时,进程操作排队的可能性比较小,可以使进程很迅速的完成每一次操作。
方案四:将所有要操作的进程放入一个队列中。然后专门放一个服务完成文件操作。
队列中的每一个排除的进程相当于第一个具体的操作,所以第一次我们的服务只需要从队列中取得相当于具体操作事项就可以了,如果这里还有大量的文件操作进程,没关系,排到我们的队列后面即可,只要愿意排,队列的多长都没关系。
对于以前几种方案,各有各的好处!大致可能归纳为两类:
1、需要排队(影响慢)比如方案一、二、四
2、不需要排队。(影响快)方案三
在设计缓存系统时,一般我们不会采用方案三。因为方案三的分析程序和写入程序是不同步的,在写的时间,完全不考虑到时候分析的难度,只管写的行了。试想一下,如我们在更新一个缓存时,如果也采用随机文件读写法,那么在读缓存时似乎会增加很多流程。但采取方案一、二就完全不一样,虽然写的时间需要等待(当获取锁不成功时,会反复获取),但读文件是很方便的。添加缓存的目的就是要减少数据读取瓶颈,从而提高系统性能。
以上是php 多用戶讀寫檔案衝突的解決方法實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。

要保護應用免受與會話相關的XSS攻擊,需採取以下措施:1.設置HttpOnly和Secure標誌保護會話cookie。 2.對所有用戶輸入進行輸出編碼。 3.實施內容安全策略(CSP)限制腳本來源。通過這些策略,可以有效防護會話相關的XSS攻擊,確保用戶數據安全。

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显著提升应用在高并发环境下的效率。

theSession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceisesneededeededeedeedeededto toavoidperformance andunununununexpectedLogOgouts.3)

在PHP中,可以使用session_name()函數配置會話名稱。具體步驟如下:1.使用session_name()函數設置會話名稱,例如session_name("my_session")。 2.在設置會話名稱後,調用session_start()啟動會話。配置會話名稱可以避免多應用間的會話數據衝突,並增強安全性,但需注意會話名稱的唯一性、安全性、長度和設置時機。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

記事本++7.3.1
好用且免費的程式碼編輯器

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),