對於來自 2 個不同機器的獨占阻塞鎖,flock 在共享 NFS 上失敗
我在通過 NFS 共享文件系統的系統上使用 PHPflock()(它使用系統flock)。
當我使用 EXCLUSIVE、BLOCKING 鎖訪問 2 個伺服器上的相同(共享)文件時,flock() 失敗。當然,只有一個程序應該能夠獲得(獨占)鎖,但在這種情況下,另一個應該阻塞。但我看到的是,flock() 呼叫立即返回錯誤。
如果我在 1 台伺服器上做同樣的事情(啟動 2 個程序以獲得獨占、阻塞鎖),它就可以工作。
問題是:這應該工作嗎?一般不建議通過 NFS 使用文件鎖定嗎?(給出的資訊根本不起作用通常指的是過時的資訊)。如果這應該工作,我可以做些什麼來調試或解決這個問題?
測試設置
(我使用了PHP 腳本,但可以使用命令行來進行更簡單的測試設置):
系統一:
flock -x lock.txt sleep 10
結果:獲得鎖
系統 2(當系統 1 獲得鎖時):
flock -x lock.txt sleep 10
這立即返回
羊群:lock.txt:沒有可用的鎖
診斷
strace flock -x lock.txt sleep 10 flock(3, LOCK_EX) = -1 ENOLCK (No locks available)
添加調試資訊
rpcdebug -m nfs all
(在客戶端)這是失敗的群嘗試的日誌。
/var/日誌/消息
Feb 4 10:24:51 myclient kernel: NFS: initiated commit call Feb 4 10:24:51 myclient kernel: NFS: 6791 nfs_commit_done (status 0) Feb 4 10:24:51 myclient kernel: NFS: nfs_update_inode(0:40/916722366 fh_crc=0xa8927c2a ct=1 info=0x27e7f) Feb 4 10:24:51 myclient kernel: NFS: commit (0:40/916722366 1358@4096) OK Feb 4 10:24:59 myclient kernel: NFS: permission(0:41/872433655), mask=0x81, res=-10 Feb 4 10:24:59 myclient kernel: NFS call access Feb 4 10:24:59 myclient kernel: NFS: nfs_update_inode(0:41/872433655 fh_crc=0x9e46fe1a ct=2 info=0x27e7f) Feb 4 10:24:59 myclient kernel: NFS reply access: 0 Feb 4 10:24:59 myclient kernel: NFS: permission(0:41/872433655), mask=0x1, res=0 Feb 4 10:24:59 myclient kernel: NFS: nfs_lookup_revalidate(/lock.txt) is valid Feb 4 10:24:59 myclient kernel: NFS: permission(0:41/915542237), mask=0x10, res=0 Feb 4 10:24:59 myclient kernel: NFS: dentry_delete(/lock.txt, 40808cc) Feb 4 10:24:59 myclient kernel: NFS: permission(0:41/872433655), mask=0x81, res=0 Feb 4 10:24:59 myclient kernel: NFS: nfs_lookup_revalidate(/lock.txt) is valid Feb 4 10:24:59 myclient kernel: NFS: revalidating (0:41/915542237) Feb 4 10:24:59 myclient kernel: NFS call getattr Feb 4 10:24:59 myclient kernel: NFS reply getattr: 0 Feb 4 10:24:59 myclient kernel: NFS: nfs_update_inode(0:41/915542237 fh_crc=0x35293470 ct=1 info=0x27e7f) Feb 4 10:24:59 myclient kernel: NFS: nfs3_forget_cached_acls(0:41/915542237) Feb 4 10:24:59 myclient kernel: NFS: (0:41/915542237) revalidation complete Feb 4 10:24:59 myclient kernel: NFS: dentry_delete(/lock.txt, 40808cc) Feb 4 10:24:59 myclient kernel: NFS: nfs_weak_revalidate: inode 872433655 is valid Feb 4 10:24:59 myclient kernel: NFS: permission(0:41/872433655), mask=0x81, res=0 Feb 4 10:24:59 myclient kernel: NFS: revalidating (0:41/915542237) Feb 4 10:24:59 myclient kernel: NFS call getattr Feb 4 10:24:59 myclient kernel: NFS reply getattr: 0 Feb 4 10:24:59 myclient kernel: NFS: nfs_update_inode(0:41/915542237 fh_crc=0x35293470 ct=1 info=0x27e7f) Feb 4 10:24:59 myclient kernel: NFS: (0:41/915542237) revalidation complete Feb 4 10:24:59 myclient kernel: NFS: nfs_lookup_revalidate(/lock.txt) is valid Feb 4 10:24:59 myclient kernel: NFS call access Feb 4 10:24:59 myclient kernel: NFS: nfs_update_inode(0:41/915542237 fh_crc=0x35293470 ct=1 info=0x27e7f) Feb 4 10:24:59 myclient kernel: NFS reply access: 0 Feb 4 10:24:59 myclient kernel: NFS: permission(0:41/915542237), mask=0x24, res=0 Feb 4 10:24:59 myclient kernel: NFS: open file(/lock.txt) Feb 4 10:24:59 myclient kernel: NFS: llseek file(/lock.txt, 0, 1) Feb 4 10:24:59 myclient kernel: NFS: flock(/lock.txt, t=1, fl=82) Feb 4 10:24:59 myclient kernel: NFS: flush(/lock.txt) Feb 4 10:24:59 myclient kernel: NFS: release(/lock.txt) Feb 4 10:24:59 myclient kernel: NFS: dentry_delete(/lock.txt, 40808cc)
系統
RHEL
uname -r 3.10.0-1062.9.1.el7.x86_64 nfsstat –s Server rpc stats: calls badcalls badclnt badauth xdrcall 0 0 0 0 0 Client rpc stats: calls retrans authrefrsh 588092 0 588092 Client nfs v3: null getattr setattr lookup access readlink 0 0% 350667 59% 0 0% 1714 0% 231693 39% 5 0% read write create mkdir symlink mknod 748 0% 2243 0% 0 0% 3 0% 0 0% 0 0% remove rmdir rename link readdir readdirplus 0 0% 0 0% 0 0% 0 0% 0 0% 110 0% fsstat fsinfo pathconf commit 0 0% 10 0% 5 0% 889 0%
掛載選項:
rw,nosuid,noexec,noatime,nodiratime,context=system_u:object_r:httpd_sys_rw_content_t:s0,vers=3,rsize=131072,wsize=131072,namlen=255,hard,proto=tcp,timeo=600,retrans=2, sec=sys,mountaddr=someip,mountvers=3,mountport=300,mountproto=udp,local_lock=none,addr=someip
我已經搜尋過這個主題。有些命中很老,沒有得到回答,或者是指 linux 上不支持共享鎖定的舊版本的flock。
例如在我的系統上, man 2 flock 提供以下資訊:
在 2.6.11 之前的 Linux 核心中,flock() 不會通過 NFS 鎖定文件(即鎖定的範圍僅限於本地系統)。取而代之的是,可以使用 fcntl(2) 字節範圍鎖定,它確實可以在 NFS 上工作,前提是 Linux 的最新版本和支持鎖定的伺服器。從 Linux 2.6.12 開始,NFS 客戶端通過將flock() 鎖模擬為整個文件上的字節範圍鎖來支持flock() 鎖。這意味著 fcntl(2) 和 flock() 鎖確實通過 NFS 相互互動。從 Linux 2.6.37 開始,核心支持一種兼容模式,允許將 flock() 鎖(以及 fcntl(2) 字節區域鎖)視為本地鎖;請參閱 nfs(5) 中關於 local_lock 選項的討論。
已經有很多資源可以解決這個問題。總之,
flock
由於手冊頁中給出的原因,您不能直接在 NFS 上使用。請查看以下連結: