首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MVC 併發寫入同一檔案衝突:檔案狀態檢查替代進程互斥

     編輯:程式設計綜合問答

問題

多用戶同時請求 Action 寫入同一伺服器檔案,嘗試 `Mutex` (跨進程互斥體) 失效 (Web 應用多進程/多機部署時 Mutex 不共享)。

錯誤方向

在 Web 應用中使用 **進程級鎖 (`Mutex`, `lock`)** 是反模式:

  • IIS 工作進程回收、多實例 (Web Farm)、容器化部署下鎖不共享。
  • 阻塞請求執行緒降低吞吐,易導致 Thread Pool Starvation。

正確方案:樂觀鎖 / 檔案狀態檢查 / 佇列化

  1. 檔案層面樂觀鎖 (最簡單):
    
       var fileInfo = new FileInfo(path);
       if (!fileInfo.IsReadOnly) { // 或檢查自訂 .lock 檔案是否存在
           // 寫入前設為 ReadOnly 或建立 .lock 檔
           try { File.WriteAllText(path, content); }
           finally { fileInfo.IsReadOnly = false; File.Delete(lockPath); }
       } else {
           // 返回「系統繁忙,請稍後再試」
       }
       
  2. 資料庫層面唯一鍵 / 行鎖 (健壯):
    • 將檔案內容存入資料表 `content` (BLOB/TEXT),利用資料庫交易/行鎖 (`SELECT ... FOR UPDATE`) 保證寫入序列化。
    • 或建立 `file_locks` 表 (file_path, locked_by, expired_at),應用層搶鎖。
  3. 訊息佇列序列化 (高併發):
    • 寫入請求發送至 RabbitMQ/Kafka/RocketMQ,單一消費者順序處理寫入,回寫結果。
  4. 分散式鎖 (多實例必備):
    • Redis `SET key value NX EX 10` (Redisson `RLock`)、ZooKeeper、etcd、Consul。

選型指南

場景推薦方案
單機、低併發、內部工具檔案 ReadOnly 標記 / .lock 檔案
單機/多實例、中等併發、有資料庫資料庫行鎖 / 佇列
高併發、微服務、跨機房Redis Redisson 分散式鎖 + 佇列

核心:拋棄進程 Mutex,採用資料庫/Redis/佇列實現跨進程/跨機器的寫入序列化。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved