HDFS SBN实现与ANN的一致性读
前言
众所周知,HDFS在启用HA模式下时,会有一个ANN(Active NameNode),以及一个SBN(Standby NameNode)。它们之间在通过QJM机制实现元数据的信息同步,简单的来说就是ANN将改动的元数据消息记录(editlog)写到JNN(JournalNode)上,然后SBN再从这些JNN上去读这些信息,再apply到自己的内存空间中。以此达到两边元数据的最终一致。其实从这里,我们能够很容易发现一个同步延时的问题,也就是说SBN内的元数据会略微延时于ANN。举个简单的例子,用户在HDFS内创建一个新的文件,然后立即去查询此文件的信息,在ANN上很显然我们能查到结果,但是从SBN上,可能就查不到。我们用一个专业的术语来描述这种现象:Stale Read,译为延时读。换个层面来说,这是一种读不一致性的问题,也是本文所讨论的一个核心问题点。
SBN实现一致性读的需求场景
针对SBN与ANN因为更新延时的造成的读不一致性问题,这是不是一个需要去解决的问题呢?毕竟元数据最终还是会一致的。但是有的时候,我们不能把问题想的这么简单,如果SBN真的能够做到与ANN的一致性读,那么相当于我们多了一个Read-Only的ANN,可以把SBN的RPC处理能力也给利用起来了。至少目前来看,SBN平时基本用不上,就等着failover切换时备着。下面是SBN实现一致性读更加具体化的应用场景:
- 充分利用SBN的处理能力,将所有读请求转向SNN处理,而让ANN只处理写请求,以此大大增强集群的处理能力。另外,Hadoop 3.0版本开始,HDFS是支持多SBN的,这无疑会更加强化此方面的优势。
- 从ANN,SBN层面讲集群的读写操作进行了分离,避免两种类型操作的互相干扰影响。
下面我们来看看SBN实现一致性读的语义定义以及实现细节。
SBN一致性读的定义和实现细节
SBN一致性读是社区目前在做的一个全新feature,JIRA链接:HDFS-12943:Consistent Reads from Standby Node,下面内容为笔者对其设计文档的一个小结,感觉还是非常有趣的。
语义定义
首先来看看SNN一致性读的标准语义定义:
如果一个客户端c看见或修改一个对象obj的状态id为modId1,在t1时间点。然后在未来任何大于t1的时间点t2,客户端c看到的obj的状态id modid2 >= modid1。
一致性读的细节实现
实现一致性读的核心思想是等SBN“追上”ANN的脚步,如果本身“落后”太远,则直接将请求重新转向ANN。
逻辑操作语义定义如下:
1.客户端c在内部维护2个lastSeenId,分别对应ANN,SBN:c.LastSeenId.ANN和c.LastSeenId.SBN。这2个id可理解为从客户端c的角度,分别从ANN,SBN所能够看到的最新事务id。
2.如果id c.LastSeenId.ANN <= c.LastSeenId.SBN,转向ANN,并更新 c.LastSeenId.ANN。
3.否则等待直到SBN追上c.LastSeenId.ANN。
其它细节要点如下:
- 需要定义一个新的FailoverProxyProvider类,比如叫做StandbyReadProxyProvider,此provider代理会将读请求转发到SBN上。
- 引入一个新角色ONN(ObserverNode),做SBN的备份,ObserverNode与SBN的区别是,前者只负责消费JNN上的editlog,但不做checkpoint操作。
- 为了使得SBN能够尽可能快地追上新的数据,需要实现SBN支持tailing in-progress的editlog。在当前逻辑中,SBN只读已经关闭了的editlog文件,然后一个整的segement文件去读。而一个关闭的editlog文件依赖于定期触发ANN的log roll操作,这期间就会有时间延时,无法立即消费到最新数据。倘若SBN能够支持读in-progress的数据,无疑将会大大减少其中的数据延时。
- ANN,SBN,ONN形成互相备份,转换关系,如下图。
ANN<===>SBN<===>ONN
参考资料
[1]. https://issues.apache.org/jira/browse/HDFS-12943. Consistent Reads from Standby Node