前不久时间,Apache Hadoop发布了新的基线版本-Hadoop 3.0.0正式发布,过去一段时间我们看到的发布版本都是各种3.0 alpha,beta版本。此次Hadoop 3.0正式发布,具有非常重大的意义。在此次Hadoop 3.0版本中的HDFS模块,除了EC(纠删码)外,还有一个Feature特性也值得我们关注–RBF(Router-based Federation,基于路由的Federation方案)。用一句简单的话来介绍这个Feature:HDFS将路由信息放在了服务端来处理,而不是在客户端。以此完全做到对于客户端的透明。不过本文,笔者不是介绍RBF特性的,这部分内容博友们可以参考阅读笔者之前几篇相关的文章。本文将要阐述的内容是笔者最近在设计的基于RBF至少上的全局配额(Quota)管理、我们都知道,在单一的HDFS集群内,是可以支持针对目录设置配额值的,以此来管理每个目录下的文件数或是空间使用量。但是如果我们使用的集群是一个federation方式的集群呢?这个我们怎么操作?本节笔者就来聊聊这个话题。
在单一的HDFS集群内,笔者相信很多公司为了规范各个业务方对于集群的正确使用,一般会给每个业务方一个专有的目录路径并设定quota值,包括命名空间值和存储空间值。这在一定程度上是进行了有效管理。
但是当随着业务规模扩张,很多时候单一集群是很难以满足所有的应用场景的。此时,就会出现多集群的情况,但是我们又想将这些集群统一管理起来,就会以federation的方式提供给外部用户使用。此时用户看到的尽管说还是一个集群,但其实它是由许多子集群所构成。此时,我们需要设置的quota值的作用域就不在是单单某特定集群的特定路径了。所以这就是笔者提出全局quota的概念以及它的意义所在了。
首先要为大家解释一下,federation下的Quota含义。在单一集群内,我们对某个目录路径设置quota值,那么它的作用域就是针对这个特定集群,这个特定路径的,一旦这个路径下的文件数或使用空间超出了quota设定的阈值,就会抛出异常并拒绝执行接下来的操作。
但是如果我们是在federation模式下,一个路径代表的含义就不太一样了,它往往意味着横跨多个集群。什么意思呢?举个例子,比如我们有以下federation 目录路径,
/path/----->(ns0---/path)
/path/subdir--->(ns1---/path)
上面的意思是,federation路径/path实质对应的路径是ns0集群的/path路径,而federation路径/path/subdir路径对应的路径是ns1集群的/path路径。然后我们说/path这个逻辑上的路径其实就横跨了2个集群:ns0和ns1。倘若此时我们对federation路径/path设置Quota值。那么此时此Quota的含义应为:ns0的/path和ns1集群的/path所代表的目录的使用值的汇聚和不能超过Quota配额值。我们federation模式我们可以想象为一个逻辑的单一文件系统,所以我们做配额管理时也要把/path/subdir这个子目录考虑上。
既然我们了解了Federation模式下的配额含义,下面紧接着需要想想如何实现相应的API:setQuota和getQuotaUsage。这可是HDFS FileSystem定义接口中的2个必须实现的方法。
与上节一样,这2个API在语义上与在单一集群模式下是完全不同的:
setQuota:为federation路径设置quota值。因为federation路径是虚拟的,它的转化含义为:为federation路径下所属的所有真实的hdfs路径设置quota值,这里是需要包括其子路径对应的集群路径地址的。
getQuotaUsage:获取quota值的调用则恰好是相反的过程。它首先要找出给定federation路径对应下的所有子集群地址,然后调用getQuotaUsage的操作,获取它们的quota使用值,最后将这些值汇总并进行返回。这个总和值即为federation路径的quota使用值。
因为Federation模式下,本身我们没有自己来计算quota使用值,而是通过汇总子集群的quota使用值来进行quota的计算的,所以本质上这还是依赖于原始的Quota实现的。
所以在federation模式下的quota判断也很简单,大体如下:
1、对某个federation路径发起写请求时,获取此路径的quota值(即调用上节中的getQuotaUsage实现),然后进行quota的检验。
2、如果quota值超出阈值,抛出异常。
上面步骤说起来容易,但是很有可能会造成性能问题,这里面会有大量的RPC调用(getQuotaUsage)产生。相当于每来一次写请求,就必须至少额外调用一次查询quota请求,相当于请求翻倍了。
为此,笔者在设计这个方案时,做了如下2点调整:
第一,在本地新增一个quota缓存,保存的关系为<逻辑路径, Quota使用汇聚值>。每次执行quota检验时,都从这个缓存里去取。
第二,新增quota缓存更新服务。这是一个异步的周期性任务,执行的操作就是向真实集群查询quota值,并更新缓存。这个设计在一定程度上是牺牲一点时效性来换取更好的性能。
Federation模式下的quota管理更细节的内容,大家可以前往JIRA HDFS-12934上进行更加深入的学习。
[1].https://issues.apache.org/jira/browse/HDFS-12934