HBase读的实现
我们先来分析一下相同的Cell(数据)可能存在的位置:首先对新写入的Cell,它会存在于MemStore中;然后对之前已经Flush到HFile中的Cell,它会存在于某个或某些StoreFile(HFile)中;最后,对刚读取过的Cell,它可能存在于BlockCache中。既然相同的Cell可能存储在三个地方,在读取的时候只需要扫瞄这三个地方,然后将结果合并即可(Merge Read),在HBase中扫瞄的顺序依次是:BlockCache、MemStore、StoreFile(HFile)(这个扫描顺序的目的也是为了减少磁盘的I/O次数)。其中StoreFile的扫瞄先会使用Bloom Filter(布隆过滤算法)过滤那些不可能符合条件的DataBlock,然后使用Block Index快速定位Cell,并将其加载到BlockCache中,然后从BlockCache中读取。我们知道一个HStore可能存在多个StoreFile(HFile),此时需要扫瞄多个HFile,如果HFile过多又是会引起性能问题。
Compaction机制
MemStore每次Flush会创建新的HFile,而过多的HFile会引起读的性能问题,那么如何解决这个问题呢?HBase采用Compaction机制来解决这个问题。在HBase中Compaction分为两种:Minor Compaction和Major Compaction。
1. Minor Compaction是指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。一次Minor Compaction的结果是更少并且更大的StoreFile。(这个是对的吗?BigTable中是这样描述Minor Compaction的:As write operations execute, the size of the memtable in- creases. When the memtable size reaches a threshold, the memtable is frozen, a new memtable is created, and the frozen memtable is converted to an SSTable and written to GFS. This minor compaction process has two goals: it shrinks the memory usage of the tablet server, and it reduces the amount of data that has to be read from the commit log during recovery if this server dies. Incom- ing read and write operations can continue while com- pactions occur. 也就是说它将memtable的数据flush的一个HFile/SSTable称为一次Minor Compaction)
2. Major Compaction是指将所有的StoreFile合并成一个StoreFile,在这个过程中,标记为Deleted的Cell会被删除,而那些已经Expired的Cell会被丢弃,那些已经超过最多版本数的Cell会被丢弃。一次Major Compaction的结果是一个HStore只有一个StoreFile存在。Major Compaction可以手动或自动触发,然而由于它会引起很多的I/O操作而引起性能问题,因而它一般会被安排在周末、凌晨等集群比较闲的时间。
如何实现Compaction:
1.通过API:
//--minor compact
admin.compact("tab2".getBytes());
//--major compact
admin.majorCompact("tab2".getBytes());
2.通过指令:
compact('tab2')
major_compact('tab2')
更形象一点,如下面两张图分别表示Minor Compaction和Major Compaction。
Hbase默认用的是Minor compaction。之所以默认不用Major Compaction的原因是在于,Major Compaction可能会带来大量的磁盘I/O,从而阻塞HBase其他的读写操作。所以对于Major Compactoin,一般选择在业务峰值低的时候执行。所以使用Major Compact 一般在周末或凌晨去执行