Hbase 读取流程概念详解、hbase基本操作、大批量的插入与读取、带条件的读取实现

 

声明:以下知识全部来源于转载,可以通过网址查看原创。

 

HBase——数据读写寻址 

 

hbaseclient->zookeeper->ROOT表-META表(包含所有的用户空间region信息(列表),以及RegionServer的服务器地址。等 第一次读过来然后缓存到本地)->region->先从MemStore找数据,如果没有,再到StoreFile上读(为了读取的效率),storeFile是Hfile的实现,对Hfile做了1层封装 , 1个storeFile对应1个HFile (HFile:数据真正存储的地方,它基于BitTable的SSTable File和HADOOP的TFile,它以key-value 的格式存储数据。

ØZookeeper

Zookeeper中记录了-ROOT-表的location。

Ø-ROOT-

表包含.META.表所在的region列表,该表只会有一个Region;

Ø.META.

表包含所有的用户空间region列表,以及RegionServer的服务器地址。

Ø-ROOT-和.META.表结构是相同的:rowkey+info+history info

Øinfo里面包含三个Column:regioninfo, server, serverstartcode。

regioninfo就是Region的详细信息,包括StartKey, EndKey 以及每个Family的信息等等。

server存储的就是管理这个Region的RegionServer的地址。

 

其中一个region信息的构成

 

HBase中KeyValue是什么样的结构?
HBase中KeyValue并不是简单的KV数据对,而是一个具有复杂元素的结构体,其中Key由RowKey,ColumnFamily,Qualifier ,TimeStamp,KeyType等多部分组成,Value是一个简单的二进制数据。Key中元素KeyType表示该KeyValue的类型,取值分别为Put/Delete/Delete Column/Delete Family等。KeyValue可以表示为如下图所示:

 

https://blog.csdn.net/huyangshu87/article/details/51063376

https://blog.csdn.net/Java_Soldier/article/details/78786139

Region数

一般,region数如果没有事前使用hbase shell来明示定义的话,算上系统的region数,一般只有3个:

1. hbase:meta

2. hbase:namespace

3. userRegion

因为默认的region大小是10G,一般小型的环境下,数据量很难快速达到数据分裂的阈值。

明示的去指定的话,region数可以根据自己业务增加的趋势实现选定一个峰值,这样在加上设计一个优秀的rowkey,数据分布比较均衡,整个集群的性能才是最优的。

 

HBase:数据读写基本流程

https://blog.csdn.net/WYpersist/article/details/80115123

 

 

 

HBase数据写流程解析

 

https://www.cnblogs.com/163yun/p/9020608.html (Client写入 -> 存入MemStore

Client写入 -> 存入MemStore,一直到MemStore满 -> Flush成一个StoreFile,直至增长到一定阈值 -> 出发Compact合并操作 -> 多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除 -> 当StoreFiles Compact后,逐步形成越来越大的StoreFile -> 单个StoreFile大小超过一定阈值后,触发Split操作,把当前Region Split成2个Region,Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer 上,使得原先1个Region的压力得以分流到2个Region上由此过程可知,HBase只是增加数据,有所得更新和删除操作,都是在Compact阶 段做的,所以,用户写操作只需要进入到内存即可立即返回,从而保证I/O高性能。

 


HBase数据读取流程解析

https://blog.csdn.net/lw_ghy/article/details/60778843

 

Hbase 批量读取的几种方式

 

1. 给定多个rowkey,HBase根据Rowkey批量查询数据JAVA API(一次查多条,返回多个记录)

https://blog.csdn.net/a867565870/article/details/78683839

 

2.hbase高性能读取数据  --自己封装多线程批量式解决办法

https://blog.csdn.net/zbc1090549839/article/details/50487336/

 

3【甘道夫】HBase基本数据操作详解【完整版,绝对精品】

从1可以知道get既可以获取一行也可以获取多行数据

从scan可以获取表中所有行,也可以获取部分行,可以设置筛选条件

https://blog.csdn.net/u010967382/article/details/37878701

  其中: 很nice 的一点  就是可以获取带条件筛选的多行Scan,这有利于做增量导出。

获取多行Scan

Scan对象可以返回满足给定条件的多行数据。 如果希望获取所有的行,直接初始化一个Scan对象即可。 如果希望限制扫描的行范围,可以使用以下方法:

  • 如果希望获取指定列族的所有列,可使用 addFamily 方法来添加所有希望获取的列族 
  • 如果希望获取指定列,使用 addColumn 方法来添加所有列
  • 通过 setTimeRange 方法设定获取列的时间范围
  • 通过 setTimestamp 方法指定具体的时间戳,只返回该时间戳的数据
  • 通过 setMaxVersions 方法设定最大返回的版本数
  • 通过 setBatch 方法设定返回数据的最大行数
  • 通过 setFilter 方法为Scan对象添加过滤器,过滤器详解请参见:http://blog.csdn.net/u010967382/article/details/37653177
  • Scan的结果数据是可以缓存在内存中的,可以通过 getCaching ()方法来查看当前设定的缓存条数,也可以通过 setCaching (int caching)来设定缓存在内存中的行数,缓存得越多,以后查询结果越快,同时也消耗更多内存。此外, 通过setCacheBlocks 方法设置是否缓存Scan的结果数据块,默认为true
  • 我们可以通过 setMaxResultSize(long)方法来设定Scan返回的结果行数。

下面是官网文档中的一个入门示例:假设表有几行键值为 "row1", "row2", "row3",还有一些行有键值 "abc1", "abc2", 和 "abc3",目标是返回"row"打头的行:

 

HTable htable = ...      // instantiate HTable

Scan scan = new Scan();

scan.addColumn(Bytes.toBytes("cf"),Bytes.toBytes("attr"));

scan.setStartRow( Bytes.toBytes("row"));                   // start key is inclusive

scan.setStopRow( Bytes.toBytes("row" +  (char)0));  // stop key is exclusive

ResultScanner rs = htable.getScanner(scan);

try {

for (Result r = rs.next(); r != null; r = rs.next()) {

// process result...

} finally {

rs.close(); // always close the ResultScanner!

}

 

(4) 结合过滤器,获取所有age在25到30之间的行

目前的数据:

hbase(main):049:0> scan 'rd_ns:itable'

ROW                                           COLUMN+CELL

100001                                       column=info:address, timestamp=1405417403438, value=anywhere

100001                                       column=info:age, timestamp=1405417403438, value=24

100001                                       column=info:name, timestamp=1405417403438, value=zhangtao

100002                                       column=info:address, timestamp=1405417426693, value=shangdi

100002                                       column=info:age, timestamp=1405417426693, value=28

100002                                       column=info:name, timestamp=1405417426693, value=shichao

100003                                       column=info:address, timestamp=1405494141522, value=huilongguan

100003                                       column=info:age, timestamp=1405494999631, value=29

100003                                       column=info:name, timestamp=1405494141522, value=liyang

3 row(s) in 0.0240 seconds

代码:

        Configuration conf = HBaseConfiguration. create ();

        HTable table =  new  HTable(conf,  "rd_ns:itable" );

        FilterList filterList =  new  FilterList(FilterList.Operator. MUST_PASS_ALL );  

        SingleColumnValueFilter filter1 =  new  SingleColumnValueFilter(

                Bytes. toBytes ( "info" ),

                Bytes. toBytes ( "age" ),

                CompareOp. GREATER_OR_EQUAL ,

                Bytes. toBytes ( "25" )

                );

        SingleColumnValueFilter filter2 =  new  SingleColumnValueFilter(

                Bytes. toBytes ( "info" ),

                Bytes. toBytes ( "age" ),

                CompareOp. LESS_OR_EQUAL ,

                Bytes. toBytes ( "30" )

                );

        filterList.addFilter(filter1);

        filterList.addFilter(filter2);

        

        Scan scan =  new  Scan();

        scan.setFilter(filterList);

        

        ResultScanner rs = table.getScanner(scan);

         for  (Result r : rs) {

             for  (Cell cell : r.rawCells()) {

                System. out .println(

                         "Rowkey : " +Bytes. toString (r.getRow())+

                         "   Familiy:Quilifier : " +Bytes. toString (CellUtil. cloneQualifier(cell))+

                         "   Value : " +Bytes. toString (CellUtil. cloneValue (cell))+

                         "   Time : " +cell.getTimestamp()

                        );

            }

        }

 

        table.close();

代码输出:

Rowkey : 100002   Familiy:Quilifier : address   Value : shangdi   Time : 1405417426693

Rowkey : 100002   Familiy:Quilifier : age   Value :  28    Time : 1405417426693

Rowkey : 100002   Familiy:Quilifier : name   Value : shichao   Time : 1405417426693

Rowkey : 100003   Familiy:Quilifier : address   Value : huilongguan   Time : 1405494141522

Rowkey : 100003   Familiy:Quilifier : age   Value :  29    Time : 1405494999631

Rowkey : 100003   Familiy:Quilifier : name   Value : liyang   Time : 1405494141522

注意:

  1. HBase对列族、列名大小写敏感 
  2. 关于过滤器请参见原作者的另外一篇博客:http://blog.csdn.net/u010967382/article/details/37653177

 

 

Hbase容错和恢复

HLogFile

  HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是“写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number

  HLog Sequece File的Value是HBase的KeyValue对象,即对应HFile中的KeyValue.

该机制用于数据的容错和恢复:

  每个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中(HLog文件格式见后续),HLog文件定期会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复

HBase容错性
Master容错:Zookeeper重新选择一个新的Master
*无Master过程中,数据读取仍照常进行;
*无master过程中,region切分、负载均衡等无法进行;
RegionServer容错:定时向Zookeeper汇报心跳,如果一旦时间内未出现心跳,Master将该RegionServer上的Region重新分配到其他RegionServer上,失效服务器上“预写”日志由主服务器进行分割并派送给新的RegionServer
Zookeeper容错:Zookeeper是一个可靠地服务,一般配置3或5个Zookeeper实例

HBase写入的各种方式总结汇总(代码)

https://www.cnblogs.com/teagnes/p/6446526.html

http://ganliang13.iteye.com/blog/1860658

 

关于HBase的絮絮叨叨(持续更新)

https://www.cnblogs.com/teagnes/p/5456797.html

hbase shell 命令

https://www.cnblogs.com/shadowalker/p/7350484.html