对HBase而言,PREAD和STREAM有什么区别?

在Scan中,用户可以设置ReadType:
 
  @InterfaceAudience.Public
public enum ReadType {
DEFAULT, STREAM, PREAD
}

 
我看HBase代码中,有些地方设置PREAD, 有些地方设置STREAM, 所以想问下:
pread和stream实现上有什么区别? 性能上有什么区别?什么情况下适合用pread,什么情况下适合用stream操作? 请教~~
已邀请:

openinx - HBase Committer @小米

赞同来自: hmaster

具体到HBase代码中的HFileBLock#readAtOffset方法,可以比较好的说明PREAD和STREAM的区别.
  1. pread其实就是positional read, 每次都会发一个offset到datanode,让datanode去seek到对应的位置,然后读取数据. 在同一个DFSInputStream上可以跑多个pread操作.pread适合的场景是小数据量的随机读,就是频率高且数据量小的操作,典型的例如small scan操作以及读取meta表定位rowKey所在region的操作,这些操作一般默认都用PREAD.
  2. stream其实是seek + read,就是发一个offset到datanode,然后就不需要你再发offset给datanode了,然后datanode依次吐数据给你.因此,同一个DFSInputStream上跑多个stream的话,吐出来的数据就乱了.stream更适合较大数据量的顺序scan操作,典型的场景例如业务扫表操作以及Compaction的扫表操作.

 
参考资料:https://issues.apache.org/jira/browse/HBASE-17917

libis - HBase爱好者

赞同来自: hmaster

stream其实是seek + read,就是发一个offset到datanode,然后就不需要你再发offset给datanode了,然后datanode依次吐数据给你.
 
这个我理解是先seek到给定offset,然后再依次读取数据,读取多少还是在读取的时候指定的吧。我看stream模式中seek是synchronized方法,所以不能并发?
 
我个人的理解:
1. 单线程访问一个hfile的话,seek+read性能优于pread(为什么?),所以在并发量比较小的场景下使用stream模式比pread模式更合适。顺序scan属于这种模式?
2. 多线程访问一个hfile的话,因为seek是一个synchronized方法,即使多个线程读取的是不同的block,也需要串行执行,因此seek+read性能没有pread好。因此大量随机读,频率高而且数据量小,比如small scan操作,pread模式比stream模式更合适
 
https://issues.apache.org/jira/browse/HBASE-17917  这个jira说的是建议所有请求(无论顺序scan还是small scan抑或get)默认都使用pread模式。
 

libis - HBase爱好者

赞同来自:

seek+read原理:seek是DFSInputStream全局有一个pos,seek就是前后移动这个全局pos,因此并发情况下需要使用锁控制这个全局的pos。
pread原理:pread不需要全局的pos,而是根据目标offset定位目标block列表,再一个block一个block遍历读取,将数据返回。
 
因此不考虑并发的话明显seek+read性能好于pread,但在并发场景下pread性能会好于seek+read。当然,如果在stream模式下每个file读取都是不一样的DFSInputStream对象的话,性能会更好。

要回复问题请先登录注册