HBase学习笔记-高级(一)

时间:2023-01-08 18:02:54

HBase
1. hbase.id记录了集群的唯一标识;hbase.version记录了文件格式的版本号
2. split和.corrupt目录在日志分裂过程中使用,以便保存一些中间结果和损坏的日志
在表目录下,为该表的每一个region单独创建一个目录,目录的名字为region name的MD5哈希值
3. 二级索引方案:a.Coprocessor b.由客户端发起对于主表和索引表的Put、Delete操作的双重操作

Split和Conpact优化

 

快速写入

1.写入前 预分Region

2.数据写入HFile,然后使用bulkload加载

3.使用 HFileOutputFormat 代替 TableOutputFormat

 

统计数据量

$hbase_home/bin/hbase org.apache.hadoop.hbase.mapreduce.RowCounter tableName


数据迁移
先Dump data到文本文件->importtsv(HBase bulk load tool生成HFile,then completebulkload 分配给Region)
注意Region预分;Region splitting algorithm
[======
hbase 0.98
/usr/hbase/bin/hbase org.apache.hadoop.hbase.mapreduce.ImportTsv -Dimporttsv.columns=HBASE_ROW_KEY,t:v01,t:v02,t:v03,t:v04,t:v05,t:v06,t:v07,t:v08,t:v09,t:v10,t:v11,t:v12,t:v13,t:v14,t:v15,t:v16,t:v17,t:v18,t:v19,t:v20,t:v21,t:v21,t:v22,t:v23,t:v24 -Dimporttsv.bulk.output=hdfs://10.1.1.30/user/output/1011 hly_temp /user/input/1011/
http://www.ithao123.cn/content-8576.html
https://github.com/uprush/hac-book/blob/master/2-data-migration/script/to_tsv_hly.py
http://www.aboutyun.com/thread-9497-1-1.html
======]

#HBase使用Map/Reduce计数
${HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.mapreduce.RowCounter tableName
#When running RowCounter against large datasets, we recommend you to tune the scanner's caching setting on your client
<property>
<name>hbase.client.scanner.caching</name>
<value>1000</value>
</property>
#This makes HBase fetch 1000 rows for each next call on the scanner. By default, HBase fetches 1 row per next call. Setting it to a higher value increases the scanner's speed, but consumes more memory.

#he deleteall command deletes all the cells in a given row.

#HBase shell时间格式化显示
hbase(main):007:0> import java.util.Date
hbase(main):008:0> Date.new(1450248331542).toString()

HLog:
#查看HLog
${HBASE_HOME}/bin/hbase hlog /hbase/WALs/node16,60020,1449622888458/node16%2C60020%2C1449622888458.1449822319549 -w AQW000617050101
HFile:
#查看HFile
${HBASE_HOME}/bin/hbase hfile -p -f /hbase/data/default/hly_temp/1e62c3178e02f20ed4366c8e9d5f7774/t/f9c993d0620c47ef8f8e8ab36912c5af

#一致性检查和修复
${HBASE_HOME}/bin/hbase hbck
${HBASE_HOME}/bin/hbase hbck -fix

#复杂查询Hive
HQL is translated into a MapReduce job by Hive

#备份和还原
1> Backing it up with a full cluster shutdown
distcp(支持同一个集群和不同集群备份;同时备份Region starting key)
备份:e.g. /usr/lib/hdh/hadoop/bin/hadoop distcp hdfs://node16:8020/hbase hdfs://node16:8020/backup
还原:直接启动HBase即可
2> Backing it up on a live cluster
1.CopyTable(可以指定开始时间/结束时间;支持增量备份;可以复制到其他集群)
#{HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.mapreduce.CopyTable --new.name=<dest_table> <src_table>
2.export(可以指定开始时间/结束时间;支持增量备份;支持压缩;不能跨集群,可以配合distcp做备份)
备份:
#{HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.mapreduce.Export -D mapred.output.compress=true -D mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec -D mapred.output.compression.type=BLOCK hly_temp /backup/export/20151217
还原:(创建表,预分好Region;Backing up region starting keys)
#{HBASE_HOME}/bin/hbase org.apache.hadoop.hbase.mapreduce.Import hly_temp /backup/export/20151217

#back up and restore NameNode metadata
1.Use NFS mount
2.multiply NameNode
#TODO

#backup region starting keys
Shell
#TODO

#Cluster replication
add_peer ... start_replication ...
#TODO

监控:
1.统计磁盘文件容量占用
总占用:
[root@node16 ~]# ${HADOOP_HOME}/bin/hadoop fs -du -s -h /hbase
表占用:
root@node16 ~]# ${HADOOP_HOME}/bin/hadoop fs -du -s -h /hbase/data/default/HIK_SMART_METADATA
2.监控系统
Ganglia; OpenTSDB; Nagios(check Process and logs)
3.Hot spot region issue
A solution for the hot write region issue is to find out the hot regions, split them manually, and then distribute the split regions to other region servers.
An HBase edit will firstly be written to the region server's Write-ahead-Log (WAL). The actual update to the table data occurs once the WAL is successfully appended
#How to find
分析WALs,然后计算每个Region的edits(WriteDiagnosis.java)

 

二级索引

前提

在HBase中,表格的Rowkey按照字典排序,Region按照RowKey设置split point进行shard,通过这种方式实现的全局、分布式索引,成为了其成功的最大的砝码。图1显示了HBase表格的Rowkey切分与Region的部署关系图。

HBase学习笔记-高级(一)

图1: HBase Rowkey-Region 关系图


然而,随着在HBase系统上应用的驱动,人们发现Global-Rowkey-Indexing不再满足应用的需求。单一的通过Rowkey检索数据的方式,不再满足更多应用的需求,人们希望像SQL一样检索数据,select * from table where col=val。可是,HBase之前的定位是大表的存储,要进行这样的查询,往往是要通过类似Hive、Pig等系统进行全表的MapReduce计算,这种方式既浪费了机器的计算资源,又因高延迟使得应用黯然失色。于是,在业界和社区,针对HBase Secondary Indexing的方案,成为HBase新版本(0.96)呼声最高的一项Feature。

 

粗略分析了当前的技术,大概的方案可以总结为这样两类:

1、使用HBase的coprocessor。CoProcessor相当于HBase的Observer+hook,目前支持MasterObserver、RegionObserver和WALObserver,基本上对于HBase Table的管理、数据的Put、Delete、Get等操作都可以找到对应的pre***和post***。这样如果需要对于某一项Column建立Secondary Indexing,就可以在Put、Delete的时候,将其信息更新到另外一张索引表中。如图二所示,对于Indexing里面的value值是否存储的问题,可以根据需要进行控制,如果value的空间开销不大,逆向的检索又比较频繁,可以直接存储在Indexing Table中,反之则避免这种情况。

HBase学习笔记-高级(一)

图2 使用HBase Coprocessor实现Secondary Indexing

2、由客户端发起对于主表和索引表的Put、Delete操作的双重操作。源自:http://hadoop-hbase.blogspot.com/2012/10/musings-on-secondary-indexes.html 【墙外】

它具体的做法总结起来有:

  • 设置主表的TTL(Time To Live)比索引表小一点,让其略早一点消亡。
  • 不要在IndexingTable存储Value值,即删除如图2所示的val列。
  • Put操作时,对于操作的主表的所有列,使用同一的Local TimeStamp的值,更新到Indexing Table,然后使用该TimeStamp插入主表数据。
  • Delete操作时,首先操作主表的数据,然后再去更新Indexing Table的数据。

虽然在这种方案里无法保证原子性和一致性,但是通过TimeStamp的设置,No Locks和 No Server-side codes,使其在二级索引上有着较大的优势。至于中间出错的环节,我们看看是否可以容忍:

1)Put索引表成功,Put主表失败。由于Indexing Table不存储val值,仍需要跳转到Main Table,所以这样的错误相当于拿一个Stale index去访问对应Rowkey吧了,对结果正确性没有影响。

2)Delete主表成功,Delete索引表失败。都是索引表的内容>=主表的内容而已,而实际返回值需要通过主表进行。

生产环境下,什么样的方法实用性更强?

就这个问题,根据个人当前对于生产环境下HBase集群的经验,综合上面两种方式的优劣,可以通过这样的方式设计。

 

1、主表服务在线业务,它的性能需要保证。使用coprocessor和客户端的封装也好,都会影响其性能,所以在正常情况下,直接操作都不太合适。如果想使用方案二,我倒是感觉,可以调整Indexing Table的操作方式,去除保证其安全性的内容,比如可以关闭写HLOG,这样会进一步减低其操作的延迟。

2、离线更新索引表。在真正需要二级索引的场景内,其时效性要求往往不高。可以将索引实时更新到Redis等KV系统中,定时从KV更新索引到Hbase的Indexing Table中。PS:Redis里面有DB设置的概念,可以按照时间段进行隔离,这样某段时间内的数据会更新到Redis上,保证Redis导入MapReduce之后仍然可以进行update操作。

引用:http://blog.sina.com.cn/s/blog_4a1f59bf01018apd.html

 

华为Hbase二级索引(Secondary Index)细节分析

http://www.dengchuanhua.com/167.html

https://github.com/Huawei-Hadoop/hindex

 

其他链接:

http://www.cnblogs.com/MOBIN/p/5579088.html

 

hbase二级索引解决方案

HBase的一级索引就是rowkey,我们只能通过rowkey进行检索。如果我们相对hbase里面列族的列列进行一些组合查询,就需要采用HBase的二级索引方案来进行多条件的查询。 
常见的二级索引方案有以下几种: 
1.MapReduce方案 
2.ITHBASE方案 
3.IHBASE方案 
4.Coprocessor方案 
5.Solr+hbase方案

MapReduce方案

IndexBuilder:利用MR的方式构建Index 
优点:并发批量构建Index 
缺点:不能实时构建Index
举例: 
原表:
row  1      f1:name  zhangsan
row  2      f1:name  lisi
row  3      f1:name  wangwu
 
索引表:
row     zhangsan    f1: id   1
row     lisi        f1: id   2
row     wangwu      f1: id   3
 
ITHBASE方案
优点:ITHBase(Indexed Transactional HBase)是HBase的一个事物型的带索引的扩展。 
缺点:需要重构hbase,几年没有更新。 
http://github.com/hbase-trx/hbase-transactional-tableindexed
IHBASE方案
**优点:**IHBase(Indexed HBase)是HBase的一个扩展,用干支持更快的扫描。 
缺点:需要重构hbase。 
原理:在Memstore满了以后刷磁盘时,IHBase会进行拦截请求,并为这个memstore的数据构建索引,索引另一个CF的方式存储在表内。scan的时候,IHBase会结合索引列中的标记,来加速scan。 
http://github.com/ykulbak/ihbase
Coprocessor方案
HIndex–来自华为的HBase二级索引 
http://github.com/Huawei-Hadoop/hindex
The solution is 100% Java, compatible with Apache HBase 0.94.8, and is open sourced under ASL.
Following capabilities are supported currently. 
1.multiple indexes on table, 
2.multi column index, 
3.index based on part of a column value, 
4.equals and range condition scans using index, and 
5.bulk loading data to indexed table (Indexing done with bulk load).
Solr+hbase方案
Solr是一个独立的企业级搜索应用服务器,它对并提供类似干Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。 
Solr是一个高性能,采用Java5开发,基干Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能节理界面,是一款非常优秀的全文搜索引擎。
HBase无可置疑拥有其优势,但其本身只对rowkey支持毫秒级的快速检索,对于多字段的组合查询却无能为力。 
基于Solr的HBase多条件查询原理很简单,将HBase表中涉及条件过滤的字段和rowkey在Solr中建立索引,通过Solr的多条件查询快速获得符合过滤条件的rowkey值,拿到这些rowkey之后在HBASE中通过指定rowkey进行查询。 
 
hbase中二级索引的实现--ihbase
一般来说,对数据库建立索引,往往需要单独的数据结构来存储索引的数据.在为hbase建立索引时,可以另外建立一张索引表,查询时先查询索引表,然后用查询结果查询数据表. 
HBase学习笔记-高级(一) 
这个图左边表示索引表,右边是数据表. 
但是对于hbase这种分布式的数据库来说,最大的问题是解决索引表和数据表的本地性问题,hbase很容易就因为负载均衡,表split等原因把索引表和数据表的数据分布到不同的region server上,比如下图中,数据表和索引表就出现在了不同的region server上 
HBase学习笔记-高级(一) 

所以为了解决这个问题, ihbase项目应运而生,它的主要思想是在region级别建立索引而不是在表级别. 
它的解决方案是用IdxRegion代替了常规的region实现,在flush的时候为region建立索引
hbase在内存中为region维护了一份索引,在scan的时候首先在索引中查找数据,按顺序提供rowkey,而在常规的scan时,能利用上一步的rowkey来move forward,有目的的进行seek. 
IdxRegionScanner在进行scan的时候,用索引来构造keyProvider,然后执行next方法时,用keyProvider提供的rowkey进行定位 
 
使用协处理器插入二级索引数据

public class HbaseCoprocessor extends BaseRegionObserver {

public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e,
final Put put, final WALEdit edit, final boolean writeToWAL)
throws IOException {
// set configuration
Configuration conf = new Configuration();
// need conf.set...
String colName = "columnName";
HTable table = new HTable(conf, "indexTableName");
List<Cell> kv = put.get("familyName".getBytes(), colName.getBytes());
Iterator<Cell> kvItor = kv.iterator();
while (kvItor.hasNext()) {
Cell tmp = kvItor.next();
Put indexPut = new Put(tmp.getValue());
indexPut.add("familyName".getBytes(), "columnName".getBytes(),
tmp.getRow());
table.put(indexPut);
}
table.close();
}

}

根据自己的实际情况修改,然后打包test.jar,放到hdfs文件系统中。

 

要使jar包生效,需要做以下配置(二者选一)

单表配置
进入hbase shell,执行如下命令:
alter 'LogTable',METHOD=>'table_att','coprocessor'=>'hdfs:///test.jar|www.aboutyun.com.hbase.HbaseCoprocessor|1001'

 

全局配置
#修改hbase-site.xml文件
#为所有table加载了一个cp class,可以用”,”分割加载多个class
<property>
<name>hbase.coprocessor.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>


问题排查:
1.ps: This tool is used to find the top processes that occupied large amounts of memory. The following command sorts the processes by memory usage, in descending order
e.g. ps auxk -rss | less
2.ClusterSSH(+ top)
3.jmap: This tool prints the Java heap summary. In order to print the aforementioned HRegionServer process' Java heap summary, use the following command:
$JAVA_HOME/bin/jmap -heap 1812
4.jstat: This is the Java Virtual Machine statistics monitoring tool. Run the following command to show the summary of the garbage collection statistics of a HRegionServer process:
$jstat -gcutil 1812(pid) 1000(intervals)
5.Problem(Too many open files)
vi /etc/security/limits.conf vi /etc/pam.d/login ulimit -n(confirm)
#the current open file number of the hadoop user
lsof -uhadoop | wc -l

 

 

http://hbase.apache.org/apidocs/index.html
apache mirror: http://repo2.maven.org/maven2/

学习:
http://blog.csdn.net/huoyunshen88/article/details/38563915
http://www.rigongyizu.com/
http://blog.sina.com.cn/s/blog_4a1f59bf010197ct.html
http://hbase.apache.org/mail-lists.html