flock 在共享 NFS 上因来自 2 台不同机器的独占阻塞锁而失败

flock 在共享 NFS 上因来自 2 台不同机器的独占阻塞锁而失败

我在通过 NFS 共享文件系统的系统上使用 PHP flock()(使用系统 flock)。

当我使用 EXCLUSIVE、BLOCKING 锁访问 2 台服务器上的同一个(共享)文件时,flock() 会失败。当然,只有一个进程应该能够获得(独占)锁,但在这种情况下,另一个进程应该被阻止。但我看到的是 flock() 调用立即返回并出现错误。

如果我在 1 台服务器上执行同样的事情(启动 2 个程序来获取 EXCLUSIVE、BLOCKING 锁),它就可以工作。

问题是:这应该有效吗?一般不建议通过 NFS 使用文件锁定吗?(给出的根本不起作用的信息通常是指过时的信息)。如果这应该有效,我该怎么做才能调试或解决这个问题?

测试设置

(我用过PHP 脚本,但可以使用命令行 flock 进行更简单的测试设置):

系统 1:

flock -x lock.txt sleep 10

结果:获取锁

系统 2(当系统 1 已获得锁定时):

flock -x lock.txt sleep 10

这将立即返回

flock:lock.txt:没有可用的锁

诊断

strace flock -x lock.txt sleep 10

flock(3, LOCK_EX)                       = -1 ENOLCK (No locks available)

添加调试信息rpcdebug -m nfs all(在客户端)

这是失败的群集尝试的日志。

/var/log/消息

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)

系统

红帽企业版

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,上下文 = 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 给出以下信息:

在 Linux 内核 2.6.11 之前,flock() 不会通过 NFS 锁定文件(即锁定范围仅限于本地系统)。相反,可以使用 fcntl(2) 字节范围锁定,只要 Linux 版本足够新并且服务器支持锁定,该锁定在 NFS 上是可行的。从 Linux 2.6.12 开始,NFS 客户端通过将 flock() 锁定模拟为整个文件上的字节范围锁定来支持 flock() 锁定。这意味着 fcntl(2) 和 flock() 锁定确实会通过 NFS 相互交互。从 Linux 2.6.37 开始,内核支持兼容模式,允许将 flock() 锁定(以及 fcntl(2) 字节区域锁定)视为本地锁定;请参阅 nfs(5) 中对 local_lock 选项的讨论。

答案1

已经有很多资源可以解决这个问题。总之,flock由于手册页中给出的原因,您无法直接在 NFS 上使用。

请参阅这些链接:

相关内容