Hbase框架详解

发布时间:2024年01月21日

HBASE

1、HBASE介绍

Hbase是bigtable的开源java版本。是建立在Hdfs之上,提供高可靠性、高性能、列存储、可伸缩、实时读写nosql的数据库系统。

HBase中的表一般有这样的特点:

1.大:一个表可以有上十亿行,上百万列

2. 面向列:面向列(族)的存储和权限控制,列(族)独立检索。

3. 稀疏:对于为空(null)的列,并不占用存储空间,因此,表可以设计的非常稀疏。

2、HBASE和HDFS的区别

2.1、HDFS
  • 为分布式存储提供文件系统
  • 针对存储大尺寸的文件进行优化,不需要对HDFS上的文件进行随机读写
  • 直接使用文件
  • 数据模型不灵活
  • 使用文件系统和处理框架
  • 优化一次写入,多次读取的方式
2.2、HBase
  • 提供表状的面向列的数据存储
  • 针对表状数据的随机读写进行优化
  • 使用key-value操作数据
  • 提供灵活的数据模型
  • 使用表状存储,支持MapReduce,依赖HDFS
  • 优化了多次读,以及多次写

3、Redis,传统数据库,HBase,Hive

Redis

分布式缓存,基于内存,强调缓存,支持数据持久化,支持事务操作,NoSQL 类型的Key/vale数据库,同时支持List、Set等更丰富的类型。

Hbase

HBase是建立在HDFS之上,提供高可靠性的列存储,实时读写的数据库系统。它介于Nosql和关系型数据库之间,仅通过主键和主键的range来检索数据,仅支持单行事务。主要用来存储非结构化和半结构化的松散数据。

关系数据库

有mysql、Oracle、SqlServer等,支持事务性操作,属于写模式,即写入数据时进行检查。它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。支持完善的sql功能,可以对少量数据进行统计分析。

Hive

Hive是基于Hadoop的数据仓库工具,可以将结构化数据文件映射为数据库表。并提供sql功能,可以将sql转化为mr任务运行。因为sql学习成本低,不必专门开发mr应用,十分适合数据仓库的统计分析。

区别

关系型数据和Hive都是支持SQL引擎的数据库;Redis和Hbase都是NoSQL 类型的Key/vale数据库,支持简单的行列操作,不支持SQL引擎。

Redis因为存储在内存中所以数据量较小,而Hbase的存储远远超出内存的大小。HBase适合做大数据的持久存储,而Redis比较适合做缓存。RDBMS一般用来做支撑业务系统提供事物或者查询。hive是面相分析的分析型工具,作为海量数据的分析工具。

Hive和HBase是两种基于Hadoop的不同技术:Hive是一种类SQL的引擎,并且运行MapReduce任务,HBase是一种在Hadoop之上的NoSQL 的Key/vale数据库,只支持简单的行列操作。当然,这两种工具是可以同时使用的。Hive可以用来进行统计查询,HBase可以用来进行快速的实时查询,二者可进行整合。

4、HBASE的架构

在这里插入图片描述

4.1、HMaster

功能:

1) 监控RegionServer

2) 处理RegionServer故障转移

3) 处理元数据的变更

4) 处理region的分配或移除

5) 在空闲时间进行数据的负载均衡

6) 通过Zookeeper发布自己的位置给客户端

4.2、RegionServer

功能:

1) 负责存储HBase的实际数据

2) 处理分配给它的Region

3) 刷新缓存到HDFS

4) 维护HLog

5) 执行压缩

6) 负责处理Region分片

5、常用HBASE shell

5.1、进入HBase客户端命令操作界面

$ bin/hbase shell

5.2、查看帮助命令

hbase(main):001:0> help

5.3、查看当前数据库中有哪些表

hbase(main):002:0> list

5.4、创建一张表

创建user表,包含info、data两个列族

hbase(main):010:0> create 'user', 'info', 'data'

或者
hbase(main):010:0> create 'user', {NAME => 'info', VERSIONS => '3'}{NAME => 'data'}
5.5、添加数据操作
  • 向user表中插入信息,row key为rk0001,列族info中添加name列标示符,值为zhangsan

    hbase(main):011:0> put ‘user’, ‘rk0001’, ‘info:name’, ‘zhangsan’

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

    hbase(main):012:0> put ‘user’, ‘rk0001’, ‘info:gender’, ‘female’

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

    hbase(main):013:0> put ‘user’, ‘rk0001’, ‘info:age’, 20

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

    hbase(main):014:0> put ‘user’, ‘rk0001’, ‘data:pic’, ‘picture’

5.6、查询数据操作
5.6.1、通过rowkey进行查询

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

hbase(main):015:0> get ‘user’, ‘rk0001’

5.6.2、查看rowkey下面的某个列族的信息

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

hbase(main):016:0> get ‘user’, ‘rk0001’, ‘info’

5.6.3、查看rowkey指定列族指定字段的值

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

hbase(main):017:0> get ‘user’, ‘rk0001’, ‘info:name’, ‘info:age’

5.6.4、查询所有数据

查询user表中的所有信息

scan ‘user’

5.6.5、列族查询

查询user表中列族为info的信息

scan ‘user’, {COLUMNS => ‘info’}

5.6.6、统计

hbase(main):053:0> count ‘user’

5.6.7.显示所有表

list

6、HBASE表数据模型

在这里插入图片描述

6.1、Row Key

与nosql数据库们一样,row key是用来检索记录的主键。访问hbase table中的行,只有三种方式:

1 通过单个row key访问

2 通过row key的range

3 全表扫描

Row key行键 (Row key)可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。

Hbase会对表中的数据按照rowkey排序(字典顺序)

6.2、列族Column Family

? hbase表中的每个列,都归属与某个列族。列族是表的schema的一部分(而列不是),必须在使用表之前定义。列名都以列族作为前缀。例如courses:history , courses:math 都属于 courses 这个列族。

? 列族越多,在取一行数据时所要参与IO、搜寻的文件就越多,所以,如果没有必要,不要设置太多的列族

6.3、列 Column

? 列族下面的具体列,属于某一个ColumnFamily,类似于我们mysql当中创建的具体的列

6.4、时间戳

? HBase中通过row和columns确定的为一个存贮单元称为cell。每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。

6.5、Cell

由{row key, column( = +

cell中的数据是没有类型的,全部是字节码形式存贮。

7、HBASE读请求过程

在这里插入图片描述

  • HRegionServer保存着meta表以及表数据,要访问表数据,首先Client先去访问zookeeper,从zookeeper里面获取meta表所在的位置信息,即找到这个meta表在哪个HRegionServer上保存着。
  • 接着Client通过刚才获取到的HRegionServer的IP来访问Meta表所在的HRegionServer,从而读取到Meta,进而获取到Meta表中存放的元数据。
  • Client通过元数据中存储的信息,访问对应的HRegionServer,然后扫描所在HRegionServer的Memstore和Storefile来查询数据。
  • 最后HRegionServer把查询到的数据响应给Client。

8、HBASE写请求过程

在这里插入图片描述

  • Client也是先访问zookeeper,找到Meta表,并获取Meta表元数据。确定当前将要写入的数据所对应的HRegion和HRegionServer服务器。

  • Client向该HRegionServer服务器发起写入数据请求,然后HRegionServer收到请求并响应。

  • Client先把数据写入到HLog,以防止数据丢失。然后将数据写入到Memstore。

  • 如果HLog和Memstore均写入成功,则这条数据写入成功

  • 如果Memstore(128M)达到阈值,会把Memstore中的数据flush到Storefile中。

  • 当Storefile(3个)越来越多,会触发Compact合并操作,把过多的Storefile合并成一个大的Storefile。

  • 当Storefile越来越大,Region也会越来越大,达到阈值(10G)后,会触发Split操作,将Region一分为二。

9、hbase的预分区

9.1、预分区有什么用
  • 增加数据读写效率
  • 负载均衡,防止数据倾斜
  • 方便集群容灾调度region
  • 优化Map数量
9.2、如何预分区

? 每一个region维护着startRowkey与endRowKey,如果加入的数据符合某个region维护的rowKey范围,则该数据交给这个region维护。

9.3、设定预分区
  • 手动设定预分区
create 'staff','info','partition1',SPLITS => ['1000','2000','3000','4000']

在这里插入图片描述

  • 使用16进制算法生成预分区
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}


在这里插入图片描述

10、HBASE的rowkey设计

10.1、rowkey设计三原则
  • 长度原则

? Rowkey 是一个二进制码流,Rowkey 的长度被很多开发者建议说设计在 10~100 个字节,不过建议是越短越好,不要超过 16 个字节,存为byte[]字节数组,一般设计成定长的

数据的持久化文件 HFile 中是按照 KeyValue 存储的,如果 Rowkey 过长比如 100 个字 节,1000 万列数据光 Rowkey 就要占用 100*1000 万=10 亿个字节,将近 1G 数据,这会极大 影响 HFile 的存储效率;

  • 散列原则

? 如果 Rowkey 是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将 Rowkey 的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个 Regionserver 实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有 新数据都在一个 RegionServer 上堆积的热点现象,这样在做数据检索的时候负载将会集中 在个别 RegionServer,降低查询效率。

? row key是按照字典序存储,因此,设计row key时,要充分利用这个排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块。

? 举个例子:如果最近写入HBase表中的数据是最可能被访问的,可以考虑将时间戳作为row key的一部分,由于是字典序排序,所以可以使用Long.MAX_VALUE - timestamp作为row key,这样能保证新写入的数据在读取时可以被快速命中。

  • 唯一原则

必须在设计上保证其唯一性。rowkey 是按照字典顺序排序存储的,因此,设计 rowkey 的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问 的数据放到一块。

10.2、热点问题
热点发生在大量的 client 直接访问集群的一个或极少数个节点(访问可能是读, 写或者其他操作)。大量访问会使热点 region 所在的单个机器超出自身承受能力,引起性能 下降甚至 region 不可用,这也会影响同一个 RegionServer 上的其他 region,由于主机无法服 务其他 region 的请求。 设计良好的数据访问模式以使集群被充分,均衡的利用。 为了避免写热点,设计 rowkey 使得不同行在同一个 region,但是在更多数据情况下,数据 应该被写入集群的多个 region,而不是一个。

解决方案:

  • 加盐

? 这里所说的加盐不是密码学中的加盐,而是在 rowkey 的前面增加随机数,具体就是给 rowkey 分配一个随机前缀以使得它和之前的 rowkey 的开头不同。分配的前缀种类数量应该 和你想使用数据分散到不同的 region 的数量一致。加盐之后的 rowkey 就会根据随机生成的 前缀分散到各个 region 上,以避免热点。

原本 rowKey 为 1001 的,SHA1 后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7 

原本 rowKey 为 3001 的,SHA1 后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd 

原本 rowKey 为 5001 的,SHA1 后变成:7b61dec07e02c188790670af43e717f0f46e8913

在做此操作之前,一般我们会选择从数据集中抽取样本,来决定什么样的 rowKey 来 Hash
后作为每个分区的临界值。
  • 哈希

? 哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是 可以预测的。使用确定的哈希可以让客户端重构完整的 rowkey,可以使用 get 操作准确获取 某一个行数据

  • 反转

反转 rowkey 的例子以手机号为 rowkey,可以将手机号反转后的字符串作为 rowkey,这 样的就避免了以手机号那样比较固定开头导致热点问题。

130xxx 155xx 156xx 180x x 189xx

  • 时间戳反转

一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为 rowkey 的一部分对这个问题十分有用,可以用 Long.Max_Value - timestamp 追加到 key 的末尾

文章来源:https://blog.csdn.net/weixin_47120324/article/details/135690282
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。