zoukankan      html  css  js  c++  java
  • NFS4文件锁机制探秘

    简介

    NFS4实现“租赁锁”。每个锁拥有一样的“租赁期”。客户端的读写操作将刷新“租赁期”。租赁期到期后,锁将被服务器释放。NFS4通过下述“模型”实现对锁的管理:

    1) 清晰地划分客户端和服务器;

    2) 可靠的锁的一致性检测机制

    3) 简单可靠的锁状态恢复机制

    几个概念

    Client -- 客户端是访问NFS服务器的资源的实体。客户端是包含直接访问NFS服务器的一个应用程序。客户端可以是传统的操作系统远程文件系统服务的应用程序。客户端负责维护一个或多个用户应用程序的NFS。客户端崩溃或失败时,它负责管理重新获取锁。请注意,多个客户端可以共享相同的传输;多个客户端可能存在于同一个网络节点。

    Clientid  --- 64位的id标识符。客户端经过认证后,由服务器分配的整型数,用于后续通讯中标识客户端。

    Server  --- 负责协调客户端访问文件系统的实体。

    Stateid  --- 128位变量用于标识特定文件状态(打开和锁定)。由服务器分配,根据stateid可找到相应的状态信息表。

    关键流程

    1) 客户端认证(申请clientid) 

    客户端启动 --> 发送nfs_client_id4(verifieridSETCLIENTID

    --> 服务器分配clientid --> 客户端发送clientid 给服务器端,二次确认SETCLIENTID_CONFIRM --> 认证成功(建立server记录)

    2) 状态建立(申请stateid) --> 带状态的文件操作 --> 撤销状态

    客户端用clientid为特定lock_owner发起锁申请 --> 服务器锁定文件,并发回stateid (建立状态表)--> 客户端用stateid进行文件读写--> 撤销状态,即撤销stateid

    NFS 4 为支持文件锁需要解决的问题:

    1) 如何识别客户端?不同客户端?客户端重启?

    2) 如何识别服务器?服务器是否重启?

    3) 如何维护锁状态?正常流程?重启恢复?

    4) 如何保证“至多一次”的锁状态更新?

    5) 状态同步?客户端失败,服务器成功下的状态同步?

     

    1) 如何识别客户端?不同客户端?客户端重启?

    每个客户端均必须经过服务器端的认证,并获取服务器端分配的唯一标识符clientid。在后续操作中,NFS系统采用clientid表示该客户端。

    客户端发起认证时,需提供两个信息,verifieridverifier用于表示该客户端是否是重启客户端(重启客户端将撤销所有此客户端的锁状态)id是该客户端用户标识自己身份的唯一字符串。Id串一般由如下几部分组成:客户端地址(ip+port),服务器地址(ip+port), MAC等机器唯一的信息。socket的通讯五元组可作为同一个server下的唯一标识串,加上MAC等信息是为了防止不同客户端的ip重用。

    在上述id生成规则下,不同客户端将生成唯一的标识串。客户端重启时,id不变,仅改变verifier。为了实现重启时id不变,每个客户端配一个监控进程,监控进程生成idverifier,并启动客户端,重启时改变verifier

     

    2) 如何识别服务器?服务器是否重启?

    服务器的标识放在stateid中,由于服务器的唯一性,可用进程id来标识服务器。服务器重启后,进程id改变,相应的stateidserver标识也将改变,导致stateid失效。同时服务器重启将导致所有锁信息丢失(无信息持久化),也导致stateid失效。

     

    3) 如何维护锁状态?正常流程?重启恢复?

    正常流程:

    针对特定文件,lock_owner可申请相应的锁(状态申请),得到服务器分配的stateid表示锁请求成功。在后续操作中,该owner均使用stateid进行文件操作。

    异常处理流程:

    a) 客户端失败:死锁,网络不可达,无法正常工作

    NFS 4采用的租赁锁,有特定的租赁期限。若客户端失败,服务器不做任何特殊处理(无法区分客户端正常与否),等待租赁锁到期,锁自然释放。

    b) 客户端重启

    客户端重启,服务器根据客户端发过来的verifier可知客户端重启,服务器主动释放与该客户端id相关的所有锁。

    c) 服务器失败 -- 无法处理,只能重启服务器

    d) 服务器重启

    服务器重启将导致所有的客户端锁状态失效,客户端进行文件操作时将知道lock状态丢失。当lock状态丢失,client应该重建锁状态。

    Server重启后,lease period期间内为客户端重建锁状态时期。在此期间,server可以阻塞所有的读、写、lock等请求,除非server能够确保不发生锁冲突(比如持久化锁状态于磁盘)

    e) 网络不可达

    网络不可达,基本等同于客户端失败,服务器等待租赁锁失效。但当网络不可达和服务器重启同时出现时,可能出现两种难以处理的情形,需要持久化存储锁状态方能解决,略去。

     

    4) 如何保证“至多一次”的锁状态更新?

    在和文件锁相关的操作中(加锁,升级,降级,解锁),多次操作是不允许的。这就要求相应的操作具有“至多一次(at-most-once)”语义。为实现“至多一次”的锁状态更新,NFS引入“序列化机制”,以应对网络重传和重排序。具体实现如下:每个锁状态更新请求均携带序列号。该序列号是一个连续递增整数,由客户端维护,不同lock_owners拥有不同的序列号,初始值为0。服务器在状态表中缓存最后收到的序列号(last sequence number (L))和应答(response)。只有当下次锁状态更新请求的序列号为L+1时,该请求才被视为有效请求!

    注意:

    a) 客户端必须保证不多于一个的锁状态更新请求!(同一锁状态更新请求可多次发送,序列号相同)

    b) 当服务器收到相同的锁状态更新请求(序列号相同)时,缓存的应答将发送给客户端,而无相应锁操作被执行。

     

    5) 状态同步?客户端失败,服务器成功下的状态同步?

    当锁状态更新请求失败后,如超时,服务器的锁状态可能已经改变。为了保证客户端的锁状态的一致性,客户端应该重发“失败”的锁状态更新请求,同步状态,即客户端必须缓存失败的锁状态更新请求,并在下次提交锁状态更新请求前,重发该lock_owner缓存的锁状态更新请求!

    “二次确认机制”也能确保状态的一致性,但成本高,重发机制,只有在失败后才会重新发送,成本低(锁状态更新请求远比客户端认证频繁!)


    参考文献:RFC 3530

  • 相关阅读:
    start tag, end tag issues in IE7, particularly in xslt transformation
    用SandCastle为注释生成chm文档
    Firebug
    架构的重点
    Linux Shell常用技巧(十) 管道组合
    Linux JDK升级
    Linux Shell常用技巧(十二) Shell编程
    Packet Tracer 5.0实验(一) 交换机的基本配置与管理
    Linux Shell常用技巧(六) sort uniq tar split
    Linux Shell常用技巧(二) grep
  • 原文地址:https://www.cnblogs.com/zhenjing/p/NFS4_lock.html
Copyright © 2011-2022 走看看