Hbase入门与使用

Hbase是一个分布式数据库,主要用于海量数据的存储和查询。其特点包括列式存储、多版本、扩展性和高性能等。Hbase依赖HDFS,数据存储采用LSM树结构,通过Rowkey进行快速定位。在设计Rowkey时需要注意长度、散列和唯一性原则,以避免热点问题。此外,Hbase的架构包括Master、RegionServer和Zookeeper,安装部署需要JDK、Hadoop和Zookeeper。Hbase Shell提供了DDL和DML操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        Hbase是一个分布式的数据库,它的主要作用为海量数据的存储和海量数据的准实时查询。Hbase的应用也十分广泛,在交通、金融、电商、移动(电话信息)等行业均有涉足。

一、Hbase特点:

1、容量大
        HBase单表可以有上百亿行、百万列,数据矩阵横向和纵向两个维度所支持的数据量级都非常具有弹性。
2、列式存储
        HBase是面向列的存储和权限控制,并支持独立检索。列式存储,即数据在表中是按照某列存储的,这样在只需要查询少数几个字段的时候,能大大减少读取的数据量。
3、多版本
        HBase每一个列的数据存储有多个版本(version)。
4、扩展性
        底层依赖于HDFS。
5、稀疏性
        为空的列并不占用存储空间,表可以设计的非常稀疏。
6、高性能
        底层的LSM数据结构和Rowkey有序排列等架构上的独特设计,使得HBase具有非常高的写入性能。region切分、主键索引和缓存机制使得HBase在海量数据下具备一定的随机读取性能,该性能针对Rowkey的查询能够达到毫秒级别。
7、可靠性
        WAL机制保证了数据写入时不会因集群异常而导致写入数据丢失;Replication机制保证了在集群出现严重的问题时,数据不会发生丢失或损坏。而且HBase底层使用HDFS,HDFS本身也有备份。

!!LSM数据结构:

        LSM树全称是基于日志结构的合并树(Log-Structured Merge-Tree)。No-SQL数据库一般采用LSM树作为数据结构,HBase也不例外。众所周知,RDBMS一般采用B+树作为索引的数据结构,如图1。RDBMS中的B+树一般是3层n路的平衡树。B+树的节点对应于磁盘数据块。因此对于RDBMS,数据更新操作需要5次磁盘操作(从B+树3次找到记录所在数据块,再加上一次读和一次写)。
图1
        在RDBMS中,数据随机无序写在磁盘块中,如果没有B+树,读性能会很低。B+树对于数据读操作能很好地提高性能,但对于数据写,效率不高。对于大型分布式数据系统,B+树还无法与LSM树相抗衡。

        LSM树可以看成n层合并树。在HBase中,它把随机写转换成对memstore和hfile的连续写。图2展示了LSM树数据写的过程。
图2
        数据写(插入,更新):数据首先顺序写如hlog (WAL), 然后写到MemStore, 在MemStore中,数据是一个2层B+树(图2中的C0树)。MemStore满了之后,数据会被刷到storefile (hFile),在storefile中,数据是3层B+树(图2中的C1树),并针对顺序磁盘操作进行优化。
        数据读:首先搜索MemStore,如果不在MemStore中,则到storefile中寻找。
        数据删除:不会去删除磁盘上的数据,而是为数据添加一个删除标记。在随后的major compaction中,被删除的数据和删除标记才会真的被删除。

        LSM数据更新只在内存中操作,没有磁盘访问,因此比B+树要快。对于数据读来说,如果读取的是最近访问过的数据,LSM树能减少磁盘访问,提高性能。

!!Rowkey设计:

        HBase是三维有序存储的,通过rowkey(行键),column key(column family和qualifier)和TimeStamp(时间戳)这个三个维度可以对HBase中的数据进行快速定位。这个三个维度是依照ASCII码表排序的。(比如A排在a前面)

  1. 先rowkey升序排序
  2. rowkey相同则column key升序排序
  3. rowkey、column key相同则timestamp降序排序

        HBase中rowkey可以唯一标识一行记录,在HBase查询的时候,有两种方式:

  1. 通过get方式,指定rowkey获取唯一一条记录
  2. 通过scan方式,设置startRow和stopRow参数进行范围匹配
  3. 全表扫描,即直接扫描整张表中所有行记录

【rowkey长度原则】
        rowkey是一个二进制码流,可以是任意字符串,最大长度64kb,实际应用中一般为10-100bytes,以byte[]形式保存,一般设计成定长。建议越短越好,不要超过16个字节,原因如下:

  1. 数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长,比如超过100字节,1000w行数据,光rowkey就要占用100*1000w=10亿个字节,将近1G数据,这样会极大影响HFile的存储效率;
  2. MemStore将缓存部分数据到内存,如果rowkey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。
  3. 目前操作系统都是64位系统,内存8字节对齐,控制在16个字节,8字节的整数倍利用了操作系统的最佳特性。

【rowkey散列原则】
        如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。
        如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。

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

【rowkey热点问题】
        HBase中的行是按照rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。然而糟糕的rowkey设计是热点的源头。热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region,由于主机无法服务其他region的请求。设计良好的数据访问模式以使集群被充分,均衡的利用。

        为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个。下面是一些常见的避免热点的方法以及它们的优缺点:

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

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

3、反转
        第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。
        反转rowkey的例子:以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题

4、时间戳反转
        一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。

!!region切分:
首先解释一下region的概念:
        region是部分数据,即是所有数据的一个子集。region包括完整的行,所以region是行为单位表的一个子集。
        每个region有三个主要要素:

  1. 它所属于哪张表
  2. 它所包含的的第一行(第一个region 没有首行)
  3. 他所包含的最后一行(末一个region 没有末行)

        初写数据时,此时表只有一个region,随着数据的增多,region开始变大,等到它达到限定的阀值大小时,则把region分裂为两个大小基本相同的region。
        而这个阀值就是storefile的设定大小(参数:hbase.hregion.max.filesize,新版本默认10G)。在第一次分裂region之前,所有加载的数据都放在原始区域的那台服务器上,随着表的变大,region 的个数也会相应的增加,而region是Hbase集群分布数据的最小单位。

【加锁】
        HBase的锁是行锁,无论对行进行访问的事物有多少列,对此行的更新都会是原子操作,即要么成功,要么失败,不会存在部分成功的情况。这就说明,如果只更新一个行1000个列中的一个列,那也会对整行加锁。

【Hbase元数据表】
        HBase内部维护着两个元数据表,分别是-ROOT- 和 .META. 表,他们分别维护着当前集群所有region的列表、状态和位置。
        -ROOT-表包含.META.表的region 列表,因为.META.表可能会因超过region的大小而进行分裂,而-ROOT-表是不会分裂的。所以,-ROOT-保存META.表的region索引,而.META. 表中则包含所有用户region(user-space region)的列表。
        表中的项使用region 名作为键。region名由所属的表名、region的起始行、创建的时间 以及对其整体进行MD5 hash值。比如:
award_week_2013,201311:170100626,1371697714559.f7f37b98c01f68b7b5cc6c1c3734a666
|–表名————-|—–起始行———|–创建时间戳—|—-整体进行MD5 hash 值————|
        由此,表scan的过程中如果加了startrow和endrow的属性后,查找是十分迅速的,即先根据给定rowkey从.META.表中 找到所在的region,然后再从region去查找。
        这个表的值什么时候会变化?——当region 进行split、disable、enable、drop或者 balance 导致region重新分配,或者由于regionserver 挂掉而导致重新分配region时,.META.表的数据会进行及时的更新,这样才能保证根据meta访问到的表是存在的。

!!主键索引:
        RowKey与索引设计,需要紧密结合业务需求场景。索引的设计目标是为HBase提供更多维度的查询能力。在实际应用中应该通过构建尽量少的索引,来满足更多的查询场景。

【影响查询性能的关键因素】

  1. 基于某一个索引/RowKey进行查询时,影响查询的最关键因素在于能否将扫描的候选结果集限定在一个合理的范围内。
  2. 知识点备注:查询驱动条件与查询过滤条件:直接影响数据扫描范围的查询条件,称之为查询驱动条件。而其它的能够起到过滤作用的查询条件,则称之为查询过滤条件。影响查询的关键因素在于如何合理的设置查询驱动条件。

【RowKey字段的选取遵循的最基本原则】

  1. 唯一性: RowKey必须能够唯一的识别一行数据。
  2. 无论应用是什么样的负载特点,RowKey字段都应该参考最高频的查询场景。数据库通常都是以如何高效的读取和消费数据为目的,而不是数据存储本身。
  3. 而后,结合具体的负载特点,再对选取的RowKey字段值进行改造,组合字段场景下需要重点考虑字段的顺序。

!!缓存机制:

        regionserver的缓存包含了memestore和blockcache两种,其中memstore用于写缓存(读缓存也包括),blockcache用于读缓存。regionserver给每一个region都分配一个memstore,数据写入的过程中先写入到memstore,当memstore达到设定的阈值后(由hbase.hregion.memstore.flush.size参数控制),会触发flush操作将数据溢写到磁盘,或者达到heapsize *hbase.regionserver.global.memstore.upperLimit * 0.9时,会强行启动flush进程,从最大的memstore开始flush直到低于限制。
        而每个regionserver只有一个blockcache,读取数据时,首先到memestore上读数据,找不到再到blockcahce上找数据,再查不到则到磁盘查找,并把读入的数据同时放入blockcache。
        blockcache使用的是LRU策略(最近最少使用策略,我觉得应该是LRU-2),当blockcache达到上限时,会触发缓存淘汰机制,将最近很少使用的比较老的数据淘汰掉。当blockcache达到heapsize * hfile.block.cache.size * 0.85时,会启用淘汰机制。

!!WAL机制:
        WAL(Write-Ahead-Log)预写日志是HBase的RegionServer在处理数据插入和删除的过程中用来记录操作内容的一种日志。在每次Put、Delete等一条记录时,首先将其数据写入到RegionServer对应的HLog文件的过程。
        客户端往RegionServer端提交数据的时候,会先写WAL日志,只有当WAL日志写成功以后,客户端才会被告诉提交数据成功,如果写WAL失败会告知客户端提交失败,换句话说这其实是一个数据落地的过程。
        在一个RegionServer上的所有的Region都共享一个HLog,一次数据的提交是先写WAL,写入成功后,再写memstore。当memstore值到达一定是,就会形成一个个StoreFile(理解为HFile格式的封装,本质上还是以HFile的形式存储的)。

        WAL的实现类是HLog,当一个Region被初始化的时候,一个HLog的实例会作为构造函数的参数传进去。
        当Region在处理Put、Delete等更新操作时,可以直接使用该共享的HLog的append方法来落地数据。
        Put、Delete在客户端上可以通过setWriteToWAL(false)方法来关闭该操作的日志,这么做虽然可以提升入库速度,但最好别这么做,因为有数据丢失的风险存在。

!!Replication机制:
        Hbase Replication主从模式通过指定备集群,将Hlog里面的数据异步发送到备集群,对主集群基本没有性能影响,数据延时时间较短。主集群提供读写服务,备集群提供读服务。如果主集群有故障,可以快速切换到备集群。hbase可以通过离线备份和在线备份提供上述的简单备份模式、主从和主主三种备份模式。

        hbase简单备份模式如果表不在线比较好办,可以通过copy table或者是distcp + add table来解决。如果表在线并且不能让其下线,只有通过snapshot方案对online的table实施备份。

        hbase Replication主主模式2个集群互为主备,都提供读写服务,读写分离。

二、Hbase的架构体系和设计模型:

服务架构体系
1、hbase的主要进程:master、regionserver
2、hbase所依赖的两个外部的服务:zookeeper HDFS
设计模型
1、表结构
2、表数据

三、Hbase的安装部署:

Hbase的部署条件
1、JDK1.7以上
2、Hadoop2.5.x以上的版本
3、zookeeper3.4.x以上的版本

四、Hbase shell:

DDL操作
create describe disable enable drop
DML操作
put delete get count scan

以上内容参考博客:
https://blog.youkuaiyun.com/yyl424525/article/details/77505804
https://blog.youkuaiyun.com/yx_keith/article/details/79138974
https://blog.youkuaiyun.com/scgaliguodong123_/article/details/46754195
https://blog.youkuaiyun.com/rlnLo2pNEfx9c/article/details/84207500

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值