Hadoop详解——HBASE原理HBASE的集群安装常用命令和Java接口

Posted LIUXUN1993728

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hadoop详解——HBASE原理HBASE的集群安装常用命令和Java接口相关的知识,希望对你有一定的参考价值。

HBASE简介

HBASE是bigtable的开源山寨版本。是建立在HDFS基础之上,提供高可靠性、高性能、列存储、可伸缩、实时读写的数据库系统。 它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的range来检索数据,仅支持单行事务(可通过hive支持来实现多表join)等复杂操作。主要用来存储非结构化和半结构化的松散数据。 与Hadoop一样,HBASE目标主要依靠横向扩展,通过不断增加廉价的商用服务器,来增加计算和存储能力。 HBASE中的表一般有以下特点: ① 大:一个表可以有上亿行,上百万列。 ② 面向列:面向列(族)的存储和权限控制,列族独立检索。 ③ 稀疏:对于空(null)的列,并不占用存储空间,因此表可以设计的非常稀疏。 如下图所示是HBASE在Hadoop Ecosystem(大数据生态系统)中的位置
注意:上图是Hadoop1.0的生态系统图,在Hadoop2.0中 在HDFS层上多了一层YARN。

HBASE表的逻辑视图

Hbase以表的形式存储数据。表中有行和列组成。列划分为若干个列族(row family)
Row key 与nosql数据库一样,row key 是用来检索记录的主键。访问habse table中的行,只有三种方式: ① 通过单个row key访问 ② 通过row key的range ③ 全表扫描 Row key行健可以是任意字符串(最大长度是64KB,实际应用中长度一般10-100bytes) 在HBASE内部,row key保存为字节数组。 存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储在一起(位置相关性) 注意: 字典排序对int排序的结果是 1、10、100,11、12、13、14、15、16、17、18、19、2、20、21......9、91、92、93、94、95。要保持整形的自然顺序。行健必须使用0作为左补充。 行的一次读写是原子操作(不论一次读写多少列)。这个设计决策能够使用户很容易的理解程序在同一个行进行并发更新时的行为。 列族 HBASE表中的每个列,都归属与某个列族。列族是表的schema的一部分(而列不是),必须在使用表之前定义。列名都以列族作为前缀。例如courses:history,courses:math都属于courses这个列族。访问控制、磁盘和和内存的使用统计都是在列族这个层面进行的。实际应用中,列族上的控制权限能帮助我们管理不同类型的应用:我们允许一些应用可以添加新的基本数据、一些应用可以读取基本数据并创建继承的列族、一些应用只允许浏览数据(甚至可能因为隐私的原因不能浏览所有的数据)。 时间戳 HBASE中通过row key和columns确定的为一个存储单元称为cell。每个cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是64位整型数据。时间戳可以由HBASE(在数据写入时自动)赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户端显式的赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个cell中,不同版本的数据按照时间倒序排序,即最新的数据排列在最前面。 为了避免数据存在过多版本造成的管理(包括存储和索引)的负担,HBASE提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(比如近十天)。用户可以针对每个列族进行设置。 Cell 由于row key, column=<family>+<label>, version 唯一确定的单元。cell中的数据是没有类型的,全部是以字节码形式存储。

物理存储

① 已知,Table中的所有行都按照row key的字典排序。 ② Table在行的方向上被分割为多个HRegion
③ Region按照大小分割,每个表一开始只有一个Region,随着数据不断插入表,Region不断增大,当增大到一定阀值的时候,HRegion就会分成两个新的HRegion。当Table中的行数不断增多,就会有越来越多的HRegion。
④ HRegion是HBASE中分布式存储和负载均衡的最小单元,最小单元表示的是不同的HRegion可以分布在不同的HRegion Server上。但是一个HRegion是不会拆分到多个Server上的。
⑤HRegion虽然是分布式存储的最小单元,但不是物理存储的最小单元。 事实上,HRegion由一个或多个Store组成,每个Store保存一个columns family 即列族。 每个Store又由一个memStore和0至多个StoreFile组成。如下图所示: StoreFile以HFile的格式保存在HDFS上。
HFile的格式为:
Trailer部分的格式如下:
HFile分为六个部分:
Data Block 段–保存表中的数据,这部分可以被压缩
Meta Block 段 (可选的)–保存用户自定义的kv对,可以被压缩。
File Info 段–Hfile的元信息,不被压缩,用户也可以在这一部分添加自己的元信息。
Data Block Index 段–Data Block的索引。每条索引的key是被索引的block的第一条记录的key。
Meta Block Index段 (可选的)–Meta Block的索引。
Trailer–这一段是定长的。保存了每一段的偏移量,读取一个HFile时,会首先 读取Trailer,Trailer保存了每个段的起始位置(段的Magic Number用来做安全check),然后,DataBlock Index会被读取到内存中,这样,当检索某个key时,不需要扫描整个HFile,而只需从内存中找到key所在的block,通过一次磁盘io将整个 block读取到内存中,再找到需要的key。DataBlock Index采用LRU机制淘汰。
HFile的Data Block,Meta Block通常采用压缩方式存储,压缩之后可以大大减少网络IO和磁盘IO,随之而来的开销当然是需要花费cpu进行压缩和解压缩。
目标Hfile的压缩支持两种方式:Gzip,Lzo。
 
HLog(WAL log)
WAL 意为Write ahead log(http://en.wikipedia.org/wiki/Write-ahead_logging),类似mysql中的binlog,用来 做灾难恢复只用,Hlog记录数据的所有变更,一旦数据修改,就可以从log中进行恢复。
每个Region Server维护一个Hlog,而不是每个Region一个。这样不同region(来自不同table)的日志会混在一起,这样做的目的是不断追加单个 文件相对于同时写多个文件而言,可以减少磁盘寻址次数,因此可以提高对table的写性能。带来的麻烦是,如果一台region server下线,为了恢复其上的region,需要将region server上的log进行拆分,然后分发到其它region server上进行恢复。
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,可参见上文描述。

HBASE系统架构




Client

包含访问HBASE的接口,Client维护者一些cache来加快对HBASE的访问,比如Region的位置信息。

ZooKeeper

① 保证任何时候,集群中只有一个master。 ② 存储所有Region的寻址入口。 ③ 实时监控Region Server的状态,将Region Server的上线和下线信息通知给HMaster。 ④ 存储HBASE的schema,包括有哪些Table,每个Table有哪些column family。

HMaster

① 为Region Server分配Region。 ② 负责Region Server的负载均衡。 ③ 发现失效的Region Server并将它上边的Region重新分配给别的Region Server。 ④ GFS上的垃圾文件回收。 ⑤ 处理schema的更新请求。

HRegion Server

① Region Server维护HMaster分配给它的HRegion,处理对这些HRegion的IO请求。 ② Region Server负责切分在运行过程中变得过大的HRegion。 client访问hbase上数据的过程并不需要master参与(寻址访问zookeeper和region server,数据读写访问regione server),master仅仅维护者table和region的元数据信息,负载很低。

HBASE中特殊的表

HBASE中有两张特殊的表,-ROOT-和.META. -ROOT-  :记录了.META. 表的Region信息,-ROOT-只有一个Region信息。 .META.  :记录了用户创建表的Region信息,.META.可以有多个Region。 ZooKeeper中记录了-ROOT-表的location位置信息
Client访问用户数据之前需要首先访问ZooKeeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据的位置去访问。

HBASE伪分布式单节点搭建

参考文档地址:http://hbase.apache.org/book.html#quickstart
首先下载HBASE安装包 下载地址:http://archive.apache.org/dist/hbase/hbase-0.96.2/

解压到/cloud下  cloud是我在系统根目录下新建的文件夹
tar -zxvf hbase-0.96.2-hadoop2-bin.tar.gz  -C /cloud/
配置步骤如下:
(1) 首先配置hbase-env.sh
编辑$HBASE_HOME/conf/hbase-env.sh 修改内容如下
 export JAVA_HOME=/usr/java/jdk1.8.0_144 
(2) 配置hbase-site.sh
编辑$HBASE_HOME/conf/hbase-site.sh 修改内容如下
<configuration>
        <property>
                <name>hbase.rootdir</name>
                <value>file:cloud/hbase-0.96.2-hadoop2/data</value>
        </property>
</configuration>
(3) 为了使用方便配置HBASE到环境变量 vim /etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_144
export HBASE_HOME=/cloud/hbase-0.96.2-hadoop2
export PATH=$PATH:$JAVA_HOME/bin:$HBASE_HOME/bin
保存退出 
使其生效 source /etc/profile
(4) 单节点的伪分布HBASE已经配置完成 ,cd到$HBASE_HOME/bin 查看使用命令 根据结果分析HBASE表结构
start-hbase.sh
使用jps命令查看Java进程,发现多了一个HMaster

使用测试

HBASE 命令的使用
1. 输入hbase 回车查看使用帮助提示的第一条,
Usage: hbase [<options>] <command> [<args>]
Options:
  --config DIR    Configuration direction to use. Default: ./conf
  --hosts HOSTS   Override the list in 'regionservers' file
Commands:
Some commands take arguments. Pass no args or -h for usage.
  shell           Run the HBase shell
……
输入命令:hbase shell 
进入到HBASE的命令界面:
2. HBASE shell的操作命令
命令的操作技巧:在hbase shell 回车后 会出现提示

在命令窗口输入exit 然后回车,就会退出shell命令界面
在命令窗口输入help 然后回车,就会出现帮助信息列表
连接后,输入help 回车出现的重要帮助信息大致如下:
'help "COMMAND"'
'help "COMMAND_GROUP"'
表示可以使用   help   ‘具体命令’  查看具体使用方法
也可以使用       help  ‘组名’    查看某一类的命令使用方法
在最下面打印相关的组有如下几种:
Group name: general
Group name: ddl
Group name: namespace
Group name: dml
……
输入help 'ddl' 查看与表结构相关的操作命令
相对简便的方式是 help 查看命令列表 然后使用 help+命令 查看使用方法
创建表
 create 'people',NAME => 'info',VERSIONS => 3,NAME => 'data',VERSIONS => 3
查看表的描述
describe 'people'
插入数据
 put 'people','rk0001','info:name','tom'
全表扫描
scan ‘people’

由列祖和列的名称来决定列
可多次插入扩展数据
put 'people','rk0001','info:gender','male'
put 'people','rk0001','info:age',25
put 'people','rk0001','data:desc','one teacher'
……多次插入后

可以使用help ‘scan’ 查看scan的使用方法
scan ‘people’, RAW => true, VERSIONS => 10 用于查询所有历史版本的数据

因为info列族的版本号设置为3 所以只会存储三个,至于多出来的只是标记了一下,在数据flush后就会清除

HBASE集群搭建

首先启动ZooKeeper集群 hadoop4 hadoop5 hadoop6
然后在hadoop1上配置HBASE 因为hadoop1配置了其它机器的ssh免登陆,配置好一台后可以通过scp复制到其它机器
在hadoop1上启动HDFS :start-dfs.sh 查看启动情况,启动成功后,开始安装HBASE
上传HBASE安装包
解压到/cloud下
 tar -zxvf /root/Desktop/hbase-0.96.2-hadoop2-bin.tar.gz -C /cloud/
cd /cloud/hbase-0.96.2-hadoop2/conf 目录下
配置如下:
1. 修改hbase-env.sh 修改如下配置内容
 export JAVA_HOME=/usr/java/jdk1.8.0_144
 export HBASE_MANAGES_ZK=false  #告诉HBASE不要使用自己的ZooKeeper进程
2.修改hbase-site.xml 
<configuration>
        <!-- 指定hbase在HDFS上存储的路径 -->
        <property>
                <name>hbase.rootdir</name>
                <value>hdfs://ns1/hbase</value>
        </property>
        <!-- 指定hbase是分布式的 -->
        <property>
                <name>hbase.cluster.distributed</name>
                <value>true</value>
        </property>
        <!-- 指定zk的地址,多个用“,”分割 -->
        <property>
                <name>hbase.zookeeper.quorum</name>
                <value>hadoop4:2181,hadoop5:2181,hadoop6:2181</value>
        </property>
</configuration>
3.修改regionservers
regionservers 是HBASE的小弟,HBASE的老大是HMaster。regionservers用来指定HBASE的小弟在哪些台主机上工作,默认是localhost。
hadoop3
hadoop4
hadoop5
hadoop6
4.HBASE在hadoop1上配置完成,将它拷贝到hadoop2  hadoop3  hadoop4  hadoop5  hadoop6
为了提高拷贝速度,可以将HBASE中的文档删除,再进行拷贝
rm  -rf  /cloud/hbase-0.96.2-hadoop2/docs/
scp -r /cloud/hbase-0.96.2-hadoop2/ root@hadoop2:/cloud/
scp -r /cloud/hbase-0.96.2-hadoop2/ root@hadoop3:/cloud/
scp -r /cloud/hbase-0.96.2-hadoop2/ root@hadoop4:/cloud/
scp -r /cloud/hbase-0.96.2-hadoop2/ root@hadoop5:/cloud/
scp -r /cloud/hbase-0.96.2-hadoop2/ root@hadoop6:/cloud/
5.分别将hadoop的hdfs-site.xml和core-site.xml 放到hbase/conf下
(因为在HBASE中虽然配置了hdfs://ns1/hbase 但是HBASE并不知道ns1与Hadoop中各个NameNode之间的关系)
在hadoop1上进入到cd /cloud/hadoop-2.7.4/etc/hadoop,然后进行拷贝操作
scp hdfs-site.xml core-site.xml root@hadoop1:/cloud/hbase-0.96.2-hadoop2/conf/
scp hdfs-site.xml core-site.xml root@hadoop2:/cloud/hbase-0.96.2-hadoop2/conf/
scp hdfs-site.xml core-site.xml root@hadoop3:/cloud/hbase-0.96.2-hadoop2/conf/
scp hdfs-site.xml core-site.xml root@hadoop4:/cloud/hbase-0.96.2-hadoop2/conf/
scp hdfs-site.xml core-site.xml root@hadoop5:/cloud/hbase-0.96.2-hadoop2/conf/
scp hdfs-site.xml core-site.xml root@hadoop6:/cloud/hbase-0.96.2-hadoop2/conf/
6 启动所有的hbase
分别启动zk:   ./zkServer.sh start
启动hadoop集群: start-dfs.sh
启动hbase,在主节点上运行:start-hbase.sh 
启动后在主节点上启动了HMaster,在hadoop3、hadoop4、hadoop5上均启动了HRegionServer
7.通过浏览器访问hbase管理页面
 http://192.168.0.10:60010 



具体的信息可以点击主页中zk_dump链接查看具体的信息

8.当前只有一台主节点,可靠性不高,可以在hadoop2上启动一个HMaster
hbase-daemon.sh start master
启动后查看 发现hadoop2中的HMaster变成了backup状态

验证其可靠性 kill -9  <pid:activeMaster> 杀死
发现hadoop2变成了active状态

HBASE Shell命令

进入hbase命令行
./hbase shell

显示hbase中的表
list

创建user表,包含info、data两个列族
create 'user', 'info1', 'data1'
create 'user', NAME => 'info', VERSIONS => '3'

向user表中插入信息,row key为rk0001,列族info中添加name列标示符,值为zhangsan
put 'user', 'rk0001', 'info:name', 'zhangsan'

向user表中插入信息,row key为rk0001,列族info中添加gender列标示符,值为female
put 'user', 'rk0001', 'info:gender', 'female'

向user表中插入信息,row key为rk0001,列族info中添加age列标示符,值为20
put 'user', 'rk0001', 'info:age', 20

向user表中插入信息,row key为rk0001,列族data中添加pic列标示符,值为picture
put 'user', 'rk0001', 'data:pic', 'picture'

获取user表中row key为rk0001的所有信息
get 'user', 'rk0001'

获取user表中row key为rk0001,info列族的所有信息
get 'user', 'rk0001', 'info'

获取user表中row key为rk0001,info列族的name、age列标示符的信息
get 'user', 'rk0001', 'info:name', 'info:age'

获取user表中row key为rk0001,info、data列族的信息
get 'user', 'rk0001', 'info', 'data'
get 'user', 'rk0001', COLUMN => ['info', 'data']

get 'user', 'rk0001', COLUMN => ['info:name', 'data:pic']

获取user表中row key为rk0001,列族为info,版本号最新5个的信息
get 'people', 'rk0002', COLUMN => 'info', VERSIONS => 2
get 'user', 'rk0001', COLUMN => 'info:name', VERSIONS => 5
get 'user', 'rk0001', COLUMN => 'info:name', VERSIONS => 5, TIMERANGE => [1392368783980, 1392380169184]

获取user表中row key为rk0001,cell的值为zhangsan的信息
get 'people', 'rk0001', FILTER => "ValueFilter(=, 'binary:图片')"

获取user表中row key为rk0001,列标示符中含有a的信息
get 'people', 'rk0001', FILTER => "(QualifierFilter(=,'substring:a'))"

put 'user', 'rk0002', 'info:name', 'fanbingbing'
put 'user', 'rk0002', 'info:gender', 'female'
put 'user', 'rk0002', 'info:nationality', '中国'
get 'user', 'rk0002', FILTER => "ValueFilter(=, 'binary:中国')"


查询user表中的所有信息
scan 'user'

查询user表中列族为info的信息
scan 'people', COLUMNS => 'info'
scan 'user', COLUMNS => 'info', RAW => true, VERSIONS => 5
scan 'persion', COLUMNS => 'info', RAW => true, VERSIONS => 3
查询user表中列族为info和data的信息
scan 'user', COLUMNS => ['info', 'data']
scan 'user', COLUMNS => ['info:name', 'data:pic']


查询user表中列族为info、列标示符为name的信息
scan 'user', COLUMNS => 'info:name'

查询user表中列族为info、列标示符为name的信息,并且版本最新的5个
scan 'user', COLUMNS => 'info:name', VERSIONS => 5

查询user表中列族为info和data且列标示符中含有a字符的信息
scan 'people', COLUMNS => ['info', 'data'], FILTER => "(QualifierFilter(=,'substring:a'))"

查询user表中列族为info,rk范围是[rk0001, rk0003)的数据
scan 'people', COLUMNS => 'info', STARTROW => 'rk0001', ENDROW => 'rk0003'

查询user表中row key以rk字符开头的
scan 'user',FILTER=>"PrefixFilter('rk')"

查询user表中指定范围的数据
scan 'user', TIMERANGE => [1392368783980, 1392380169184]

删除数据
删除user表row key为rk0001,列标示符为info:name的数据
delete 'people', 'rk0001', 'info:name'
删除user表row key为rk0001,列标示符为info:name,timestamp为1392383705316的数据
delete 'user', 'rk0001', 'info:name', 1392383705316


清空user表中的数据
truncate 'people'


修改表结构
首先停用user表(新版本不用)
disable 'user'

添加两个列族f1和f2
alter 'people', NAME => 'f1'
alter 'user', NAME => 'f2'
启用表
enable 'user'


###disable 'user'(新版本不用)
删除一个列族:
alter 'user', NAME => 'f1', METHOD => 'delete' 或 alter 'user', 'delete' => 'f1'

添加列族f1同时删除列族f2
alter 'user', NAME => 'f1', NAME => 'f2', METHOD => 'delete'

将user表的f1列族版本号改为5
alter 'people', NAME => 'info', VERSIONS => 5
启用表
enable 'user'


删除表
disable 'user'
drop 'user'


get 'person', 'rk0001', FILTER => "ValueFilter(=, 'binary:中国')"
get 'person', 'rk0001', FILTER => "(QualifierFilter(=,'substring:a'))"
scan 'person', COLUMNS => 'info:name'
scan 'person', COLUMNS => ['info', 'data'], FILTER => "(QualifierFilter(=,'substring:a'))"
scan 'person', COLUMNS => 'info', STARTROW => 'rk0001', ENDROW => 'rk0003'

scan 'person', COLUMNS => 'info', STARTROW => '20140201', ENDROW => '20140301'
scan 'person', COLUMNS => 'info:name', TIMERANGE => [1395978233636, 1395987769587]
delete 'person', 'rk0001', 'info:name'

alter 'person', NAME => 'ffff'
alter 'person', NAME => 'info', VERSIONS => 10


get 'user', 'rk0002', COLUMN => ['info:name', 'data:pic']


scan 'people', COLUMNS => 'info',RAW => true, VERSIONS => 3

HBASE常用的Java接口

package liuxun.hadoop.hbase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.Test;

public class HBaseDemo 
	private Configuration conf = null;
	@Before
	public void init() 
		conf = HBaseConfiguration.create();
		conf.set("hbase.zookeeper.quorum", "hadoop4:2181,hadoop5:2181,hadoop6:2181");
	
	/**
	 * 插入单条数据
	 * @throws Exception 
	 */
	@Test
	public void testPut() throws Exception 
		HTable table = new HTable(conf, "peoples");
		Put put = new Put(Bytes.toBytes("kr0001")); //指定row key
		put.add(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("张三"));
		put.add(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes(35));
		put.add(Bytes.toBytes("info"), Bytes.toBytes("money"), Bytes.toBytes(150000.0));
		table.put(put);
		table.close();
	
	/**
	 * 插入多条数据
	 * @throws Exception
	 */
	@Test
	public void testPutAll() throws Exception 
		HTable table = new HTable(conf, "peoples");
//		List<Put> puts = new ArrayList<>();
//		for(int i = 1; i <= 1000000; i++) 
//			Put put = new Put(Bytes.toBytes("kr"+i));
//			put.add(Bytes.toBytes("info"), Bytes.toBytes("money"), Bytes.toBytes(""+i));
//			puts.add(put);
//		
//		table.put(puts);
//		table.close();
		List<Put> puts = new ArrayList<>(10000);
		for (int i = 1; i <= 1000000; i++) 
			Put put = new Put(Bytes.toBytes("kr" + i));
			put.add(Bytes.toBytes("info"), Bytes.toBytes("money"), Bytes.toBytes("" + i));
			puts.add(put);
			if (i % 10000 == 0) 
				table.put(puts);
				puts = new ArrayList<>(10000);
			
		
		table.put(puts);
		table.close();
	
	
	/**
	 * 根据row key查询单条数据
	 * @throws Exception
	 */
	@Test
	public void testGet() throws Exception 
		HTable table = new HTable(conf, "peoples");
		Get get = new Get(Bytes.toBytes("kr1000000")); //根据主键查询
		Result result = table.get(get);
		String money = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("money"))); 
		System.out.println(money);
		table.close();
	
	
	/**
	 * 查询多条数据
	 * @throws Exception
	 */
	@Test
	public void testScan() throws Exception 
		HTable table = new HTable(conf, "peoples");
		Scan scan = new Scan(Bytes.toBytes("kr299990"), Bytes.toBytes("kr300000"));
		ResultScanner scanner = table.getScanner(scan);
		for (Result result : scanner) 
			String money = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("money"))); 
			System.out.println(money);
		
		table.close();
	
	
	/**
	 * 删除数据 
	 * 注意:并没有真正删除,而只是做了一个标志位,只有flush清空内存的时候才会真正删除
	 * @throws Exception
	 */
	@Test
	public void testDel() throws Exception 
		HTable table = new HTable(conf, "peoples");
		Delete delete = new Delete(Bytes.toBytes("kr1000000"));
		table.delete(delete);
		table.close();
	
	
	public static void main(String[] args) throws Exception 
		Configuration conf = HBaseConfiguration.create();
		// 通过ZooKeeper确定连接地址,配置内容从hbase-site.xml中查找
		conf.set("hbase.zookeeper.quorum", "hadoop4:2181,hadoop5:2181,hadoop6:2181");
		
		HBaseAdmin admin = new HBaseAdmin(conf);
		
		HTableDescriptor desc = new HTableDescriptor(TableName.valueOf("peoples"));
		HColumnDescriptor family_info = new HColumnDescriptor("info");
		family_info.setMaxVersions(3);
		HColumnDescriptor family_data = new HColumnDescriptor("data");
		desc.addFamily(family_info);
		desc.addFamily(family_data);
		admin.createTable(desc);
		admin.close();
	



以上是关于Hadoop详解——HBASE原理HBASE的集群安装常用命令和Java接口的主要内容,如果未能解决你的问题,请参考以下文章

大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 图文详解

Hbase_入门配置

HBase详解

HBase 0.98 分布式集群安装详解

HBase 0.98 分布式集群安装详解

CDH Hadoop + HBase HA 部署详解