hadoop实时day19–Apache HBase
今日课程内容大纲
1、Apache HBase 介绍概述
nosql 数据库
2、Apache HBase 数据模型
3、Apache HBase
和hadoop关系
和rdbms关系
4、Apache HBase 特性优点
5、Apache HBase 组件角色、职责--初识版
主从架构集群
6、Apache HBase集群搭建
7、Apache HBase shell 操作
DDL:创建表 修改表 删除表
DML:插入数据 更新数据 查询数据 删除数据
今日课程内容重点:all
HBase 基本概念
-
介绍
-
hbase是一款==基于HDFS,支持实时读写的nosql列式存储数据库==。
#数据库 hbase不是olap系统。hbase不支持复杂业务分析。 #nosql数据库 hbase不是rdbms(关系型数据库) 不支持sql语法 事务支持及其薄弱 #基于hdfs 实时读写 hdfs交互延时很高 hbase又可以实时读写 如何解决这两个冲突的? hbase lsm树(内存加磁盘) #列式存储 便于查询 hbase大表实时查询
-
hbase启发于Google ==bigtable==论文 之前属于hadoop子项目 后独立出来成为单独顶级项目
hbase= hadoop database简写 billions of rows millions of columns 数十亿行 数百万列
-
hbase设计目标 大表数据实时写入 实时查询功能。
-
hbase本身并不快,只是表数据大的时候慢的不明显。
国内对应mysql单表性能 阿里建议单表数据超过500w 进行分表分库 否则mysql性能会急剧降低。 oracle于商业软件 性能比mysql强很多 千万行级别数据
-
-
HBase 数据模型
-
从整体上审视如何存储大表。
-
宽窄表。 形容列多,列式存储。
同一列的数据存储在一起 便于查询。 针对不同的列进行不同的优化
-
高低表。形容行多,表分区(region)
根据行的范围把表的数据进行分区 不同分区的数据可以存储在不同的机器上
-
-
从具体细节来看
-
namespace(ns)
命名空间 类似于mysql中数据库的概念 在一个命名空间下可以创建多个表。 默认命名空间叫做default。
-
table(t)
hbase中的一张张表 。hbase基于表模型管理数据的。
-
region
表的分区。 指定范围内的行的数据组成表的一个分区。 可以解决大表的存不存下的问题。 不同分区可以存储在不同的机器上。
-
rowkey(rk)
行键。是hbase不同行的数据区分的唯一标识。 类似于mysql中主键。不重复的。 rowkey默认根据字典序排序。 已有: 0001 0002 新增: 00011 结果: 0001 00011 0002
-
Column Family(cf)
多个列的集合构成一个列族。在底层 同一个列族的数据是存储在一起的。 官方建议列族越少越好。 在hbase中操作列的时候 一定要指定属于哪一个列族。 列族:列 不同行数据的同一个列族下面可以不同的列。
-
Column Qualifier(cq c)
一列数据。
-
cell
单元格。由table+rk+cf+c 定位到一个单元格。 单元格中不仅有value数据 还有数据版本号。
-
timestamp
版本号。 hbase默认存储一个版本的数据。支持存储多个版本的数据。 默认版本号是根据插入更新的时间戳来定义的 也可以用户指定版本号。 在查询的时候 默认返回最新版本的数据 也可以指定返回版本的数据。
-
-
HBase 和其中表的特性
-
HBase特性
- 海量存储 分布式概念
- 列式存储
- 准确来说列族存储。 便于查询
- 极易扩展
- 从hbase的角度看 ,表可以不断拆分成region
- 从底层存储来看 hbase的数据放置在hdfs上
- 高并发
- 稀疏性
-
- hbase表一点都不稀疏 十分严谨
-
HBase表的特点
-
数据规模大
-
无严格约束 不遵循行列对应
不同行可以有不同的列
-
表一点不稀疏 很紧凑
-
数据多版本存储
-
数据无类型
所有的数据在hbase底层 都是以byte[]形式存在的。
-
-
HBase 基本架构
-
hbase是一个标准的主从架构
- 常见的是一主多从
- 也可以多主多从。 形成master ha机制。
-
具体角色
-
主角色:master
- DDL操作
- 监控regionserver状态、region故障迁移 负载均衡
-
从角色:regionserver
- DML操作 数据读写请求的直接参与者
- region split、compact
-
依赖
- zk集群
- master主备选举
- regionserver master 挂掉故障监控通知
- 元数据存储
- hbase中表的region范围 位于哪台机器位置信息
- 读写请求必须先找zk
- hdfs集群
- 最终数据存储在hdfs上的。
- zk集群
-
-
regionserver内部初探
- 详细见课堂画图。
HBase集群搭建
-
前提
- 保证==hdfs集群和zk集群正常启动,且服务可用==。
-
安装包
hbase-1.2.0-cdh5.14.0.tar.gz
-
上传解压
-
配置文件
-
conf/hbase-env.sh
export JAVA_HOME=/export/servers/jdk1.8.0_65 export HBASE_MANAGES_ZK=false #关闭hbase自带的zk服务 使用自己搭建的zk 注释掉下述两个配置 # Configure PermSize. Only needed in JDK7. You can safely remove it for JDK8+ #export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m" #export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"
-
conf/hbase-site.xml
<configuration> <property> <name>hbase.rootdir</name> <value>hdfs://node-1:8020/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.master.port</name> <value>16000</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>node-1:2181,node-2:2181,node-3:2181</value> </property> <property> <name>hbase.zookeeper.property.dataDir</name> <value>/export/data/zkdata</value> </property> </configuration>
-
conf/regionservers 从角色位置信息 配合脚本一键启动
node-1 node-2 node-3
-
-
scp安装包到其他节点
-
拷贝hadoop的配置文件给hbase 3台机器都需要执行。
core-site.xml hdfs-site,xml ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/core-site.xml /export/servers/hbase/conf/core-site.xml ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml /export/servers/hbase/conf/hdfs-site.xml
-
配置hbase环境变量
vim /etc/profile export HBASE_HOME=/export/servers/hbase export PATH=:$HBASE_HOME/bin:$PATH source /etc/profile scp /etc/profile root@node-3:/etc/
-
hbase集群启动
-
问问自己 hdfs和zk启动了没?服务正常没?
-
单节点逐个启动
hbase-daemon.sh start|stop master、regionserver
-
脚本一键启动
start-hbase.sh stop-hbase.sh
-
-
HBase的 web UI页面
http://master_host:60010
HBase shell命令行
-
格式
bin/hbase shell
-
注意事项
- hbase 支持sql语法吗? 不支持sql
- hbase 客户端是ruby语言语法风格。(hbase使用java版本的ruby 简称jruby)
- hbase 客户端删除错误信息。
- backspace 向后删除
- ctrl+backspace 向前删除 (和之外的习惯是一致)
- 还可以直接ctrl+c 结束
-
需要学习掌握的命令
#Group name: general Commands: status, table_help, version, whoami # Group name: namespace 针对命名空间操作 类似于mysql中数据库 Commands: create_namespace, describe_namespace, drop_namespace, list_namespace, list_namespace_tables # Group name: ddl 数据定义语言 针对表的操作 Commands: alter, create, describe, disable, disable_all, drop, drop_all, enable, enable_all, exists, is_disabled, is_enabled, list # Group name: dml 数据操纵语言 针对表的数据操纵 Commands: count, delete, deleteall, get, put, scan, truncate
- 如果不知道命令如何使用 可以在shell 直接输入命令回车 提示使用方法。
- hbase 命令结尾不需要加;
-
命名空间
如果不指定命名空间 所有操作默认是在default下。 如果需要指定操作命名空间 ns1:t1
-
ddl
-
显示表 list
hbase(main):022:0> list TABLE t_user 1 row(s) in 0.0080 seconds => ["t_user"]
-
创建表 create
#在hbase建表的时候 只需要指定列族名称即可 至于列族下有哪些列 在插入数据的时候指定 create 't1', {NAME => 'f1'}, {NAME => 'f2'}, {NAME => 'f3'} create 't1', 'f1', 'f2', 'f3' create 't_user','basic_info','extral_info' #创建一张表 两个列族
-
删除表 drop
#hbase中表存在两种状态: 可以enable 不可用 disable #如果需要删除一张表 首先禁用该表 disable 然后再执行删除 hbase(main):014:0> drop 't_userbasic_info' ERROR: Table t_userbasic_info is enabled. Disable it first. Drop the named table. Table must first be disabled: hbase> drop 't1' hbase> drop 'ns1:t1' #禁用表 disable, disable_all #启动表 enable, enable_all #判断表是否可用 是否禁用 is_disabled, is_enabled hbase(main):016:0> is_disabled 't_userbasic_info' false hbase(main):017:0> is_enabled 't_userbasic_info' true #如何删除一张表 hbase(main):018:0> disable 't_userbasic_info' hbase(main):019:0> is_disabled 't_userbasic_info' true hbase(main):020:0> drop 't_userbasic_info'
-
修改表 alter
-
查看表元信息 desc
hbase(main):024:0> desc 't_user' Table t_user is ENABLED #表状态 t_user #表名 COLUMN FAMILIES DESCRIPTION #列族信息 #列族basic_info相关信息 {NAME => 'basic_info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CEL LS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'} #列族extral_info相关信息 {NAME => 'extral_info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CE LLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
-
-
dml
-
插入数据 put
# 在插入数据的时候 需要指定表名 rowkey 列族 列 列值 [版本号] hbase> put 't1', 'r1', 'c1', 'value' #意味着hbase在插入数据的时候 只能一个一个cell插入 不能一行同时插入 put 't_user','001','basic_info:name','allen' put 't_user','001','extral_info:city','sh' put 't_user','002','basic_info:age','18' put 't_user','002','extral_info:hobby','sing' put 't_user','003','basic_info:name','tom' put 't_user','003','extral_info:city','bj' put 't_user','003','extral_info:hobby','ball' put 't_user','004','basic_info:name','anna' put 't_user','004','basic_info:age','19'
-
更新数据 put
- 在put数据的时候 如果数据不存在 此时就是插入操作
- 在put数据的时候 如果数据已经存在 此时就是更新操作
-
查询数据
-
get 查询
#get在查询的时候 必须指定rowkey 意味着一次只能查询一行数据 #1、只指定rowkey 返回一行数据 hbase(main):039:0> get 't_user','003' COLUMN CELL basic_info:name timestamp=1598255796692, value=tom extral_info:city timestamp=1598255800291, value=bj extral_info:hobby timestamp=1598255803542, value=ball #2、指定返回 列族的数据 get 't_user','003',{COLUMN => 'extral_info'} hbase(main):041:0> get 't_user','003',{COLUMN => 'extral_info'} COLUMN CELL extral_info:city timestamp=1598255800291, value=bj extral_info:hobby timestamp=1598255803542, value=ball 还可以指定多个列族 get 'r1', {COLUMN => ['c1', 'c2', 'c3']} #3、指定rowkey 列族 列---->cell hbase(main):043:0> get 't_user','003',{COLUMN => 'extral_info:hobby'} COLUMN CELL extral_info:hobby timestamp=1598255803542, value=ball # 还可以添加filter过滤器 进行更加精准的查询 get 't_user', '003', {FILTER => "ValueFilter(=,'binary:a')"} get 't_user', '003', {FILTER => "ValueFilter(=,'substring:a')"} 比较规则: BinaryComparator 按字节索引顺序比较指定字节数组,采用 Bytes.compareTo(byte[]) SubstringComparator 判断提供的子串是否出现在value中。String.contains()
-
scan 扫描数据
#scan 支持全表扫描 可以在扫描的时候加上参数进行过滤 #1、如果只指定表名 相当于全表扫描查询返回 select * from table; hbase(main):038:0> scan 't_user' #2、扫描指定列族数据 支持指定多个列族 scan 't_user', {COLUMNS => 'extral_info'} scan 'user', {COLUMNS => ['info', 'data']} hbase(main):048:0> scan 't_user', {COLUMNS => 'extral_info'} ROW COLUMN+CELL 001 column=extral_info:city, timestamp=1598255532519, value=sh 002 column=extral_info:hobby, timestamp=1598255785340, value=sing 003 column=extral_info:city, timestamp=1598255800291, value=bj 003 column=extral_info:hobby, timestamp=1598255803542, value=ball #3、扫描指定列族 指定列的数据 scan 't_user', {COLUMNS => 'extral_info:hobby'} hbase(main):049:0> scan 't_user', {COLUMNS => 'extral_info:hobby'} ROW COLUMN+CELL 002 column=extral_info:hobby, timestamp=1598255785340, value=sing 003 column=extral_info:hobby, timestamp=1598255803542, value=ball #4、控制扫描的范围 和返回条数 #从002开始扫描 startrow起始扫描位置 scan 't_user', {COLUMNS => ['basic_info'], STARTROW => '002'} #从002开始扫描 startrow起始扫描位置 控制扫描的条数 scan 't_user', {COLUMNS => ['basic_info'], LIMIT => 1, STARTROW => '002'} #从STARTROW 开始扫描 到STOPROW结束 含头不含尾 [STARTROW,STOPROW) hbase(main):054:0> scan 't_user', {COLUMNS => ['basic_info'], STARTROW => '002',STOPROW => '003'} ROW COLUMN+CELL 002 column=basic_info:age, timestamp=1598255780434, value=18 #5、hbase支持多版本数据存储 可以在查询的时候返回多个版本的数据 scan 'user', {TIMERANGE => [1392368783980, 1392380169184]}
-
-
删除数据 delete
#1、能不能删除一行数据 可以 只指定rowkey 就删除改行数据 delete 't1','rk001' #2、指定rowkey 列族 语法无误 实际效果没有 实际中可以删除各个列来实现 delete 't_user', '001', 'basic_info' #3、指定rowkey 列族:列 delete 'user', 'rk0001', 'info:name'
-
清空表数据 truncate
hbase(main):079:0> truncate 't1' Truncating 't1' table (it may take a while): - Disabling table... - Truncating table... 0 row(s) in 3.6670 seconds #在清空表数据的时候 首先会禁用表 然后再清空
-
-
HBase shell高级命令
-
status 查看集群状态
-
whoami 显示当前的操作用户 组
-
list
- 显示当前的命名空间有多少张表
-
describe 表名 desc简写
- 查看显示表信息
-
exists
- 判断表是否存在
-
count
Count the number of rows in a table. 统计一张表有多少条数据
-
HBase 多版本存储
-
概念
- 默认情况下 hbase表支持存储一个版本数据。
- 在建表的时候 或者通过alter可以修改表 让其支持存储多个版本的数据
- 默认情况下 版本号是时间戳 也可以用户指定 但是hbase 强烈不建议你自己指定。
- 在多版本存储下 查询默认返回是最新的版本 问题:新是什么意思?
- 可以在查询的时候指定返回某个版本数据
-
栗子
-
如何查看已有表是否支持多版本存储?
使用desc 命令 查看 VERSIONS => '1' 值 #可以在一张表中 针对不同列族 修改不同的版本 #也就意味着hbase的表的属性 不同列族之间可以不一样。
-
如何开启多版本存储
#创建表开启 create 't2', {NAME => 'cf1', VERSIONS => 3} #修改已有的表 alter 't1', {NAME => 'cf1', VERSIONS => 3} alter 'user', NAME => 'info', VERSIONS => 3
-
多版本数据插入
put 't2','001','cf1:name','allen1' put 't2','001','cf1:name','allen2' put 't2','001','cf1:name','allen3'
-
多版本数据查询
-
默认查询
scan 't2' 返回的是最新的版本 版本号最大的。
-
多版本查询
scan 't2', { VERSIONS => 5} hbase(main):101:0> scan 't2', { VERSIONS => 5} ROW COLUMN+CELL 001 column=cf1:name, timestamp=1598260355284, value=allen3 001 column=cf1:name, timestamp=1598260333703, value=allen2 001 column=cf1:name, timestamp=1598260313208, value=allen1
-
-
探究:为什么官方不建议自己指定版本号 ?
create 't3', {NAME => 'cf1', VERSIONS => 3} put 't3','001','cf1:name','allen1',1003 put 't3','001','cf1:name','allen2',1001 put 't3','001','cf1:name','allen3',1002 #如何理解新 和操作先后顺序没关系 和版本号大小有关系 hbase(main):110:0> scan 't3', { VERSIONS => 5} ROW COLUMN+CELL 001 column=cf1:name, timestamp=1003, value=allen1 001 column=cf1:name, timestamp=1002, value=allen3 001 column=cf1:name, timestamp=1001, value=allen2
-
HBase 删除的本质
-
删除动作
- 物理删除
- 逻辑删除
-
hbase采用是逻辑删除。
-
在执行delete删除的时候 hbase会对删除的数据进行标记。 tombstone(墓碑标记)
-
被墓碑标记的数据在正常查询下 是不显示的 对于用户来说 该数据就被删除了
-
可以通过raw模式查看那些被标记删除 但是没有真正删除的数据
-
hbase的数据究竟什么时候才真正删除。
在memstore flush 和stofile compact会进行最终删除。
-
今日作业
-
复习hbase 数据模型
-
hbase角色 职责
-
regionserver 内部组件细节 --自己画图。
-
hbase shell命令操作
-
明天内容
-
hbase架构原理
-
hbase读写流程
-
hbase核心3个机制
- memstore flush
- storefile compact
- region split
-
java api操作 尤其是查询操作
spark flink 都可以读写hbase数据。
-
hbase和mapreduce集成
-