php檔案鎖產生的問題與解決方案(一個真實案例)
一個真實案例
想起自己之前犯過一個相關的錯誤。當時場景是這樣的:有一個微信公眾號項目,呼叫微信公眾號的介面都需要access_token
,它的有效期限是2小時。當時我的做法是把它存放在文件中,格式使用的是json
。 {"access_token":"easWasdw32323", "expire":1588219064}
。偽代碼如下:
function getToken ($tokenFile) { $tokenJson = file_get_contents($tokenFile); if (!$tokenJson) { $token = loadToken($tokenFile); } else if (json_decode($tokenJson, true)['expire'] <= time()){ $token = loadToken($tokenFile); } else { $token = json_decode($tokenJson, true)['access_token']; } return $token; } function loadToken ($tokenFile) { $fp = fopen($tokenFile, 'r+'); $tokenJson = ...; // 调用微信接口获取到token fwrite($fp, json_encode($tokenJson)); return $tokenJson['access_token']; }
出現的問題:
專案運行一段時間後就會出問題,但過一、兩秒後再刷新就正常了。
問題原因分析:
假設token已經過期了,這時候有2個請求來了,分別命名為A、B。 A來了,發現token到期後,去呼叫微信介面取得新的token,取得後,更新到存放token的檔案中。
但是,檔案沒有完全更新完畢的時候,B來了,讀入存放token的檔案。因為token檔案中資料沒有更新完整,B讀到的資料就會產生錯誤。
另外還有可能是A和B同時在更新檔案內容,這樣就會產生資料混亂,也會導致錯誤發生。
如何規避這個錯誤呢?
檔案鎖定機制可以完成。
在PHP中提供了 flock()函數,可以對檔案使用鎖定機制(鎖定或釋放檔案)。當一個進程在訪問文件時加上鎖,其他進程要想對該文件進行訪問,則必須等到鎖定被釋放以後。這樣就可以避免在並發存取同一個檔案時破壞資料。
函數原型如下:
flock ( resource $handle , int $operation [, int &$wouldblock ] ) : bool
##handle:
檔案系統指針,是典型地由fopen() 建立的resource(資源)。 - operation
operation 可為下列其中一個值之一:
# LOCK_EX 為專屬鎖定時所鎖定(寫入的程序)。
# LOCK_UN 釋放時所鎖定(不論共用或專屬)。
- LOCK_NB在附加鎖定時所鎖定(Windows 或未支援)。
wouldblock
如果鎖定會阻塞的話(EWOULDBLOCK 錯誤碼情況下),可選擇的第三個參數會被設定為TRUE。 (Windows 上不支援)
demo
demo1.php
<?php $file = 'data.txt'; $handler = fopen($file, 'a+') or die('文件资源打开失败'); // 取得独占锁 if (flock($handler, LOCK_EX)) { sleep(5); flock($handler, LOCK_UN); } else { echo '锁定失败'; } fclose($handler);
demo2.php
<?php $file = 'data.txt'; $handler = fopen($file, 'a+') or die('文件资源打开失败'); // 取得独占锁 if (flock($handler, LOCK_EX)) { fwrite($handler, 'sometest string'); flock($handler, LOCK_UN); } else { echo '锁定失败'; } fclose($handler);
先執行demo1.php然後立即執行demo2.php ,會發現,因為被demo1.php鎖定了文件,demo2.php寫入不了新內容,只有等demo1.php釋放了鎖定,demo2.php才能拿到獨佔鎖,然後才能寫入文件。
解決問題
###學完這些知識後,就能解決我之前的問題了。改進的程式碼如下:###<?php function getToken ($tokenFile){ $tokenJson = file_get_contents($tokenFile); if (!$tokenJson) { $token = loadToken($tokenFile); } else if (json_decode($tokenJson, true)['expire'] <= time()){ $token = loadToken($tokenFile); } else { $token = json_decode($tokenJson, true)['access_token']; } return $token; } function loadToken ($tokenFile) { $fp = fopen($tokenFile, 'w'); // 取得独占锁 if (flock($fp, LOCK_EX)) { $tokenJson = ...; // 调用微信接口获取到token fwrite($fp, json_encode($tokenJson)); flock($fp, LOCK_UN); } else { return false; } return $tokenJson['access_token']; }
以上是php檔案鎖產生的問題與解決方案(一個真實案例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

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

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

PHP8.1中的枚舉功能通過定義命名常量增強了代碼的清晰度和類型安全性。 1)枚舉可以是整數、字符串或對象,提高了代碼可讀性和類型安全性。 2)枚舉基於類,支持面向對象特性,如遍歷和反射。 3)枚舉可用於比較和賦值,確保類型安全。 4)枚舉支持添加方法,實現複雜邏輯。 5)嚴格類型檢查和錯誤處理可避免常見錯誤。 6)枚舉減少魔法值,提升可維護性,但需注意性能優化。

SOLID原則在PHP開發中的應用包括:1.單一職責原則(SRP):每個類只負責一個功能。 2.開閉原則(OCP):通過擴展而非修改實現變化。 3.里氏替換原則(LSP):子類可替換基類而不影響程序正確性。 4.接口隔離原則(ISP):使用細粒度接口避免依賴不使用的方法。 5.依賴倒置原則(DIP):高低層次模塊都依賴於抽象,通過依賴注入實現。

在PHPStorm中如何進行CLI模式的調試?在使用PHPStorm進行開發時,有時我們需要在命令行界面(CLI)模式下調試PHP�...

如何在系統重啟後自動設置unixsocket的權限每次系統重啟後,我們都需要執行以下命令來修改unixsocket的權限:sudo...

使用PHP的cURL庫發送JSON數據在PHP開發中,經常需要與外部API進行交互,其中一種常見的方式是使用cURL庫發送POST�...
