Linux

對於來自 2 個不同機器的獨占阻塞鎖,flock 在共享 NFS 上失敗

  • February 5, 2020

我在通過 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 上使用。

請查看以下連結:

引用自:https://serverfault.com/questions/1001700