1. dfs.block.size hadoop分区块的大小,应该大于HFile文件和HLog文件的大小.
3. HRegion.blockingMemStoreSize ,MemStore中阻塞的threshold,=HRegion.memstoreFlushSize * conf.getLong("hbase.hregion.memstore.block.multiplier", 2);
4. Store.compactionThreshold = conf.getInt("hbase.hstore.compactionThreshold", 3);By default, we compact if an HStore has more than MIN_COMMITS_FOR_COMPACTION map files,如果Store下的StoreFile数量大于等于这个值(updateStorefiles(...)).那么就需要compact.
5. Store.desiredMaxFileSize , HFile文件的最大值.通过HTableDescriptor.setMaxFileSize(long maxFileSize)方法设置.
// By default we split region if a file > HConstants.DEFAULT_MAX_FILE_SIZE.
long maxFileSize = info.getTableDesc().getMaxFileSize();
if (maxFileSize == HConstants.DEFAULT_MAX_FILE_SIZE) {
maxFileSize = conf.getLong("hbase.hregion.max.filesize",
HConstants.DEFAULT_MAX_FILE_SIZE);
}
this.desiredMaxFileSize = maxFileSize;
7. HColumnDescriptor.setInMemory(boolean inMemory) 方法,和HColumnDescriptor.setBlockCacheEnabled(boolean blockCacheEnabled),如果blockCacheEnabled为true,那么StoreFile在创建Reader时会创建一个BlockCache对象(默认为LruBlockCache),reader读取数据时,先从BlockCache中读取,如果缓存中没有,而且本次读取的结果可以缓存,那么把结果(CachedBlock)缓存到BlockCache中.
inMemory,BlockCache在创建缓存对象时,会根据inMemory来设置不同的类型,不同类型在总的缓存空间中占的比例不同(BlockBucket),这样一旦BlockCache的空间不够用,要清除一些缓存时,就会对不同的对象有不同的清除策略.
8. HFile文件中的BlockIndex是都读入到内存中的,在调用loadFileInfo()方法时,会创建一个BlockIndex对象,BlockIndex中保存bolock index 信息,这些信息由HFile.Writer在append()和close()时保存.
这里要强调的是,block index中的key为KeyValue中的所有key信息,包括row-key,columnfamily,columnqualifier,和timestamp及keytype(???).而且每个key为Block中的第一个key.
9. KeyValue类,KeyValue wraps a byte array and has offset and length for passed array at where to start interpreting the content as a KeyValue blob. The KeyValue blob format inside the byte array is: <keylength>(int,4字节) <valuelength>(int,4字节) <key> <value> Key is decomposed as: <rowlength>(short,2字节) <row> <columnfamilylength>(byte,1字节) <columnfamily> <columnqualifier> <timestamp>(long,8字节) <keytype>(byte,1字节) Rowlength maximum is Short.MAX_SIZE, column family length maximum is Byte.MAX_SIZE, and column qualifier + key length must be < Integer.MAX_SIZE. The column does not contain the family/qualifier delimiter.
10. Store
A Store holds a column family in a Region. Its a memstore and a set of zero or more StoreFiles, which stretch backwards over time. 每个Store对应一个column family, 其中包含一个MemStore(内存缓冲),和多个StoreFile(HFile文件).
There's no reason to consider append-logging at this level; all logging and locking is handled at the HRegion level. Store just provides services to manage sets of StoreFiles. One of the most important of those services is compaction services where files are aggregated once they pass a configurable threshold.
11. HRegion.internalFlushcache()
因为在MemStore中有一些更新过的内容,我们应该把这些更新放到HFile文件中,HLog文件也应该保存每次flush的state(通过sequence id相当于时间段来实现),这样即使我们从HLog文件来恢复数据,也能知道那些数据要恢复,那些数据不用恢复.方法会根据StoreFile的实例(也是HFile文件的数量)来判断是不是应该执行compact操作(Store.updateStorefiles(...)方法).
A. Flush the memstore to the on-disk stores, noting the current sequence ID for the log.
B. Write a FLUSHCACHE-COMPLETE message to the log, using the sequence ID that was current at the time of memstore-flush.
C. Get rid of the memstore structures that are now redundant, as they've been flushed to the on-disk HStores.
12. HRegionServer中LinkedBlockingQueue<HMsg> outboundMsgs用来存放发送给HMaster的信息.
14. StoreFile 是不是reference name 的正则表达式 ^(\\d+)(?:\\.(.+))?$ ,group(2)不为空.
15. Store.storeSize 所有StoreFile(HFile)文件的大小.
16. Store.checkSplit(boolean force) 是不是进行split操作
a. storeSize < this.desiredMaxFileSize,也就是所有的storeFile文件的总和小于设定的最大文件数量,那么不进行split.
b. meta region 不能split.(???那-META- region多个记录的时候怎么处理.)
c. 取所有StoreFile中文件最大的那个,并取该StoreFile的midkey,midkey是从HFile文件中的BlockIndex中选取,取中间下标的那个((this.count - 1)/2).midKey为KeyValue中的key值(包含rowlength,row,columnfamilylength,columnfamily,columnqualifier,timestamp)(???不知道这里包不包括keytype),所以要取row出来,还有storeSize.
17. Store.compact(List<StoreFile> filesToCompact, boolean majorCompaction, long maxId) 多个StoreFile文件合并成一个文件的方法.
18. HRegion.compactStores(boolean majorCompaction) HRegion下的compact操作.
19. HRegionServer
a. HBaseServer server -- 监听服务,listen for request from HMaster ,other region server or Client.
b. ServerConnection connection -- 与其它region server的通信.
c. HMasterRegionInterface hbaseMaster -- 持有的HMaster连接.
20. HRegion.close(boolean abort)
a. close会等待所有的writelock被释放,这可能会要比较长的时间,特别是用户的connetion在未释放获得的锁就失去连接时.
b. 非abort的close会把MemStore中的内容写入到StoreFile中,这些文件都是由hadoop来管理,如果网络不好,也可能需要很长的时间.
21. HRegion的split操作.
a. 由CompactSplitThread来具体执行,通过向thread的compactionRequested( LinkedBlockingQueue<HRegion>)中写入请求就可能触发compact和split.
b. split之前会先进行一个compact操作.这个compact操作可能是minor compact也可能是major compact.
c. compact后,会从所有的Store下的所有StoreFile文件最大的那个取midkey.这个midkey可能并不处于全部数据的mid中.一个row-key的下面的数据可能会跨不同的HRegion.
d. 然后根据这个midkey将HRegion下的所有Store分割,生成Reference文件.
e. 创建新的Reference后,及生成新的region目录层次结构,报告HMaster offline region,写入-ROOT-或者-META-表.(??? CompactSplitThread.split(HRegion region, byte[] midKey) 这里有个小疑问,在报告给HMaster oldRegion offline以后,当前的Region Server崩溃了,-ROOT-或者-META-表中还没有插入任何记录,那么这个region不是要一真offline下去,这里要看下HMaster的处理)
f. 具体查看CompactSplitThread类
HRegion split后,原HFile文件并不会被马上切分,只是通过Reference文件指明bloom,或者top选项,在创建Reader时读取原来的HRegion目录下的内容,如果HMaster把新的Region分配给其它Region Server,那么HFile的数据不能保证本地化(即使HBase与Hadoop在同一个集群内),只有当HRegion下的Store进行一次major compact时,数据才会全部本地化.由于major compact的条件是时间间隔,那么不同的Store 执行major compact的时间可能并不一样.
22. MajorCompactionChecker
a. extends Chore,每个时间间隔(threadWakeFrequency*conf.getInt("hbase.server.thread.wakefrequency.multiplier", 1000))来检查Region Server下的所有HRegion是不是可以进行major compaction,如果可以就把这个请求发送给CompactSplitThread.
b. HRegion 检查所有的Store是不是进行major compaction.
23. Store判断是不是进行major compact的操作是在Store.isMajorCompaction(...)中进行的,判断的大概思路为
a. 取Store所在目录(/hbase/Keyspace1/0e08760dc41b6b83bb72948339f83de7/Standard1)目录下的所有文件(这些都应该是HFile文件),选取其中修改时间最古老的那个.
b. 判断那个古老的时间是不是也早于now - this.majorCompactionTime(当前时间回溯我们设定的时间),如果早于那么进行major compact.
24. Store.majorCompactionTime 执行major Compact 的时间间隔最大是多少.
这个时间的设置既可以通过conf来设置HConstants.MAJOR_COMPACTION_PERIOD = "hbase.hregion.majorcompaction",也可以通过创建表时的HColumnDescriptor.setValue(HConstants.MAJOR_COMPACTION_PERIOD, "86400000");来设置,这样不同的columnFamily就有了不同的频率.详细信息看Store
25. MemStoreFlusher 负责把MemStore内存中的数据写入到HFile文件中.
a. HRegion的put,delete操作都会检测memStoreSize是不是达到了memstoreFlushSize.
b. HRegion.memstoreFlushSize,TableDescription中的MEMSTORE_FLUSHSIZE_KEY ,在创建表时由HTableDescriptor.setMemStoreFlushSize(long memstoreFlushSize)方法指定,决定从MemStore中flush到HFile文件的threshold.
c. 如果HRegion要求memstoreflush,那么会将当前HRegion放入到MemStoreFlusher.flushQueue队列中.
d. HRegionServer对每次的put,delete操作都会去调用reclaimMemStoreMemory()方法,看整个HRegionServer的MemStore size是不是超过了最大的内存限制(MemStoreFlusher创建时设置)
对MemStore的管理,并不是针对每个Store的,尽管MemStore是每个Store创建时创建的,这样设定memstoreFlushSize时应该考虑到所有的column family的数据更新的量有多少.
26. HRegionServer启动时,会一直等待直到能从ZooKeeper中取到HMaster的地址信息,并且会在/hbase/master上注册一个Watcher(HRegionServer本身),具体执行的细节可以看HRegionServer.process(WatchedEvent event)方法.