前言
在Ozone目前数据写出的过程,是基于从对象文件的block,再从block到chunk粒度进行数据的写出的。每次Ozone写完一个chunk后,对应着会触发一次write chunk的RPC call。当我们写入的数据文件对象很大的时候,过程中将会涉及到很多次write chunk PRC的操作调用。这个RPC call的频繁调用意味着相应更多的transaction的发生。对于Ozone Datanode里使用Raft协议做数据一致性同步过程的影响而言,则意味着更多的raft log需要被apply以及对应Ratis snapshot的take操作也会变得更加频繁。在一定程度上,这会影响到Datanode节点本身的数据写出操作。最近社区提出了利用Ratis Streaming的特性来优化Ozone数据写出的流程。本文笔者来简单聊聊Ozone Streaming这种全新方式的数据写出过程,目前此功能处于有一个初步的设计方案阶段。
Ozone Streaming的实现背景:Ratis Streaming
首先我们来聊聊Ozone Streaming的一个大的背景,Ozone Streaming想法的提出源自于Ratis Streaming特性。Ratis Streaming,顾名思义,指的是能用流的方式将数据写出去而不是通过传统RPC模式,将数据一点一点写出去。
在Ratis Streaming功能中,除了其能够减少数据写过程中的RPC数,还有另外一个改进是它使用了netty作为底层流原理的实现,能够做到数据传输过程中的的zero buffer copy的功效。同时在streaming方式的数据写出过程里,写出操作是在一个流里进行的,因此不会涉及到频繁的流关闭操作。
目前Ratis Streaming功能分为了2个阶段的实现:
一阶段:实现无transaction创建的流数据写出过程
二阶段:数据Pipeline写出的方式的优化,从原来的Leader到Follower的start-topology结构变为纯线型的Pipeline处理模式。
这部分细节可参考RATIS-979上设计文档的描述。
Ozone Streaming方式写过程
在上文部分已经提到过,现有Ozone写过程存在着transaction操作过多导致的一些性能效率上的问题。而且目前从Ozone Client写数据传输到最终Datanode上,存在着大量的buffer数据的拷贝开销。另外由于Ozone目前支持了multi raft功能后,一个Datanode可以被包含在多个raft group组里。这样使得当一个Datanode成为多个raft leader时,这个节点会表现出一定的热点瓶颈的现象。
但是现在在Ratis Streaming方式下,我们可以通过流的方式进行数据的写出了,然后在前面流数据结束的时候,进行最后一次的block的commit操作。此过程图如下所示:
此图第一部分阶段为数据流写出的过程,每次数据传输以packet为单位,进行依次数据的写出。当client每次收到所有packet数据写出ack结果之后,才能继续写出下一个packet的数据。
当所有packet数据都写出去之后,则再进行最后block的提交的过程,在此过程中才会有transaction的发生。这种流式方式的数据写出比之前通过每次小批量数据的RPC数据写出的方式减少了很多的transaction的发生和处理。
但这里还是有可能遇到流数据写出失败的情况,比如没有收到全部节点的ack回复等等。这个时候我们需要让它怎么做呢?
在设计文档中的做法是,提前进行block数据的提交来结束此流数据的写出,以上次成功ack回复时数据写出的大小作为提交的length。这种失败处理方式至少能保证当前streaming写出的数据都是正确的。此失败过程处理图如下所示:
以上就是本文简单介绍的Ozone Streaming方式的数据写过程的新设计,设计细节可参阅JIRA HDDS-4454。
参考资料
[1].https://issues.apache.org/jira/browse/HDDS-4454
[2].https://issues.apache.org/jira/browse/RATIS-979
来源:oschina
链接:https://my.oschina.net/u/4390260/blog/4842218