HBase图
HBase概述
HBase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,用于存储海量的结构化或者半结构化,非结构化的数据(底层是字节数组做存储的)
HBase是Hadoop的生态系统之一,是建立在Hadoop文件系统(HDFS)之上的分布式、面向列的数据库,通过利用Hadoop的文件系统提供容错能力。如果需要进行实时读写或者随机访问大规模的数据集的时候,会考虑使用HBase。
- HBase可以看做java中的hashMap,根据key找到对应的值(get())
- 根据字节数组读
- 借助<key,键值对>的方式获取对应的数据值
- 索引
- 数据是有序的
HBase作为Google Bigtable的开源实现,Google Bigtable利用GFS作为其文件存储系统类似,则HBase利用Hadoop HDFS作为其文件存储系统;Google通过运行MapReduce来处理Bigtable中的海量数据,同样,HBase利用Hadoop MapReduce来处理HBase中的海量数据;Google Bigtable利用Chubby作为协同服务,HBase利用Zookeeper作为对应。在2010年5月,成为apache顶级项目
2.HBase处理数据
虽然Hadoop是一个高容错、高延时的分布式文件系统和高并发的批处理系统,但是它不适用于提供实时计算;
HBase是可以提供实时计算的分布式数据库,数据被保存在HDFS分布式文件系统上,由HDFS保证期高容错性;
但是再生产环境中,HBase是如何基于hadoop提供实时性呢?
HBase上的数据是以StoreFile(HFile)二进制流的形式存储在HDFS上block块儿中;
但是HDFS并不知道的HBase用于存储什么,它只把存储文件认为是二进制文件,也就是说,HBase的存储数据对于HDFS文件系统是透明的。
3.HBase与HDFS
在下面的表格中,我们对HDFS与HBase进行比较:
HDFS | HBase |
---|---|
HDFS适于存储大容量文件的分布式文件系统。 | HBase是建立在HDFS之上的数据库。 |
HDFS不支持快速单独记录查找。 | HBase提供在较大的表快速查找 |
HDFS提供了高延迟批量处理;没有批处理概念。 | HBase提供了数十亿条记录低延迟访问单个行记录(随机存取)。 |
HDFS提供的数据只能顺序访问。 | HBase内部使用哈希表和提供随机接入,并且其存储索引,可将在HDFS文件中的数据进行快速查找。 |
Hbase—>HashMap
hdfs只是提供存储和副本的作用
HBase相关概念
1.分布式数据库(region)
把数据等分为三个region进行存储,把region进行分片分到不同的副本,读取的时候拼成完整文件读,所以需要记录每个region的开始位置和结束位置
2.列式存储和行式存储
- 行式存储压缩前重复跳过三次名字进行查询id和age,压缩条件是重复率较高的进行压缩,压缩后至跳过一次姓名,所以加快了速度。
- HBase中没有库的概念,只有命名空间的概念
- 每一行都有的唯一标识rowkey
- 默认时间戳为版本号
- 每一列都要有(rowkey:列簇:列名:值)
3.稀疏性(图包含在上图的2,3,4三张表中)
HBase中需要根据行键、列族、列限定符和时间戳来确定一个单元格,因此,可以视为一个“四维坐标”,即[行键, 列族, 列限定符, 时间戳]
4.数据模型
HBase通过表格的模式存储数据,每个表格由列和行组成,其中,每个列又被划分为若干个列族(colnum family),请参考下面的图:
表:HBase的数据同样是用表来组织的,表由行和列组成,列分为若干个列族,行和列的坐标交叉决定了一个单元格。
行:每个表由若干行组成,每个行有一个行键作为这一行的唯一标识。访问表中的行只有三种方式:通过单个行键进行查询、通过一个行键的区间来访问、全表扫描。
列族:一个HBase表被分组成许多“列族”的集合,它是基本的访问控制单元。
列修饰符(列限定符):列族里的数据通过列限定符(或列)来定位
单元格:在HBase表中,通过行、列族和列限定符确定一个“单元格”(cell),单元格中存储的数据没有数据类型,总被视为字节数组byte[]
时间戳:每个单元格都保存着同一份数据的多个版本,这些版本采用时间戳进行索引
4.1.HBase数据模型
HBase将数据存放在带有标签的表中,表由行和列组成,行和列交叉确定一个单元格,单元格有版本号,版本号自动分配,为数据插入该单元格时的时间戳。单元格的内容没有数据类型,所有数据都被视为未解释的字节数组。
表格中每一行有一个行键(也是字节数组,任何形式的数据都可以表示成字符串,比如数据结构进行序列化之后),整个表根据行键的字节序来排序,所有对表的访问必须通过行键。
表中的列又划分为多个列族(column family),同一个列族的所有成员具有相同的前缀,具体的列由列修饰符标识,因此,列族和列修饰符合起来才可以表示某一列,比如:info:format、cotents:image
在创建一个表的时候,列族必须作为模式定义的一部分预先给出,而列族是支持动态扩展的,也就是列族成员可以随后按需加入。物理上,所有的列族成员一起存放在文件系统上,所以实际上说HBase是面向列的数据库,更准确的应该是面向列族,调优和存储都是在列族这个层次上进行的。一般情况下,同一个列族的成员最后具有相同的访问模式和大小特征。
总结起来,HBase表和我们熟知的RDBMS的表很像,不同之处在于:行按行键排序,列划分为列族,单元格有版本号,没有数据类型。
4.2.HBase数据坐标
HBase中需要根据行键、列族、列限定符和时间戳来确定一个单元格(cell),cell中的数据是没有类型的,全部是字节码形式存贮。,因此,可以视为一个“四维坐标”,即[行键, 列族, 列限定符, 时间戳]。
对于上图这样一个HBase表,其数据坐标举例如下:
键 | 值 |
---|---|
[“201505003”, “Info”, “email”, 1174184619081] | “xie@qq.com” |
[“201505003”, “Info”, “email”, 1174184620720] | “you@163.com” |
4.3.HBase区域
HBase自动把表水平划分为区域(Region),每个区域都是有若干连续行构成的,一个区域由所属的表、起始行、终止行(不包括这行)三个要素来表示。
一开始,一个表只有一个区域,但是随着数据的增加,区域逐渐变大,等到它超出设定的阈值大小,就会在某行的边界上进行拆分,分成两个大小基本相同的区域。然后随着数据的再增加,区域就不断的增加,如果超出了单台服务器的容量,就可以把一些区域放到其他节点上去,构成一个集群。也就是说:集群中的每个节点(Region Server)管理整个表的若干个区域。所以,我们说:区域是HBase集群上分布数据的最小单位。
HBase系统架构
1、架构图
2、组件介绍
HBase由三种类型的服务器以主从模式构成:
-
Region Server:负责数据的读写服务,用户通过与Region server交互来实现对数据的访问。(读写,查询操作客户端直接与region Server交互)
-
HBase HMaster:负责Region的分配及数据库的创建和删除等操作。(主节点)
-
ZooKeeper:负责维护集群的状态(某台服务器是否在线,服务器之间数据的同步操作及master的选举等)。
HDFS的DataNode负责存储所有Region Server所管理的数据,即HBase中的所有数据都是以HDFS文件的形式存储的。出于使Region server所管理的数据更加本地化的考虑,Region server是根据DataNode分布的。HBase的数据在写入的时候都存储在本地。但当某一个region被移除或被重新分配的时候,就可能产生数据不在本地的情况。这种情况只有在所谓的compaction之后才能解决。
元数据存储在zooKeeper中
怎么寻找数据? 首先Client与zookeeper建立连接,然后找到元数据的位置,然后找到元数据里需要读取的位置,然后根据region Server中的region找数据。
当memstore写满了会放在blockcache(缓冲队列)中,然后重新生成memsrore存数据,当blockcache达到阈值时,取出来生成对应storefile(与memstore文件大小一样),到达一定阈值时,一定数量的storefile会进行合并,合并成hfile文件(以二进制方式存储),然后把这个二进制流文件交给他的客户端,放到hdfs中,在hdfs中相当于一个block块,也会有副本
Client
包含访问HBase的接口并维护cache来加快对HBase的访问
Zookeeper
保证任何时候,集群中只有一个master
存贮所有Region的寻址入口。
实时监控Region server的上线和下线信息。并实时通知Master
存储HBase的schema和table元数据
Master
为Region server分配region
负责Region server的负载均衡
发现失效的Region server并重新分配其上的region
管理用户对table的增删改操作
(建立心跳机制,监控维护集群健康状态)
RegionServer
Region server维护region,处理对这些region的IO请求
Region server负责切分在运行过程中变得过大的region
HLog(WAL log):
HLog文件就是一个普通的Hadoop Sequence(二进制) File,Sequence File 的Key是 HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和 region名字外,同时还包括sequence number和timestamp,timestamp是” 写入时间”,sequence number的起始值为0,或者是最近一次存入文件系 统sequence number。
HLog SequeceFile的Value是HBase的KeyValue对象,即对应HFile中的 KeyValue
Region
HBase自动把表水平划分成多个区域(region),每个region会保存一个表里面某段连续的数据;每个表一开始只有一个region,随着数据不断插 入表,region不断增大,当增大到一个阀值的时候,region就会等分会两个新的region(裂变);
当table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个Regionserver上。
Memstore 与 storefile
一个region由多个store组成,一个store对应一个CF(列簇)
store包括位于内存中的memstore和位于磁盘的storefile写操作先写入 memstore,当memstore中的数据达到某个阈值,hregionserver会启动 flashcache进程写入storefile,每次写入形成单独的一个storefile
当storefile文件的数量增长到一定阈值后,系统会进行合并(minor、 major compaction),在合并过程中会进行版本合并和删除工作 (majar),形成更大的storefile。
当一个region所有storefile的大小和超过一定阈值后,会把当前的region 分割为两个,并由hmaster分配到相应的regionserver服务器,实现负载均衡。
客户端检索数据,先在memstore找,找不到再找storefile
HRegion是HBase中分布式存储和负载均衡的最小单元。最小单元就表 示不同的HRegion可以分布在不同的HRegion server上。
HRegion由一个或者多个Store组成,每个store保存一个columns family。
每个Strore又由一个memStore和0至多个StoreFile组成。
如图:StoreFile 以HFile格式保存在HDFS上。
3、理解难点(面试题)
1、flush刷新在HDFS上呈现究竟是怎么刷新的呢?? 我们目前刚刚学习的时候,添加数据,都是一条一条的put进去,而我们在put的数据比较少(小于128M)的时候,我们put完去HDFS上并未查看到我们put的文件,这是因为数据
还在内存中,也就是还在memStore中,所以要想在HDFS中查看到,我们必须手动刷新到磁盘中,这是将memStore的数据刷新到StoreFile中去,这样我们在HDFS中就可以查看到了。 2、为什么Hbase不可以使用像Mysql那样进行查询?? 首先,我们应该可以感受到,我们在插入的时候,每行数据,有多少列,列名叫什么完全是我们自己定义的,之所以不支持像MySql那样对列进行查询和操作,因为不确定列的个数和名称。 3、数据最后存在HDFS上的,HDFS不支持删改,为什么Hbase就可以呢?? 这里有个思想误区,的确,数据是以HFile形式存在HDFS上的,而且HDFS的确是不支持删改的,但是为什么Hbase就支持呢?首先,这里的删除并不是真正意义上的对数据进行删除,
而是对数据进行打上标记,我们再去查的时,就不会查到这个打过标记的数据,这个数据Hmaster会每隔1小时清理。修改是put两次,Hbase会取最新的数据,过期数据也是这个方式被清理。
Hbase shell
1.Region信息观察
创建表指定命名空间
在创建表的时候可以选择创建到bigdata19这个namespace中,如何实现呢?
使用这种格式即可:‘命名空间名称:表名’
针对default这个命名空间,在使用的时候可以省略不写
create 'bigdata19:t1','info','level'
此时使用list查看所有的表
如果只想查看bigdata19这个命名空间中的表,如何实现呢?
可以使用命令list_namespace_tables
list_namespace_tables 'n1'
查看region中的某列簇数据
hbase hfile -p -f /hbase/data/default/tbl_user/e0fa1f6553292386591dea9288aa20f6/info/b7bb6a6bc04646d7b3ae73c93c389378
1.查看表的所有region
list_regions '表名'
2.强制将表切分出来一个region
split '表名','行键'
但是在页面(master:50070,/hbase/data/default/users)上可以看到三个:过一会会自动的把原来的删除
2.查看某一行在哪个region中
locate_region '表名','行键'
可以hbase hfile -p -f xxxx 查看一下
2、预分region解决热点问题(面试题)
row设计的一个关键点是查询维度
rowkey三大设计原则:
唯一性
长度不宜过长
散列性
(在建表的时候根据具体的查询业务 设计rowkey 预拆分)
在默认的拆分策略中 ,region的大小达到一定的阈值以后才会进行拆分,并且拆分的region在同一个regionserver中 ,只有达到负载均衡的时机时才会进行region重分配!并且开始如果有大量的数据进行插入操作,那么并发就会集中在单个RS中, 形成热点问题,(问题:什么是热点问题?)所以如果有并发插入的时候尽量避免热点问题 ,应当预划分 Region的rowkeyRange范围 ,在建表的时候就指定预region范围(怎样解决热点问题?)
好处:不同的数据被不同的region管理,不同的region被不同的regionServer管理
查看命令使用(指定4个切割点,就会有5个region)
help 'create'
create 'tb_split','cf',SPLITS => ['e','h','l','r']
list_regions 'tb_split'
添加数据试试
put 'tb_split','c001','cf:name','first' put 'tb_split','f001','cf:name','second' put 'tb_split','z001','cf:name','last'
hbase hfile -p –f xxxx 查看数据
如果没有数据,因为数据还在内存中,需要手动刷新内存到HDFS中,以HFile的形式存储
3、日志查看
演示不启动hdfs 就启动hbase
日志目录: /usr/local/soft/hbase-1.7.1/logs
start-all.sh发现HMaster没启动,hbase shell客户端也可以正常访问
再启动hbase就好了
4、scan进阶使用
查看所有的命名空间
list_namespace
查看某个命名空间下的所有表
list_namespace_tables 'default'
修改命名空间,设置一个属性
alter_namespace 'bigdata19',{METHOD=>'set','author'=>'abc'}
查看命名空间属性
describe_namespace 'bigdata19'
删除一个属性
alter_namespace 'bigdata19',{METHOD=>'unset', NAME=>'author'}
删除一个命名空间
drop_namespace 'bigdata19'
创建一张表
create 'teacher','cf'
添加数据
put 'teacher','tid0001','cf:tid',1 put 'teacher','tid0002','cf:tid',2 put 'teacher','tid0003','cf:tid',3 put 'teacher','tid0004','cf:tid',4 put 'teacher','tid0005','cf:tid',5 put 'teacher','tid0006','cf:tid',6
显示三行数据
scan 'teacher',{LIMIT=>3}
put 'teacher','tid00001','cf:name','abc' scan 'teacher',{LIMIT=>3}
从后查三行
scan 'teacher',{LIMIT=>3,REVERSED=>true}
查看包含指定列的行
scan 'teacher',{LIMIT=>3,COLUMNS=>['cf:name']}
简化写法:
scan 'teacher',LIMIT=>3
在已有的值后面追加值
append 'teacher','tid0006','cf:name','123'
5、get进阶使用
简单使用,获取某一行数据
get 'teacher','tid0001'
获取某一行的某个列簇
get 'teacher','tid0001','cf'
获取某一行的某一列(属性 )
get 'teacher','tid0001','cf:name'
可以新增一个列簇数据测试
查看历史版本
1、修改表可以存储多个版本
alter 'teacher',NAME=>'cf',VERSIONS=>3
2、put四次相同rowkey和列的数据
put 'teacher','tid0001','cf:name','xiao1' put 'teacher','tid0001','cf:name','xiao2' put 'teacher','tid0001','cf:name','xiao3' put 'teacher','tid0001','cf:name','xiao4'
3、查看历史数据,默认是最新的
get 'teacher','tid0001',{COLUMN=>'cf:name',VERSIONS=>2}
修改列簇的过期时间 TTL单位是秒,这个时间是与插入的时间比较,而不是现在开始60s
alter 'teacher',{NAME=>'cf2',TTL=>'60'}
6、插入时间指定时间戳
1641007819000
put 'teacher','tid0007','cf2:job','bigdata19',1654845442790
7、delete(只能删除一个单元格,不能删除列簇)
删除某一列
delete 'teacher','tid0004','cf:tid'
8、deleteall(删除不了某个列簇,但是可以删除多个单元格)
删除一行,如果不指定类簇,删除的是一行中的所有列簇
deleteall 'teacher','tid0006'
删除单元格
deleteall 'teacher','tid0006','cf:name','cf2:job'
9、incr和counter
统计表有多少行(统计的是行键的个数)
count 'teacher'
新建一个自增的一列
incr 'teacher','tid0001','cf:cnt',1
每操作一次,自增1
incr 'teacher','tid0001','cf:cnt',1 incr 'teacher','tid0001','cf:cnt',10 incr 'teacher','tid0001','cf:cnt',100
配合counter取出数据,只能去incr字段
get_counter 'teacher','tid0001','cf:cnt'
10、获取region的分割点,清除数据,快照
获取region的分割点
get_splits 'tb_split'
清除表数据
truncate 'teacher'
拍摄快照
snapshot 'teacher','teacher_20220913'
列出所有快照
list_table_snapshots 'tb_split'
再添加一些数据
put 'tb_split','a001','cf:name','abc'
恢复快照(先禁用)
disable 'tb_split' restore_snapshot 'tb_split_20220610' enable 'tb_split'
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/289663.html