HDFS之Observer NameNode

Observer NameNode

通常在一个HA的hdfs集群中,会有一个Active Namenode及一个或多个Standby Namenode。

  1. Active Namenode的主要作用:负责所有客户端的请求

  2. Standby Namenode的作用:

  • 跟踪并同步Journalnode上的edit logs

  • 接受来自所有datanode块位置信息

这些都是为了保持namespace的最新信息,以便在active节点故障的时候,使其能够快速接管服务。

在后续版本出现了一种新型的Namenode,Oberver Namenode,它本身和Standby namenode相似,除了承担之前standby的作用外,它主要负责客户端的读请求。是的,看到这里,这种namenode的出现的目的就不言而喻了,读写分离。单namenode确实会有吞吐量的瓶颈,Observer Namenode的出现可以帮助分担请求及带宽,从而提高整体的吞吐量。

在这个架构中,namenode可以有三种状态,active、standby和observer。状态切换只可以在active和standby,standby和observer之间,不可以直接在active和observer

保证读写一致性

客户端设置了一个State ID,每次请求都会将此ID加入到RPC请求的header。State ID就是Namenode的事务ID。客户端每次读写操作都会更新state ID。

客户端自读自写

  1. 客户端请求Active Namenode执行写操作,随后写操作成功之后,Namenode的response中会返回一个事务ID。此时客户端会存储该ID为State ID。

  2. 之后客户端执行读操作,此时将请求Observer Namenode,这次请求会带上State ID。如果Observer Namenode已经同步了最新的事务,那么进行检查后,将会返回请求。

这样单客户端的自写自读就实现了一致性。

那么我们其实能想到,如果上述客户端执行读请求时,Observer Namenode的事务ID小于客户端的State ID呢。那么可能请求就会卡在RPC queue从而增加了请求时间。甚至请求会失败,此时会回退到请求Active Namenode。这个确保的机制是由客户端代理类ObserverReadProxyProvider实现的,它继承了已存在的ConfiguredFailoverProxyProvider。

保证同步的新特性

这样其实问题就明晰了,在这个架构中最好保证Observer Namenode一直有最新的事务信息。所以tail edit logs是很关键的,会直接影响到读请求的时延。有一些新的机制,用来显著减少这个时延。如:Edit Tailing Fast-Path,RPC-based tailing instead of HTTP,in-memory cache on the JournalNode。

  • Edit Tailing Fast-Path:新的拉取机制,正常默认会等edit log完成之后拉取。但是新机制可以拉取in-progress状态的edit log,从而尽量保证与active同步。

  • RPC-based tailing instead of HTTP:采用rpc请求替换http,性能更好。

  • in-memory cache on the JournalNode:让Jn节点在内存中缓存edit log。这个特性主要是为RPC-based tailing服务的。

多个客户端保证一致性

假如此时客户端a执行完成了写操作,客户端b去读取该文件,此时b并不知道最新的事务ID,那么可能读不到a的写入的。

为了防止这种情况,metadata sync被加入,这是一个msync()方法。当客户端调用此方法时,它会通过Active Namenode获取并更新本地的State ID。这个操作是比较轻量的。这样如果b在读取之前调用了msync,那么自然能保证它能够读取到a之前的写入信息。

要实现msync()不需要改变代码,application启动时会在对Observer执行任何读操作之前自动调用msync(),这样在客户端初始化之前执行的任何写操作都是可见的。另外,ObserverReadProxyProvider支持auto-msync模式,启用之后会在特定的时间间隔(可设置)内自动执行msync()。默认是禁用的,因为调用此方法会有一定的开销。

这样多个客户端获取最新的State ID的问题解决了,但是在执行读取的时候,还是会碰见上面的问题,如果Observer Namenode当时并没有同步,那么请求还是会等待,或者用户可以通过上述tail edit log的参数设置,从而尽量避免这种情况。

配置

为了启用Observer Namenode,需要在hdfs-site.xml加入此配置:

    <property>
       <name>dfs.namenode.state.context.enabled</name>
       <value>true</value>
    </property>
  1. dfs.namenode.state.context.enabled 用于启用namenode使其可以维护和更新server state和id。 启用之后,namenode将会创建一个上下文实例,用于记录当前server的state id。Server state id也将会被传回客户端。为了优化Observer读用例的性能默认是被禁用的。但是为了启用Observer Namenode 特性,此配置需要被打开。

  2. dfs.ha.tail-edits.in-progress 对in-progress的edit log启用fast tailing。

    <property>
      <name>dfs.ha.tail-edits.in-progress</name>
      <value>true</value>
    </property>

此配置将启用fast tailing对in-progress edit log以及RPC-based edit log fetching,in memory cache in JournalNodes等等机制。默认禁用,使用Observer Namenode需要打开。

  1. dfs.ha.tail-edits.period Stangby/Observer Namenode从JournalNode获取edits的间隔
    <property>
      <name>dfs.ha.tail-edits.period</name>
      <value>0ms</value>
    </property>

默认是1分钟,建议设置一个更低的值,也不要太大。因为在Observer 获取edit logs和active nn的最新状态之前,请求都将在RPC队列中等待,这会导致RPC时间的增加

  1. dfs.ha.tail-edits.period.backoff-max Standby/Observer Namenode拉取edits是否执行回退
    <property>
      <name>dfs.ha.tail-edits.period.backoff-max</name>
      <value>10s</value>
    </property>

会有这么一种情况,当namenode尝试从jn获取edit但是发现没有最新的edit。当edit tailing的周期非常短时,这种情况会很普遍,此时集群并没有很高的负载。但是这样将会导致namenode即使在没有最新的edit时也会不断的尝试读取,会导致其高使用率。当这个配置启用后,当尝试edit tail却返回为0时将会执行指数回退,也就是会逐渐拉长等待的时间。此配置指定edit tailing尝试的最大等待时间。

  1. dfs.journalnode.edit-cache-size.bytes JournalNode在内存中缓存edit的字节数
    <property>
      <name>dfs.journalnode.edit-cache-size.bytes</name>
      <value>1048576</value>
    </property>

这个缓存主要被用于RPC-based tailing。此配置仅仅当dfs.ha.tail-edits.in-progress打开时有用。

  1. dfs.namenode.accesstime.precision 是否对HDFS file启用access time。
    <property>
      <name>dfs.namenode.accesstime.precision</name>
      <value>0</value>
    </property>

建议禁用此配置。如果启用,这将把getBlockLocations调用转换为写调用,因为它需要保持写锁来更新打开文件的时间。因此,请求将在所有的Observer namenode上失败,并最终退回到active节点。因此,RPC性能会下降。

客户端配置(hdfs-site.xml)

用于启用Observer Namenode特性:

<property>
    <name>dfs.client.failover.proxy.provider.<nameservice></name>
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ObserverReadProxyProvider</value>
</property>
<property>
    <name>dfs.client.failover.observer.auto-msync-period.<nameservice></name>
    <value>500ms</value>
</property>

如果客户端希望使用auto-msync功能,可以使用以下配置。这指定的是一个时间周期,如果客户端的state ID并没有从active nn更新,msync()将自动被执行。如果指定为0,该方法在每次读操作之前都将执行。指定负数,不会自动执行。如果指定一个正的时间周期,那么每次读操作时,超过这段时间没有联系active则将被执行。

为了启用observer支持,必须需要一个HA的且大于2个namenode的HDFS集群。之后,你需要将Standby Namenode 转变为observer状态。一个集群最小的配置,active、standby、observer各一个。对于更大的集群,根据读请求的强度和HA的需要,我们建议运行两个甚至更多的observer namenode。

状态转换命令

haadmin -transitionToObserver

一个新的HA admin命令,将Standby Namenode转换到Observer state。只能在Standby Namenode上执行,在active nn上执行将抛出异常。类似地,transactionToStandby只能执行在Observer Namenode,将其转变为Standby状态。

缺点:

当前Observer Namenode并没有完成集成自动failover。如果dfs.ha.auto-failover.enabled为true,仅仅只是在Observer Namenode之上运行一个ZKFC。唯一的好处:当你将Observer Namenode的状态转换为standby之后,它将使其之上的Namenode自动参与active的选举。当然如果你并不需要,你可以禁用ZKFC在Observer Namenode上。除此之外,对于transitionToObserver命令你也需要增加一个forcemanaual参数。

haadmin -transitionToObserver -forcemanual
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值