HBASE  基本结构
一。overview
1. hbase <=> NOSQL 
    不错,hbase 就是某种类型的nosql 数据库,唯一的区别就是他支持海量的数据。
    hbase的基本功能: 
    1) 强一致性的读写,而非“最终一致性”(eventually consistent)的数据仓库。基于此,hbase非常适合高速的统计计数工作。
    
    2)自动sharding ,hbase 是分布式的数据库,支持数据的自动切分。

    3) regionServer 的自动failover 

    4)  集成hadoop/hdfs ,habase 是构建在hadoop/hdfs 文件系统上的。

    5)  支持mapreduce 

    6)  java client api

    7) Thift/Rest  api : 支持非java 语言的访问。

    8) 数据块级cache 及布隆过滤(bloom filter) 

    9) 集成操作管理系统,提供基于web 及command-line的工具。

2.适用场景:

    1) hbase 并非适合所有的场景,首先,你要有足够的数据,如果只有几百万笔记录,一般的RDBMS 就可以管理了。 hbase 设计是支持数十亿记录级别的数据仓库
    
    2) hbase 不支持RDBMS的功能,比如表连接,索引,排序等。

    3) 确信,你有足够的硬件系统来支持。hbase 不保证能够在5个节点一下的集群中,正确的运行。


3.hbase 与hadoop/hdfs 的区别: 

    1) hdfs 是一个分布式的文件系统,他非常适合于存储大文件,他仅完成了一般文件系统的功能,他不支持文件内部记录级别的搜索功能。

    2) hbase 是构建在hdfs之上的,并且提供了记录级别的快速查找功能。hbase 将数据放在索引过的storefile 中。

二。字典表

    hbase 的数据字典: -ROOT-  .META  这俩表被hbase shell 的list 命令过滤掉,不显示,但是他们跟普通的hbase TABLE 是一样的。

1.ROOT 
    1) root表记录了.META. 表的位置 他的结构: 

     A) Key: 
        .META. region key(.META.,,1)
     
     B) Values: 
        info:regioninfo (serialized HRegionInfo instance of .META.)
        info:server    (server:port of the RegionServer holding .META.)
        info:serverstartcode (start-time of RegionServer process holding  .META.) 

2.META. 
    1) META. 表 保存了系统中所有的regions 的信息,结构:

    A) Key: 
        Region key of the format ([table],[region start key],[region id])

    B) Values:
        info:regioninfo (serialized HRegionInfo instance for this region)
        info:server (server:port  of the RegionSever containing this region) 
        info:serverstartcode (start-time of the RegionSever process containing this region) 

    2) 当一个region 正在执行split 的时候,会出现另外两个列 info:splitA 与 info:splitB 这俩列的值也是HRegionInfo 的实例,当split 完毕后,这两列会被删除掉。 

    3) 注意:  HRegionInfo: 如果key 为空,指示表的开始与表的结尾,
        如果一个region 有空的start key 则这个region 是表的第一个region。  如果region 同事有空的start key 与空的end key ,那么这个表只有当前一个region。 

3.启动序列: 

    META. 的位置写入ROOT  META. 跟新server 与startcode 的值。

三。 CLIENT 

    Hbase 的client HTable 负责查找resionserver 用来提供基本的操作,通过查询.META. 以及-ROOT- 字典表来查找regionsever 。 
    一旦找到对应的region ,客户端会直接连去region 对应的resionserver ,同事也会cache 这个结果,之后就不再通过meta. 来读写数据,除非这个regionserver死掉,才会从新从meta. 查找新的regionserver 。 

1.连接: 

    HTable 不是线程安全的,不适合多线程调用。一般建议使用HBaseConfiguration 实例来连接数据库。 

    1) 连接池,目前没有最终的解决方案,有个HTablePool ,但是难于管理。
    
        一般提前建立一个数组来存储已经建立的连接: 
        HConnectionManager.createConnection(Configuration)

    2) WriterBuffer 与批量(batch) 方法
        如果客户端的 AutoFlush 被设为off 那么数据的写入,会先写满writebuffer 然后再刷新的resionserver。 writebuffer 默认是2MB . 
    注意: htable.delete(Delete) 方法,不会进入writebuffer 。
    关于控制writebuffer 的细粒度的参考 HTable的batch 方法。

    3) 对非java 客户端的支持。 

    4) 行级锁, 目前的client 还有行级锁,以后的版本会去除这块。 

四. 客户端请求过滤(Client Request Filter) 

    Get 与Scan 实例,可以配置filter 来过滤,但是Filter 可能会被拒绝因为类型太多了,需要先理解他们的功能。

    这一部分,需要对系统代码有一定的了解,需要比较好的java 知识,先掠过去。 
    考一段实例代码: 
FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE);
SingleColumnValueFilter filter1 = new SingleColumnValueFilter(
    cf,
    column,
    CompareOp.EQUAL,
    Bytes.toBytes("my value")
    );
list.add(filter1);
SingleColumnValueFilter filter2 = new SingleColumnValueFilter(
    cf,
    column,
    CompareOp.EQUAL,
    Bytes.toBytes("my other value")
    );
list.add(filter2);
scan.setFilter(list);

2.列值的filter 

    SingleColumnValueFilter  用来过滤列值(column value) 操作CompareOp.EQuAL 相等  CompareOp.NOT_EQUAL 不相等,CompareOpGREATER 范围

    一段示例代码: 
SingleColumnValueFilter filter = new SingleColumnValueFilter(
    cf,
    column,
    CompareOp.EQUAL,
    Bytes.toBytes("my value")
    );
scan.setFilter(filter);


3.正则表达式支持: 

SubstringComparator comp = new SubstringComparator("y val");   // looking for 'my value'
SingleColumnValueFilter filter = new SingleColumnValueFilter(
    cf,
    column,
    CompareOp.EQUAL,
    comp
    );
scan.setFilter(filter);

关于filter 这部分,参考https://hbase.apache.org/book.html#architecture 9.4. 节内容。 

五. Master 
    
    HMaster 是一台管理服务器,负责监控所有的regionserver 实例,以及提供修改.META.的接口,在生产环境中,hmaster 一般部署在namenode 上。 


1.启动时行为: 

    如果运行在多主的环境中,如果主要的master 故障,或则无法与ZOOKEEPer 的联系,备机会接替。

2.运行时故障:
    如果在集群运行期间,hmaster下线,因为client 都直接与regionserver 联系,所以集群可以继续运行一小段时间,但是因为hmaster 控制了核心功能,所以如果master 下线,应尽快重启master 。 

3.接口(Interface) 
    HMasterInterface 提供 基于metadata的接口

    Table (createTable modifyTable removeTable enable。。。。) 
    ColumnFamily (addColumn modifyColumn removeClolumn)
    Region (move assign unassign)

4.进程:
    hmaster 运行着几个后台进程。
    1) LoadBalance 进程 负载负载均衡。

    2) CatalogJanitor 检查并清理.META. 表。 


六. RegionServer 
    regionserver 为region 提供管理服务 在生产部署上,regionserver 运行在datanode 上。 

1.接口   提供数据的访问,以及region 的管理
    Data (get put delete next 。。。) 

    Region (splitRegion compactRegion。。。)

2.进程 regionserver 运行几个后台进程。
    
    1) CompactSplitThread  
        提供split 以及小型 压缩/整理工作

    2) MajorCompactionChecker 
        提供大型压缩/整理工作
    3)MemStoreFlusher 
        周期性的刷新内存的数据导磁盘
    4) LogRoller 
        周期性检查regionserver 的HLOG 

3.Coprocessors 
    因为java 不能多继承,所以很多复杂性的工作,导致java代码的编写变的很复杂,而hbase 的不同的功能点,都在不同的模块里,这就导致,一个代码同事完成几个功能时,使编码工作很复杂,于是参照goole 论文里的技术,开发了Coprocessors 模块。 详细信息参照: https://blogs.apache.org/hbase/entry/coprocessor_introduction

4.Block Cache 
    1)设计: block cache 是lru CACHE 有3个级别的cache 策略
        a) 单次访问策略: 一个数据块第一次从hdfs载入cache
        b) 多次访问侧路: 一个数据块在a)策略基础上,被多次访问。
        c) In-memory策略: 
    关于cache 策略: https://hbase.apache.org/xref/org/apache/hadoop/hbase/io/hfile/LruBlockCache.html

    2) USAGE 
        Block cache 默认对所有的用户表起作用,也就是所有的数据读取操作,都会经过block cache 的缓存。适合于大多数情况,为了特定的性能提升关闭cache 也是可以的。cache 的设置取决于工作集(WSS working_set_size) 大小。
block cache 的大小的估算公式: 
    number of region servers * heap size * hfile.block.cache.size * 0.85
    默认的block cache的尺寸是heapsize 的25% 几个实例:
    一个region server 默认的heapsize 1g 那么block cache 大约为217Mb 
    20个 region serer 默认的heapsize 8g  那么blocK CACHE  大约为34Gb 
    100个region  server 默认的heapsize 24g block cache 大约1TB 

    .META. -ROOT-  字典表默认为In-memory 策略。 
    HFILE 的索引 keys, Bloom filter 也会用到block cache 。 

     使用原则: 应该了解一下自己要访问的数据集的大小,
    对于随机访问的,不建议使用block cache ,因为大数据量的随机访问,会导致block cache 别占满,而后,因为lru策略会导致jvm 更多的垃圾回收,带来性能损失。 
    对于MAPPING TABLE : A在mapreduce任务中,因为每个记录仅被读取一次,所以没有必要使用block cache 。 



5.WAL (hbase 日志) 
    
    1)    每个regionserver 会把对数据的修改写进wal 日志,然后写memstore 然后才写到store 物理文件中。HLOG 是wallog的实现,每个regionserver 一个实例。 

    2) wal flush 目前没有文档记载。
    3) wal splitting 
        没有详细文档记载

七.Regions
    
    regions 是高可用,与可分布式表的基本元素,每个列族(column family)一个store (对应我们理解上的一个数据文件) 
       (HBase table)
    Region       (Regions for the table)
         Store          (Store per ColumnFamily for each Region for the table)
              MemStore           (MemStore for each Store for each Region for the table)
              StoreFile          (StoreFiles for each Store for each Region for the table)
                    Block             (Blocks within a StoreFile within a Store for each Region for the table)
 

    hbase 在HDFS 上的存储结构: 
/hbase
     /<Table>             (Tables in the cluster)
          /<Region>           (Regions for the table)
               /<ColumnFamiy>      (ColumnFamilies for the Region for the table)
                    /<StoreFile>        (StoreFiles for the ColumnFamily for the Regions for the table)
            

    WAL 日志在hdfs 里存储结构: 
/hbase
     /.logs
          /<RegionServer>    (RegionServers)
               /<HLog>           (WAL HLog files for the RegionServer)
            


1.Region Size 
    确定一个合适的region size 是个比较难的事情需要考虑几个情况: 

    1) hbase 通过region 在服务器间实现可扩展性,但是如果你有2个16gb的region 在一个20个节点的集群了,大约只会用到几台服务器,大部分服务器都是闲置的,浪费了资源。
    2) 另一方面,更过的region 数量,会让整个工作变慢,对于同样大小的数据,700个region 的性能要好于3000个region 的情况,
    3) regionsever 在内存封装上,1个region 跟多个region 是没有区别的。


2.Region-RegionServer-Assignment(region 在regionserver 的分配) 
    
    1) 启动过程
        a) master 调用AssignmentMenager 
        b) AssignmentManager 查看.META. 里已存在的region 的分配情况
        c)如果region 的assignment 还有效,就继续保持
        d) 如果这assignment 失效,LoadbalanceFactory 被调用重新分配这个region ,默认是在所有的regionserver间随机的分派的。 
        e) META. 信息随这个region 的重新指派而更新。

    2) failover 
        当一个regionserver失败时: 
        a) region 马上变得不可用
        b)hmaster 检测到regionserver失败
        c)region assignment 被认为失效,将启动重新分派的工作。 

    3) loadbalance 
        region 可以周期性通过LoadBalance 在regionserver建移动。 

3.region regionserver 本地化
    经过一段时间后,会达到region 本地化
    因为hdfs的复制是
    a)第一份写本地节点
    b) 第二份复制写同一个机柜的另一台机器
    3) 第三份复制写另一个机柜
    这样通过一段时间,hbase 就达到本地化了,在regionserver failover 时候,数据会从新分配,region 可能会被指派到不同的节点上,但是经过一段时间,通过上面的过程,还是会实现本地化。

4.Region splits 
    应该禁止让hbase 自己执行region split ,控制参数为hbase.hregion.max.filesize  禁止自动split 时,可以设置这个值为100gb 左右,一旦忘记执行手工split 100gb的数据文件通过compation 的时间在大约1小时左右。 

    0.94版面以后,可以用手工的split 策略覆盖全局的策略
    region 的split 策略,可以全局设置,也可以单个表设置。 

5在线Region merge 

master 跟regionserver 都可以执行merge 操作,
示例操作:
    $ hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME'
          hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME', true
          

6.store 
    一个store 包括一个memstore 和0个或多个store file (HFILE) 每个store 对应于一个column family 

    1) memstore  保存了内存里的修改影像,数据的修改在memstore里完成然后请求flush 将数据写入store file 。
    2) store file 就是我们常规意义上存储在hbase里的数据文件了。 
        a) HFILE 的格式: 
            参考信息:https://hbase.apache.org/book.html#hfilev2

        b) hfile 工具: 
             $ ${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.io.hfile.HFile -v -f hdfs://10.81.47.41:8020/hbase/TEST/1418428042/DSMP/4759508618286845475  查看文集内容

        c)storefile in hdfs  参考前面的hbase 在hdfs上存储格式。

    3) 数据块(BLOCK)
        storefile 由block 组成,block的大小可以在columfamily 里设置
        数据压缩(compact) 就是在数据块级别上进行。 

    4) keyvalue 对
        keyvalue 的存储格式: 
            a)keylength
            b) valuelength
            c) key
            d) value
        key 的结构: 
            
            a) rowlength 
            b) row (i.e. the rowkey) 
            c) columnfamilylenth
            d)columnfamily
            e)columnqualifier
            f)timestamp
            g)keytype (i.e.  Put Delete DeleteColumn DeleteFamily) 
        一个示例数据: 
        Put #1: rowkey=row1, cf:attr1=value1
        Put #2: rowkey=row1, cf:attr2=value2

        我们想hbase 写了两行数据,结构分拆
        
        for  PUT 1: 
        rowlength ------------> 4
        row -----------------> row1
        columnfamilylength ---> 2
        columnfamily --------> cf
        columnqualifier ------> attr1
        timestamp -----------> server time of Put
        keytype -------------> Put

for  PUT 2: 

        rowlength ------------> 4
        row -----------------> row1
        columnfamilylength ---> 2
        columnfamily --------> cf
        columnqualifier ------> attr2
        timestamp -----------> server time of Put
        keytype -------------> Put

        
    

    5) 关于Compaction 
        这部分不太好说,参考文档:
        https://hbase.apache.org/book.html#architecture 9.7.6.5 小节。

八. 批量导入(BULK LOAD) 
    这个属于工具性,一个主要的过程,先根据hbase 的文件格式,
    把要导入hbase 的数据写成hbase 的文件格式,然后在通过工具把这些文件注册到.META.中。 

    这个部分没有实际操作过,参考下文档吧:https://hbase.apache.org/book.html#architecture 9.8 小节 。