2019-03-10 09:39  阅读(1998)
文章分类:Hbase 源码 文章标签:大数据HbaseHbase 源码
©  原文作者:岑玉海 原文地址:https://www.cnblogs.com/cenyuhai/tag/hbase%E6%BA%90%E7%A0%81%E7%B3%BB%E5%88%97/

作者:岑玉海

出处:https://www.cnblogs.com/cenyuhai/tag/hbase%E6%BA%90%E7%A0%81%E7%B3%BB%E5%88%97/


Hbase 版本:0.96

hbase是一个KeyValue型的数据库,在《hbase实战》描述它的逻辑模型【行键,列族,列限定符,时间版本】,物理模型是基于列族的。但实际情况是啥?还是上点代码吧。

HTableDescriptor tableDesc = new HTableDescriptor("test");
       //日志flush的时候是同步写,还是异步写
       tableDesc.setDurability(Durability.SYNC_WAL);
       //MemStore大小
       tableDesc.setMemStoreFlushSize(256*1024*1024);

       HColumnDescriptor colDesc = new HColumnDescriptor("f");
       //块缓存,保存着每个HFile数据块的startKey
       colDesc.setBlockCacheEnabled(true);
       //块的大小,默认值是65536
       //加载到内存当中的数据块越小,随机查找性能更好,越大,连续读性能更好
       colDesc.setBlocksize(64*1024);
       //bloom过滤器,有ROW和ROWCOL,ROWCOL除了过滤ROW还要过滤列族
       colDesc.setBloomFilterType(BloomType.ROW);
       //写的时候缓存bloom
       colDesc.setCacheBloomsOnWrite(true);
       //写的时候缓存索引
       colDesc.setCacheIndexesOnWrite(true);
 //存储的时候使用压缩算法
    colDesc.setCompressionType(Algorithm.SNAPPY);
       //进行compaction的时候使用压缩算法
       colDesc.setCompactionCompressionType(Algorithm.SNAPPY);
       //压缩内存和存储的数据,区别于Snappy
       colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX);
       //写入硬盘的时候是否进行编码
       colDesc.setEncodeOnDisk(true);
       //关闭的时候,是否剔除缓存的块
       colDesc.setEvictBlocksOnClose(true);
       //是否保存那些已经删除掉的kv
       colDesc.setKeepDeletedCells(false);
       //让数据块缓存在LRU缓存里面有更高的优先级
       colDesc.setInMemory(true);
       //最大最小版本
       colDesc.setMaxVersions(3);
       colDesc.setMinVersions(1);
       //集群间复制的时候,如果被设置成REPLICATION_SCOPE_LOCAL就不能被复制了
       colDesc.setScope(HConstants.REPLICATION_SCOPE_GLOBAL);
       //生存时间
       colDesc.setTimeToLive(18000);

       tableDesc.addFamily(colDesc);

 在上面列出来表定义和列族定义的所有参数,含义也标上去了,我们经常需要设置的可能就是下面的这些。

//bloom过滤器,过滤加速
       colDesc.setBloomFilterType(BloomType.ROW);
       //压缩内存和存储中的数据,内存紧张的时候设置
       colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX);
 //让数据块缓存在LRU缓存里面有更高的优先级
       colDesc.setInMemory(true);
       //最大版本,没必要的话,就设置成1个
       colDesc.setMaxVersions(1);
       //集群间复制的时候,如果被设置成REPLICATION_SCOPE_LOCAL就不能被复制了
       colDesc.setScope(HConstants.REPLICATION_SCOPE_GLOBAL);
 //存储的时候使用压缩算法,这个基本是必备的,hbase的存储大得惊人
    colDesc.setCompressionType(Algorithm.SNAPPY);
       //进行compaction的时候使用压缩算法
        colDesc.setCompactionCompressionType(Algorithm.SNAPPY);

hbase的表在hdfs上面的是这么存储的,/hbase-root/tableName/regionName/familyName/HFile, 在tableName这一级目录会有一个名.tabledesc的文件,在region这一级目录有一个名为.regioninfo的文件,都是明文的。

了解完表和列族的定义之后,我们看看KeyValue是怎么存储的吧,引用一下代码,可能大家一看就都懂了。

@Override
   public void write(Cell cell) throws IOException {
     checkFlushed();
     // Row rowkey,起始位置,长度
     write(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
     // Column family 列族,起始位置,长度
     write(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
     // Qualifier 列名,起始位置,长度
     write(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
     // Version 时间戳
     this.out.write(Bytes.toBytes(cell.getTimestamp()));
     // Type Put或者Delete
     this.out.write(cell.getTypeByte());
     // Value 值,起始位置,长度
     write(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
   }

好吧,列存储的话存储的时候每个列都会重复前面的rowkey、列族这些信息,在列很多的情况下,rowkey和列族越长,消耗的内存和列族都会很大,所以它们都要尽量的短。

可以考虑用colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX_TREE)来压缩一下内存中的大小,这个后面后面会讲到。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> hbase源码系列(四)数据模型-表定义和列族定义的具体含义
上一篇
hbase源码系列(三)Client如何找到正确的Region Server
下一篇
hbase源码系列(五)Trie单词查找树