Hbase概念
hbase & hdfs 关系图
hadoop数据库,分布式可伸缩大型数据存储。
用户对随机、实时读写数据。
十亿行 x 百万列。
版本化、非关系型数据库。
Feature
- Linear and modular scalability.
//线性模块化扩展方式。 - Strictly consistent reads and writes.
//严格一致性读写 - Automatic and configurable sharding of tables
//自动可配置表切割 - Automatic failover support between RegionServers.
//区域服务器之间自动容在 - Convenient base classes for backing Hadoop MapReduce jobs with Apache HBase tables.
- Easy to use Java API for client access.
//java API - Block cache and Bloom Filters for real-time queries
//块缓存和布隆过滤器用于实时查询 - Query predicate push down via server side Filters
//通过服务器端过滤器实现查询预测 - Thrift gateway and a REST-ful Web service that supports XML, Protobuf, and binary data encoding options
- Extensible jruby-based (JIRB) shell
- Support for exporting metrics via the Hadoop metrics subsystem to files or Ganglia; or via JMX
//可视化 - 面向列数据库。
HBase要点
- 1) 它介于 NoSQL 和 RDBMS 之间,仅能通过主键(rowkey)和主键的 range 来检索数据
- 2) HBase 查询数据功能很简单,不支持 join 等复杂操作
- 3) 不支持复杂的事务,只支持行级事务(可通过 hive 支持来实现多表 join 等复杂操作)。
- 4) HBase 中支持的数据类型:byte
- 5) 主要用来存储结构化和半结构化的松散数据。
HBase 表特点
- 大:一个表可以有上十亿行,上百万列
- 面向列:面向列(族)的存储和权限控制,列(簇)独立检索。
- 稀疏:对于为空(null)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
- 无模式:每行都有一个可排序的主键和任意多的列,列可以根据需要动态的增加,同一 张表中不同的行可以有截然不同的列
HBase 存储机制
- 面向列存储,table是按row排序。
- 底层是 跳表 & 布隆过滤器
HBase 定位机制(三级坐标)
- 行
rowkey - 列族 & 列
column family & column - 时间戳
timestamp版本
表 行 列 列族的关系
官网的关系图如下
其它版本
Table is a collection of rows.
表是行的集合Row is a collection of column families
行是列族的集合Column family is a collection of columns.
列族是列的集合Column is a collection of key value pairs.
列是键值对的集合(列其实就是 key)
RowKey, Column Family, TimeStamp, Cell 概念解释
- RowKey 是用来检索记录的主键
- rowkey 行键可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),最好是 16。
- 每一个物理文件中都会存一个 rk:TODO ??
- 在 HBase 内部,rowkey 保存为字节数组。HBase 会对表中的数据按照 rowkey 排序 (字典顺序)
- 设计 key 时,要充分排序存储这 个特性,将经常一起读取的行存储放到一起。(位置相关性)
- 注意:字典序对 int 排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…9,91,92,93,94,95,96,97,98,99。要保持整形的自然序,行键必须用 0 作左填充。
- rowkey 行键可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),最好是 16。
- Column Family 列族是表的 Schema 的一部分(而列不是),必须在使用表之前定义好,而且定义好了之后就不能更改。
- HBase 表中的每个列,都归属与某个列簇。
- 列簇越多,在取一行数据时所要参与 IO、搜寻的文件就越多,所以,如果没有必要,不要 设置太多的列簇(最好就一个列簇)
- TimeStamp
- HBase 中通过 rowkey 和 columns 确定的为一个存储单元称为 cell。
- 每个 cell 都保存着同一份 数据的多个版本。
- 版本通过时间戳来索引。
- 每个 cell 中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
- hbase 提供了两种数据版 本回收方式:
- 保存数据的最后 n 个版本
- 保存最近一段时间内的版本(设置数据的生命周期 TTL)。
- Cell 单元格
- 由{rowkey, column( =
+ ), version} 唯一确定的单元。 - Cell 中的数据是没有类型的,全部是字节码形式存贮。
- 由{rowkey, column( =
HBase 的HA搭建
选择安装的主机cs1~cs4, 安装jdk, 解压hbase 包, 配置环境变量
验证安装是否成功
$>hbase version配置 hbase 完全分布式
[hbase/conf/hbase-env.sh]
export JAVA_HOME=/usr/local/jdk1.8.0_73
export HBASE_MANAGES_ZK=false[hbse-site.xml]
hbase.cluster.distributed
true
hbase.rootdir
hdfs://mycluster/hbase
hbase.zookeeper.quorum
cs1:2181,cs2:2181,cs3:2181
hbase.zookeeper.property.dataDir
/home/ap/zookeeper 配置 regonservers
[hbase/conf/regionservers]
cs2
cs3
cs4
cs5修改 backup-masters(自行创建),指定备用的主HMaster
vi backup-masters
cs6
最重要一步:
- 傻逼版:
- 要把 hadoop 的 hdfs-site.xml 和 core-site.xml 放到 hbase/conf 下, 这样hbase 才能通过命名空间mycluster 找到当前可用 namenode, 再通过 namenode 分配指定 hbase 在 HDFS上的存储路径
cp /apps/hadoop/etc/hadoop/core-site.xml /apps/hbase/conf/
cp /apps/hadoop/etc/hadoop/hdfs-site.xml /apps/hbase/conf/
- 要把 hadoop 的 hdfs-site.xml 和 core-site.xml 放到 hbase/conf 下, 这样hbase 才能通过命名空间mycluster 找到当前可用 namenode, 再通过 namenode 分配指定 hbase 在 HDFS上的存储路径
- 高级版:
- 在hbase-env.sh文件添加hadoop配置文件目录到HBASE_CLASSPATH环境变量并分发.
[/soft/hbase/conf/hbase-env.sh]
export HBASE_CLASSPATH=$HBASE_CLASSPATH:/soft/hadoop/etc/hadoop - 在hbase/conf/目录下创建到hadoop的hdfs-site.xml符号连接。
$>ln -s /soft/hadoop/etc/hadoop/hdfs-site.xml /soft/hbase/conf/hdfs-site.xml
- 在hbase-env.sh文件添加hadoop配置文件目录到HBASE_CLASSPATH环境变量并分发.
- 傻逼版:
启动 hbase 集群
$>start-hbase.sh登录 hbase 的 webUI
- 注意, 页面上显示的版本, 是~/apps/hbase/lib中自己存储的 jar 包的版本
启动/停止 hbase 进程
等价于
- hbase-daemon.sh start master
- hbase-daemons.sh start regionserver
- 注意: 在哪个节点启动 start-hbase.sh , 就在哪里启动 HMaster 进程, 如果
- stop-hbase.sh
停止 hbase
HBase shell 操作
登录shell终端.
- $hbase> hbase shell
help 相关
- $hbase> help
查看所有帮助 - $hbase> table_help
关于表操作的另外一种方式的帮助文档 - $hbase> help “dml”
获取一组命令的提示 - $hbase>help ‘list_namespace’
查看特定的命令帮助
desc 查看描述信息
- desc ‘t1’ : 下面这些在建表的时候都可以指定
{NAME => ‘f1’, BLOOMFILTER => ‘ROW’, VERSIONS => ‘1’, IN_MEMORY => ‘false’, KEEP_DELETED_CELLS =>
‘FALSE’, DATA_BLOCK_ENCODING => ‘NONE’, TTL => ‘FOREVER’, COMPRESSION => ‘NONE’, MIN_VERSIONS =>
‘0’, BLOCKCACHE => ‘true’, BLOCKSIZE => ‘65536’, REPLICATION_SCOPE => ‘0’}
1 row(s) in 0.1780 seconds
list 相关
- $hbase> list
列出所有非系统表 - $hbase>list_namespace
列出名字空间(数据库) - $hbase>list_namespace_tables ‘defalut’
列出名字空间的所以表
create 相关
- $hbase>create_namespace ‘ns1’
创建名字空间 - $hbase>create ‘ns1:t1’,’f1’
创建表,指定空间下,列族
注意: 如果 t1已经创建了, 就不能通过这个方式来添加 列族 - create ‘t1’,’f1’
- create ‘user_info’,{NAME=>’base_info’,VERSIONS=>3 },{NAME=>’extra_info’,VERSIONS=>1 }
同时创建多个 列族
exist 相关
- exists ‘t1’
查看表是否存在
put 相关
- 注意: 如果往 同表 & 同rowkey & 同样的列 中插入 value, 会默认展示最近的一个时间戳的信息, 如果 get 的回收指定 VERSIONS数量, 则会展示此数量的版本信息
- 向 user 表中插入信息,row key 为 rk0001,列簇 info 中添加 name 列标示符,值为 zhangsan
- put ‘user’, ‘rk0001’, ‘info:name’, ‘zhangsan’, 1482077777777
手动指定时间戳
时间戳是可以自己指定的,如若不指定,则会自动获取系统的当前时间的时间戳
- put ‘user’, ‘rk0001’, ‘info:name’, ‘zhangsan’, 1482077777777
- 向 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’
get 相关
- 获取 user 表中 row key 为 rk0001 的所有信息
注意: ‘表名’, ‘ rowkey’
- get ‘user’, ‘rk0001’
- 获取 user 表中 row key 为 rk0001,info 列簇的所有信息
注意: ‘表名’, ‘ rowkey’, ‘列族名’
- get ‘user’, ‘rk0001’, ‘info’
- 获取 user 表中 row key 为 rk0001,info 列簇的 name、age 列标示符的信息
注意: ‘表名’, ‘rowkey’, ‘列族名’:’列名’, ‘列族名’:’列名’
- get ‘user’, ‘rk0001’, ‘info:name’, ‘info:age’
- 获取 user 表中 row key 为 rk0001,info、data 列簇的信息
注意: ‘表名’, ‘rowkey’, ‘列族名’, ‘列族名’
- 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 个的信息
注意: ‘表名’, ‘rowkey’, {COLUMN =>’列族名’, 存储版本数=> 数量}
- get ‘user’, ‘rk0001’, {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,列标示符中含有 a 的信息
- get ‘people’, ‘rk0001’, {FILTER => “(QualifierFilter(=,’substring:a’))”}
获取 国籍 为中国的用户信息
注意: ‘表名’, ‘rowkey’, ‘列族名’:’列名’, ‘value’
- put ‘user’, ‘rk0002’, ‘info:name’, ‘fanbingbing’
- put ‘user’, ‘rk0002’, ‘info:gender’, ‘female’
- put ‘user’, ‘rk0002’, ‘info:nationality’, ‘中国’
- get ‘user’, ‘rk0002’, {FILTER => “ValueFilter(=, ‘binary:中国’)”}
- 获取2个不同列中的指定字段
注意: ‘表名’, ‘rowkey’, {COLUMN => [‘列族名’:’列名’, ‘列族名’:’列名’]}
- get ‘user’, ‘rk0002’, {COLUMN => [‘info:name’, ‘data:pic’]}
scan 相关
扫描元数据
scan ‘hbase : meta’
t9,,1529936935368.f1a900954c069f0319195f16043c8e1a column=info:regioninfo, timestamp=1529936935933, value={ENCODED => f1a900954c069f0319195f16043c8e1a, NAME => ‘t9,,1529936935368.f1a900954c069f031919
. 5f16043c8e1a.’, STARTKEY => ‘’, ENDKEY => ‘’}
t9,,1529936935368.f1a900954c069f0319195f16043c8e1a column=info:seqnumDuringOpen, timestamp=1529936935933, value=\x00\x00\x00\x00\x00\x00\x00\x02
.
t9,,1529936935368.f1a900954c069f0319195f16043c8e1a column=info:server, timestamp=1529936935933, value=cs5:16020
.
t9,,1529936935368.f1a900954c069f0319195f16043c8e1a column=info:serverstartcode, timestamp=1529936935933, value=1529923622913$hbase>split ‘ns1:t1’
//切割表$hbase>split ‘’
//切割区域, 见下面切割之前
切割之后
UI界面 table regions
继续进行 region 切割
- scan ‘hbase:meta’
- 找到切割点 STARTKEY => ‘row000550’ 的 那行的 NAME => 后面的值
- 从这个值开始切割到指定值
split ‘t9,row000551,1529938745618.90ed2fb6b7744ea5f0a7ff613d05aada.’,’row000888’
扫描表中所有的信息
- $hbase>scan ‘ns1:t1’
查询 user 表中列簇为 info 的信息
- hbase> scan ‘hbase:meta’
扫描权标 - $hbase> scan ‘hbase:meta’, {COLUMNS => ‘info’}
注意: COLUMNS要大写 - $hbase> scan ‘ns1:t1’, {COLUMNS => [‘c1’, ‘c2’], LIMIT => 10, STARTROW => ‘xyz’}
- scan ‘user’, {COLUMNS => ‘info’, RAW => true, VERSIONS => 5}
- scan ‘persion’, {COLUMNS => ‘info’, RAW => true, VERSIONS => 3}
Scan 时可以设置是否开启 Raw 模式,开启 Raw 模式会返回包括已添加删除标记但是未 实际删除的数据。
- hbase> scan ‘hbase:meta’
查询 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 ‘user’, {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]}
delete/truncate 相关 (删除,清空数据)
- 注意: 删除列族, 在 alter 中
- 删除 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’
目前版本会先 disable , 再 truncate, 最后再 enable
- truncate ‘people’
alter 相关
- 注意,在修改列族 时
hbase> alter ‘t1’, NAME => ‘f1’, VERSIONS => 5
- VERSIONS 是指能存多少个版本, 如果不指定的话, 退出 hbase 的时候, 默认只会留最新的一个版本
- 如果存在, 就是修改
- 不存在, 就是增加
添加两个列簇 f1 和 f2
- 简写: alter ‘t1’, ‘f2’
- alter ‘people’, NAME => ‘f1’
- alter ‘user’, NAME => ‘f2’
停用/启用 表
- enable ‘t9’
启用 - is_enabled ‘t9’
是否可用 - disable ‘t9’
停用 - is_disabled ‘t9’
是否不可用
- enable ‘t9’
删除一个列簇:
- 注意: 当表中只有一个列族时, 无法将其删除
- disable ‘user’(新版本不用)
- alter ‘user’, NAME => ‘f1’, METHOD => ‘delete’
- 或
- alter ‘user’, ‘delete’ => ‘f1’
- enable ‘user’
添加列簇 f1 同时删除列簇 f2
- disable ‘user’(新版本不用)
- alter ‘user’, {NAME => ‘f1’}, {NAME => ‘f2’, METHOD => ‘delete’}
- enable ‘user’
将 user 表的 f1 列簇版本号改为 5
- disable ‘user’(新版本不用)
- alter ‘people’, NAME => ‘info’, VERSIONS => 5
people 为 rowkey - enable ‘user’
drop 相关
- disable ‘user’
- drop ‘user’
count 相关
- $hbase>count ‘ns1:t1’
统计函数, 1000行统计一次
flush 相关
- 把文件刷到磁盘的过程
- hbase> flush ‘TABLENAME’
- hbase> flush ‘REGIONNAME’
- hbase> flush ‘ENCODED_REGIONNAME’
ValueFilter 过滤器
- get ‘person’, ‘rk0001’, {FILTER => “ValueFilter(=, ‘binary:中国’)”}
- get ‘person’, ‘rk0001’, {FILTER => “(QualifierFilter(=,’substring:a’))”}
exit 退出
$hbase> exit
遇到问题总结
- 插入前, 必须创建好
- namespace
相当于数据库的概念 - table
表命 - column family
列族名
- namespace
- 不需要提前创建
- 行名
- 列名
- value
- 如果表已经创建, 要增加列族的话, 只能用 alter, 不能继续用 create
通过Java API访问Hbase
创建hbase模块
添加依赖
<?xml version=”1.0” encoding=”UTF-8”?>
4.0.0
com.rox
HbaseDemo
1.0-SNAPSHOT
org.apache.hbase
hbase-client
1.2.3
复制hbase集群的hbase-site.xml文件到模块的src/main/resources目录下。
-——————————————————————————————
Hbase API 类和数据模型之间的对应关系:
\0. 总的对应关系
- HBaseAdmin
编程实现 代码见 https://github.com/airpoet/bigdata/blob/master/HBaseDemo/src/test/java/com/rox/text/TestCRUD.java
public class TestCRUD {
@Test
public void put() throws IOException {
// 创建 conf 对象
Configuration conf = HBaseConfiguration.create();/ 通过连接工厂创建连接对 /
// 通过连接工厂创建连接对象
Connection conn = ConnectionFactory.createConnection(conf);
// 通过连接查询 TableName 对象
TableName tname = TableName.valueOf(“ns1:t1”);
// 获得 table对象
Table table = conn.getTable(tname);
// 通过bytes 工具类转化字符串为字节数组
byte[] bytes = Bytes.toBytes(“row3”);
// 创建 put 对象, 传入行号
Put put = new Put(bytes);
// 创建 列族, 列, value 的 byte 数据
byte[] f1 = Bytes.toBytes(“f1”);
byte[] id = Bytes.toBytes(“id”);
byte[] value = Bytes.toBytes(188);
put.addColumn(f1, id, value);
// table put 数据
table.put(put);
//============================
// get
byte[] rowid = Bytes.toBytes(“row3”);
Get get = new Get(rowid);
// 得到 res
Result res = table.get(get);
// 从 res 中取出 value
byte[] idvalue = res.getValue(Bytes.toBytes(“f1”),Bytes.toBytes(“id”));
System.out.println(Bytes.toInt(idvalue));
}
}
HBase 写入过程 & 存储路径
- WAL
write ahead log,写前日志。 - HDFS 上存储路径详解
- http://cs1:50070/explorer.html#/hbase/data/ns1/t1/97eada11d196f1e134c41e859d338e07/f1/fsfsfgwgfsgfrgfdg
- data
存储数据的目录 - ns1
namespace 名称 - t1
表名 - 97eada11d196f1e134c41e859d338e07
region 的编号 - f1
列族 - fsfsfgwgfsgfrgfdg
HFile: 列族存储的文件, 每一个 hfile 文件对应的是一个列族
- data
- meta 数据路径 http://cs1:50070/explorer.html#/hbase/data/hbase/meta/1588230740/info
- http://cs1:50070/explorer.html#/hbase/data/ns1/t1/97eada11d196f1e134c41e859d338e07/f1/fsfsfgwgfsgfrgfdg
HBase 和 Hive 的比较
- 相同点
- HBase 和 Hive 都是架构在 Hadoop 之上,用 HDFS 做底层的数据存储,用 MapReduce 做 数据计算
- 不同点
- 解决的问题不同
- Hive 是建立在 Hadoop 之上为了降低 MapReduce 编程复杂度的 ETL 工具。
- HBase 是为了弥补 Hadoop 对实时操作的缺陷
- 表的架构不同
- Hive 表是纯逻辑表,因为 Hive 的本身并不能做数据存储和计算,而是完全依赖 Hadoop
- HBase 是物理表,提供了一张超大的内存 Hash 表来存储索引,方便查询
- 定位 & 访问机制不同
- Hive 是数据仓库工具,需要全表扫描,就用 Hive,因为 Hive 是文件存储
- HBase 是数据库,需要索引访问,则用 HBase,因为 HBase 是面向列的 NoSQL 数据库
- 存储模式不同
- Hive 表中存入数据(文件)时不做校验,属于读模式存储系统
- HBase 表插入数据时,会和 RDBMS 一样做 Schema 校验,所以属于写模式存储系统
- 是否实时处理(处理效率)不同
- Hive 不支持单行记录操作,数据处理依靠 MapReduce,操作延时高
- HBase 支持单行记录的 CRUD,并且是实时处理,效率比 Hive 高得多
- 解决的问题不同
HBase在 HDFS 上的存储路径
- 相同列族的数据存放在一个文件中。
- [表数据的存储目录结构构成]
- [WAL目录结构构成]
Client 端 与 HBase 交互过程
HBase 简单集群结构
- region:是 hbase 中对表进行切割的单元,由 regionserver 负责管理
- region 分裂是逻辑概念?? :TODO
- hamster:hbase 的主节点,负责整个集群的状态感知,负载分配、负责用户表的元数据(schema)管理(可以配置多个用来实现 HA),hmaster 负载压力相对于 hdfs 的 namenode 会小很多
- regionserver:hbase 中真正负责管理 region 的服务器,也就是负责为客户端进行表数据读写 的服务器每一台 regionserver 会管理很多的 region,同一个 regionserver 上面管理的所有的 region 不属于同一张表
- zookeeper:整个 hbase 中的主从节点协调,主节点之间的选举,集群节点之间的上下线感 知„„都是通过 zookeeper 来实现
- HDFS:用来存储 hbase 的系统文件,或者表的 region
- region:是 hbase 中对表进行切割的单元,由 regionserver 负责管理
Hbase 顶层结构图
0.hbase集群启动时,master负责分配区域到指定区域服务器。
1.联系zk,找出meta表所在rs(regionserver)/hbase/meta-region-server
2.定位row key,找到对应region server
3.缓存信息在本地。
4.联系RegionServer
5.HRegionServer负责open HRegion对象,为每个列族创建Store对象,Store包含多个StoreFile实例,他们是对HFile的轻量级封装。每个Store还对应了一个MemStore,用于内存存储数据。
百万数据批量插入
- 代码
long start = System.currentTimeMillis() ;
Configuration conf = HBaseConfiguration.create();
Connection conn = ConnectionFactory.createConnection(conf);
TableName tname = TableName.valueOf(“ns1:t1”);
HTable table = (HTable)conn.getTable(tname);
//不要自动清理缓冲区
table.setAutoFlush(false);
for(int i = 4 ; i < 1000000 ; i ++){
}Put put = new Put(Bytes.toBytes("row" + i)) ; //关闭写前日志 put.setWriteToWAL(false); put.addColumn(Bytes.toBytes("f1"),Bytes.toBytes("id"),Bytes.toBytes(i)); put.addColumn(Bytes.toBytes("f1"),Bytes.toBytes("name"),Bytes.toBytes("tom" + i)); put.addColumn(Bytes.toBytes("f1"),Bytes.toBytes("age"),Bytes.toBytes(i % 100)); table.put(put); if(i % 2000 == 0){ table.flushCommits(); }
//
table.flushCommits();
System.out.println(System.currentTimeMillis() - start );
HBase 切割文件
- 默认10G 进行切割
hbase.hregion.max.filesize
10737418240
HBase 合并文件
- merge_region ‘1f4609ba4e2a9440aedde5d0e7123722’,’48277c27196a5c6e30d5ae679e9ec4f0’
merge ‘前一个区域的 encoded’ , ‘后一个区域的 encoded’
HBase 手动移动文件
- hbase(main):034:0> move ‘8658ac9ea01f80c2cca32693397a1e70’,’cs3,16020,1529980599903’
前面是 encoded region name , 后面是服务器名
预先切割
- 创建表时, 预先对表进行切割
- 切割线是 rowkey
create ‘ns1:t2’,’f1’,SPLITS=>[‘row300’, ‘row600’] - 创建预先切割表之后, 存的值就会到对应的区域中去
- 注意: put 一次就是一条数据
指定版本数的问题
- 创建表时指定列族的版本数,该列族的所有列都具有相同数量版本
- 创建表时,指定列族的版本数。
$hbase>create ‘ns1:t3’,{NAME=>’f1’,VERSIONS=>3} - 如果创建表的时候创的是3个版本, 查4个版本, 此时最多也就显示3个
$hbase>get ‘ns1:t3’,’row1’,{COLUMN=>’f1’,VERSIONS=>4}
COLUMN CELL
f1:name timestamp=1530019546709, value=tom3
f1:name timestamp=1530019542978, value=tom2
f1:name timestamp=1530019540164, value=tom1
原生扫描(expert)
原生扫描, 包含标记了delete的数据
$hbase>scan ‘ns1:t3’,{COLUMN=>’f1’,RAW=>true,VERSIONS=>10}
hbase(main):177:0> scan ‘ns1:t3’,{COLUMN=>’f1’,RAW=>true,VERSIONS=>10}
ROW COLUMN+CELL
row1 column=f1:name, timestamp=1530019546709, value=tom3
row1 column=f1:name, timestamp=1530019542978, value=tom2
row1 column=f1:name, timestamp=1530019540164, type=DeleteColumn
row1 column=f1:name, timestamp=1530019540164, value=tom1删除数据, 标记为删除, 小于该删除时间的数据都作废, flush 后, 用 RAW 似乎还会保留, 用非 RAW 的方式查看的画, 此删除数据, 及时间戳比这个小的数据, 都不会显示.
$hbase>delete ‘ns1:t3’,’row1’,’f1:name’,148989875645
- 这里是否要停掉 hbase 服务再起来看看?
TTL
- time to live ,存活时间
- 影响所有的数据,包括没有删除的数据
- 超过该时间,原生扫描也扫不到数据
- 创建带 TTL参数的表
$hbase>create ‘ns1:tx’ , {NAME=>’f1’,TTL=>10,VERSIONS=>10}
KEEP_DELETED_CELLS
- 删除key之后,数据是否还保留, 未测试
$hbase>create ‘ns1:tx’ , {NAME=>’f1’,TTL=>10,VERSIONS,KEEP_DELETED_CELLS=>true} - TTL 的优先级高于 KEEP_DELETED_CELLS, 如果设置了 TTL, 时间一到就没了, 用 RAW 也找不回来
- 删除key之后,数据是否还保留, 未测试
缓存 和 批处理
开启服务器端扫描器缓存
- 表层面(全局), 貌似是默认的? 再看看书上说的
hbase.client.scanner.caching
2147483647
- 表层面(全局), 貌似是默认的? 再看看书上说的
操作层面
注意: 貌似JavaAPI 中默认是没有设置 caching 的
- 设置方式
scan.setCaching(10); - 操作时间
cache row nums : 1000 //632
cache row nums : 5000 //423
cache row nums : 1 //7359
扫描器缓存是 面向行级别的
批量扫描是 面向列级别的
- 控制每次next()服务器端返回的列的个数。
- scan.setBatch(5);
每次next返回5列。
过滤器
图示
代码
计数器
- shell 实现
- $hbase>incr ‘ns1:t8’,’row1’,’f1:click’,1
后面可以跟任意数字, 正负,0都可以 - $hbase>get_counter ‘ns1:t8’,’row1’,’f1:click’
获取计数器
- $hbase>incr ‘ns1:t8’,’row1’,’f1:click’,1
- Java 代码
协处理器 coprocessor :TODO 有空再看
批处理的,等价于存储过程或者触发器
Observer
- RegionObserver //RegionServer区域观察者
- MasterObserver //Master节点。
- WAlObserver //
Endpoint
- 终端,类似于存储过程。
HBase & Mapreduce 整合
- 运行官方案例
- [ap@cs1]~/apps/hbase% export HBASE_HOME=/home/ap/apps/hbase
- [ap@cs1]~/apps/hbase% export HADOOP_HOME=/home/ap/apps/hadoop
- [ap@cs1]~/apps/hbase% export HADOOP_CLASSPATH=
${HBASE_HOME}/bin/hbase mapredcp
- 使用 MapReduce导入本地数据到Hbase
- apps/hadoop/bin/yarn jar apps/hbase/lib/hbase-server-1.2.6.1.jar importtsv \
- -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:color fruit \
- hdfs://cs1:8020/input_fruit
这是 namenode 的 RPC 地址
HBase & Hive 整合
1.环境配置
1 | export HBASE_HOME=/home/ap/apps/hbase |