在副本冗余模式的分布式存储系统中,站在数据安全的角度来说,会采用同步复制的方案,即将数据都写入所有节点之后才返回给客户端。
image.png一个很简单的副本复制分发方案:先写完第一个副本,写完之后,再拷贝给第二三副本。但这个方案显然效率不高。
于是HDFS 提出了 pipeline 模型,假设下面以三副本为例:
客户端会将要写入的数据拆分为一个个Block,然后写入时是一个个Block的方式写入,而一个Block又会被拆分为若干个小包(packet)。
在发起写请求之前从NN 获取到三个副本的承载DataNode,然后建立pipeline 链路。
假设一个Block被拆成ABCD 四个包,按照pipeline 链路依次发送,当DN 接收到一个包时,先固化到本地,然后转手给下游,最后一个DN 固化完成后,会依次原路返回结果(ACK),最终客户端收到返回结果,代表本次写请求正式完成。
step1: Client(ABCD) -> DN1() -> DN2() -> DN3()
step2: Client(BCD) -> DN1(A) -> DN2() -> DN3()
step3: Client(CD) -> DN1(AB) -> DN2(A) -> DN3()
step4: Client(D) -> DN1(ABC) -> DN2(AB) -> DN3(A)
step5: Client() -> DN1(ABCD) -> DN2(ABC) -> DN3(AB)
step6: Client() -> DN1(ABCD) -> DN2(ABCD) -> DN3(ABC)
step7: Client() -> DN1(ABCD) -> DN2(ABCD) -> DN3(ABCD)
HDFS 使用这种方式将数据以管道的方式,顺序的沿着一个方向传输,这样能够充分利用每个机器的带宽,避免网络瓶颈和高延迟时的连接,最小化推送所有数据的延时。
pipeline 读的一致性设计
HDFS是支持一写多读机制的,意味着在流水线上的DataNode(正在被写)允许被其他客户端读取(Reader 以下均称此类读客户端为Reader)。这样就会产生读的不一致性,比如说我在流水线上游的某个DataNode中读到 "B" 这条数据,但是去下游的DataNode读,却读不到。这是因为下游的DataNode可能还没收到数据。
所以,处与正在 pipeline 过程中的 datanode 怎么判断自己数据是否可以被 Reader 读取呢?
首先我们提出对一个Block有两个关键定义:
- DR (Data Received)
一个DataNode接收到的数据为DR - DA(Data Acknowledged)
一个DataNode根据下游收到的ACK,已被下游确认接收的数据为DA
网友评论