HBase相关面试题

1.HBase是什么?

1) HBase是一个分布式的基于列式存储的数据库,基于Hadoophdfs存储,zookeeper进行管理。

2) HBase适合存储半结构化或非结构化数据,对于数据结构字段不够确定或者杂乱无章很难按一个概念去抽取的数据。

3) HBasenull的记录不会被存储。

4) 基于的表包含rowkey,时间戳,和列族。新写入数据时,时间戳更新,同时可以查询到以前的版本。

5) HBase是主从架构。hmaster作为主节点,hregionserver作为从节点。

 

2.HBase 的特点是什么?

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

2)无模式:每行都有一个可排序的主键和任意多的列,列可以根据需要动态的增加,同一张表中不同的行可以有截然不同的列;

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

4)稀疏:空(null)列并不占用存储空间,表可以设计的非常稀疏;

5)数据多版本:每个单元中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳;

6)数据类型单一:HBase 中的数据都是字符串,没有类型。

 

3.HBase 和 Hive 的区别?

1)、设计目标和数据存储方式
‌Hive‌:Hive是一个建立在Hadoop之上的数据仓库工具,主要用于简化MapReduce编程。它通过将结构化数据文件映射为数据库表,并提供类SQL查询功能。Hive表是纯逻辑表,不存储数据,完全依赖于HDFS和MapReduce进行数据处理‌。
‌HBase‌:HBase是一个面向列的分布式数据库,设计用于弥补Hadoop在实时操作上的不足。它存储在HDFS上,通过键值对的方式组织数据,适合存储非结构化数据。HBase表是物理表,提供超大的内存Hash表,适合进行实时查询和随机访问‌。
2)、查询性能和适用场景
‌Hive‌:由于Hive依赖于MapReduce进行数据处理,查询性能相对较低,适合批处理和离线分析。Hive不适合实时查询,因为其全表扫描的方式导致查询延迟较高‌。
‌HBase‌:HBase提供实时的数据访问和查询,具有高吞吐量和低延迟的特点,适合实时查询和随机访问。HBase的列存储方式使其在处理大规模非结构化数据时表现出色‌。
3)、具体应用场景
‌Hive‌:适用于需要对结构化数据进行批处理和分析的场景,如趋势分析、日志处理等。Hive不适合实时查询和单行记录操作‌。
‌HBase‌:适用于需要高速查询和随机访问非结构化数据的场景,如实时数据分析、缓存等。HBase支持单行记录的CRUD操作,适用于实时数据处理‌。

 

4.HBase 适用于怎样的情景?

① 半结构化或非结构化数据

② 记录非常稀疏

③ 多版本数据

④ 超大数据量

 

5.描述 HBase 的 rowKey 的设计原则?

Rowkey 长度原则

Rowkey 是一个二进制码流,Rowkey 的长度被很多开发者建议说设计在 10~100 个字节,不过建议是越短越好,不要超过 16 个字节。

原因如下:

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

2MemStore 将缓存部分数据到内存,如果 Rowkey 字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此 Rowkey 的字节长度越短越好。

3)目前操作系统是都是 64 位系统,内存 8 字节对齐。控制在 16 个字节,8 字节的整数倍利用操作系统的最佳特性。

Rowkey 散列原则

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

Rowkey 唯一原则

必须在设计上保证其唯一性。

 

5.描述 HBase 中 scan 和 get 的功能以及实现的异同?

1)、功能
‌Get功能‌:Get操作是用于获取指定RowKey的数据。它通过指定一个具体的行键来读取该行键对应的数据,适用于获取单个行键的数据。Get操作具有较高的精确性,只返回指定行键的数据‌。

get 'table_name', 'my_rowkey'

‌Scan功能‌:Scan操作是用于扫描表中的多个行键,并返回符合指定条件的多行数据。它可以通过设置起始行键和结束行键的范围来扫描一定范围内的行键,适用于获取多个行键的数据。Scan操作可以设置过滤器,进行数据过滤和排序,适用于复杂的查询场景‌。

scan 'table_name', { STARTROW => 'start_row', STOPROW => 'stop_row' }

scan "table_name",FILTER=>"PrefixFilter('1001') AND ValueFilter(=,'substring:159')"

ROW  COLUMN+CELL
1001  column=info:phone, timestamp=1527914569028, value=15962459503
1 row(s) in 0.1010 seconds

2)、实现方式
‌Get实现方式‌:Get方法通过指定RowKey来获取数据,处理方式包括设置ClosestRowBefore和rowlock来保证行的事务性。Get操作返回单个行的详细信息,包括行键和列值‌。
‌Scan实现方式‌:Scan方法通过设置起始行和结束行、时间范围、列族和列限制等参数来实现条件查询。Scan操作返回一个ResultScanner对象,包含从HBase表检索到的Result对象列表,每个Result代表单个行的结果,包含行键和列值。Scan操作可以通过设置缓存大小和批处理大小等参数来优化性能‌。
3)、使用场景
‌Get使用场景‌:Get操作适用于需要获取单个行键数据的场景,如获取某个用户的详细信息等。由于Get操作返回的是单个行的数据,因此在处理大量数据时效率较高‌。
‌Scan使用场景‌:Scan操作适用于需要获取多个行键数据的场景,如查询某个时间范围内的用户活动记录等。Scan操作可以通过设置过滤器进行复杂查询,适用于需要处理大量数据且查询条件复杂的场景‌。

 

7.请详细描述 HBase 中一个 cell 的结构?

HBase Cell是HBase中存储数据的基本单元,每个Cell都包含三个部分:键(Row key)、值(Value)和时间戳(Timestamp)。在HBase中,所有的数据都被存储为Cell的形式,并通过键值对的形式进行索引。
(1)、键(Row key):Cell的唯一标识,用于索引和查找数据。在HBase中,所有的数据都通过Row key进行组织和管理。
(2)、值(Value):Cell的实际数据内容,可以是任意形式的二进制数据。
(3)、时间戳(Timestamp):记录Cell数据变更的时间戳,用于版本控制和数据恢复。

HBase 中通过 row 和 columns 确定的为一个存贮单元称为 cell。

Cell:由{row key, column(=<family> + <label>), version}唯一确定的单元。cell 中的数据是没有类型的,全部是字节码形式存储。

 

8.简述 HBase 中 compact 用途是什么,什么时候触发,分为哪两种,有什么区别,有哪些相关配置参数?(☆☆☆☆☆)

HBase 中每当有 memstore 数据 flush 到磁盘之后,就形成一个 storefile,当 storeFile的数量达到一定程度后,就需要将 storefile 文件来进行 compaction 操作。

Compact 的作用:

① 合并文件

② 清除过期,多余版本的数据

③ 提高读写数据的效率

HBase 中实现了两种 compaction 的方式:minor and major. 这两种 compaction 方式的区别是:

1)Minor 操作只用来做部分文件的合并操作以及包括 minVersion=0 并且设置 ttl 的过期版本清理,不做任何删除数据、多版本数据的清理工作。

2)Major 操作是对 Region 下的 HStore 下的所有 StoreFile 执行合并操作,最终的结果是整理合并出一个文件。

 

9.HBase 优化?

1)高可用

HBase Hmaster 负责监控 RegionServer 的生命周期,均衡 RegionServer 的负载,如果 Hmaster 挂掉了,那么整个 HBase 集群将陷入不健康的状态,并且此时的工作状态并不会维持太久。所以 HBase 支持对 Hmaster 的高可用配置。

核心:避免单点故障。 Master: 保证Master不会单点故障; RegionServer: 多个。

1.关闭HBase集群(如果没有开启则跳过此步)
[hadoop@hadoop102 HBase]$ bin/stop-HBase.sh

2.在conf目录下创建backup-masters文件
[hadoop@hadoop102 HBase]$ touch conf/backup-masters

3.在backup-masters文件中配置高可用HMaster节点
[hadoop@hadoop102 HBase]$ echo hadoop103 > conf/backup-masters

4.将整个conf目录scp到其他节点
[hadoop@hadoop102 HBase]$ scp -r conf/ hadoop103:/opt/module/HBase/

[hadoop@hadoop102 HBase]$ scp -r conf/ hadoop104:/opt/module/HBase/

5.打开页面测试查看
http://hadooo102:16010

 

2)预分区

每一个 region 维护着 startRowKey endRowKey,如果加入的数据符合某个 region 维护的rowKey 范围,则该数据交给这个 region 维护。那么依照这个原则,我们可以将数据所要投放的分区提前大致的规划好,以提高 HBase 性能。

Region会自动切分的,切分Region的目的是为了负载均衡! 但是因为切分时,只会将region中的rowkey排序后,按照中间的rowkey进行切分,切分后有可能依然无法达到负载均衡!
解决: 使用预分区!预分区指在建表时提前分区!

(1).手动设定预分区
HBase> create 'staff1','info','partition1',SPLITS => ['1000','2000','3000','4000']

(2).生成16进制序列预分区
create 'staff2','info','partition2',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}

(3).按照文件中设置的规则预分区
创建splits.txt文件内容如下:
aaaa
bbbb
cccc
dddd

然后执行:
create 'staff3','partition3',SPLITS_FILE => 'splits.txt'

(4).使用JavaAPI创建预分区
//自定义算法,产生一系列Hash散列值存储在二维数组中
byte[][] splitKeys = 某个散列值函数
//创建HBaseAdmin实例
HBaseAdmin hAdmin = new HBaseAdmin(HBaseConfiguration.create());
//创建HTableDescriptor实例
HTableDescriptor tableDesc = new HTableDescriptor(tableName);
//通过HTableDescriptor实例和散列值二维数组创建带有预分区的HBase表
hAdmin.createTable(tableDesc, splitKeys);

 

3RowKey 设计

一条数据的唯一标识就是 rowkey,那么这条数据存储于哪个分区,取决于 rowkey 处于哪一个预分区的区间内,设计 rowkey 的主要目的 ,就是让数据均匀的分布于所有的 region中,在一定程度上防止数据倾斜。

1). Rowkey是一行的唯一标识!Rowkey的最大长度是64K,一般设计10-100个byte。
不能太长,太长会带来大量的存储冗余!
列族也不能太长,一般情况下,列族只取一个字符!

2). 数据在flush时,会按照rowkey进行排序!rowkey相同的数据,会被flush到同一个文件中!
在HFile文件增多时,会有compact,在compact时,读取的所有的文件的rowkey会继续排序,rowkey相同的数据会被聚合到一个HFile中!

3). RowKey设计需要考虑到读操作和写操作两种不同的需求情况!
读操作: 希望读取的数据,尽量在一个region中,在扫描时,只需要向当前region的regionserver发请求!rowkey的前缀都一致即可!
写操作: 在高并发写入时,吞吐量要上去!​ 必须将一批数据的rowkey进行离散化(对rowkey进行处理,处理后,他们可以分散到多个region!)!

 接下来我们就谈一谈 rowkey 常用的设计方案。

(1).生成随机数、hash、散列值
原本rowKey为1001的,SHA1后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
原本rowKey为3001的,SHA1后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd
原本rowKey为5001的,SHA1后变成:7b61dec07e02c188790670af43e717f0f46e8913
在做此操作之前,一般我们会选择从数据集中抽取样本,来决定什么样的rowKey来Hash后作为每个分区的临界值。

(2).字符串反转
20170524000001转成10000042507102
20170524000002转成20000042507102
这样也可以在一定程度上散列逐步put进来的数据。

(3).字符串拼接
20170524000001_a12e
20170524000001_93i7

 

4内存优化

HBase 操作过程中需要大量的内存开销,毕竟 Table 是可以缓存在内存中的,一般会分配整个可用内存的 70%HBase Java 堆。但是不建议分配非常大的堆内存,因为 GC 过程持续太久会导致 RegionServer 处于长期不可用状态,一般 16~48G 内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。

经验值:HMaster 使用 4G 内存
RegionServer,每100T的数据,分配12-16G内存!

 

5)基础优化

(1).允许在HDFS的文件中追加内容
hdfs-site.xml、HBase-site.xml
属性:dfs.support.append
解释:开启HDFS追加同步,可以优秀的配合HBase的数据同步和持久化。默认值为true。
Hbase3.XX以上版本已经默认为true

(2).优化DataNode允许的最大文件打开数
hdfs-site.xml
属性:dfs.datanode.max.transfer.threads
解释:HBase一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为4096或者更高。默认值:4096
一般不用修改

(3).优化延迟高的数据操作的等待时间
hdfs-site.xml
属性:dfs.image.transfer.timeout
解释:如果对于某一次数据操作来讲,延迟非常高,socket需要等待更长的时间,建议把该值设置为更大的值(默认60000毫秒),以确保socket不会被timeout掉。

(4).优化数据的写入效率
mapred-site.xml
属性:
mapreduce.map.output.compress
mapreduce.map.output.compress.codec
解释:开启这两个数据可以大大提高文件的写入效率,减少写入时间。第一个属性值修改为true,第二个属性值修改为:org.apache.hadoop.io.compress.GzipCodec或者其他压缩方式。
还可以通过建表时指定压缩方式。

(5).设置RPC监听数量
HBase-site.xml
属性:HBase.regionserver.handler.count
解释:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。

(6).优化HStore文件大小
HBase-site.xml
属性:HBase.hregion.max.filesize
解释:默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile。

(7).优化HBase客户端缓存
HBase-site.xml
属性:HBase.client.write.buffer
解释:用于指定HBase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。

(8).指定scan.next扫描HBase所获取的行数
HBase-site.xml
属性:HBase.client.scanner.caching
解释:用于指定scan.next方法获取的默认行数,值越大,消耗内存越大。

(9).flush、compact、split机制
当MemStore达到阈值,将Memstore中的数据Flush进Storefile;compact机制则是把flush出来的小文件合并成大的Storefile文件。split则是当Region达到阈值,会把过大的Region一分为二。

涉及属性:
即:128M就是Memstore的默认阈值
HBase.hregion.memstore.flush.size:134217728
即:这个参数的作用是当单个HRegion内所有的Memstore大小总和超过指定值时,flush该HRegion的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模型来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM。

HBase.regionserver.global.memstore.upperLimit:0.4
HBase.regionserver.global.memstore.lowerLimit:0.38
即:当MemStore使用内存总量达到HBase.regionserver.global.memstore.upperLimit指定值时,将会有多个MemStores flush到文件中,MemStore flush 顺序是按照大小降序执行的,直到刷新到MemStore使用内存略小于lowerLimit

 

10.Region 如何预建分区?

预分区的目的主要是在创建表的时候指定分区数,提前规划表有多个分区,以及每个分区的区间范围,这样在存储的时候 rowkey 按照分区的区间存储,可以避免 region 热点问题。

通常有两种方案:

方案 1:shell 方法

create 'tb_splits', {NAME => 'cf',VERSIONS=> 3},{SPLITS => ['10','20','30']}

方案 2: JAVA 程序控制

(1).取样,先随机生成一定数量的 rowkey,将取样数据按升序排序放到一个集合里;

(2).根据预分区的 region 个数,对整个集合平均分割,即是相关的 splitKeys

(3).HBaseAdmin.createTable(HTableDescriptor tableDescriptor,byte[][]splitkeys)可以指定预分区的 splitKey,即是指定 region 间的 rowkey 临界值。

 

11.HRegionServer 宕机如何处理?

1ZooKeeper 会监控 HRegionServer 的上下线情况,当 ZK 发现某个 HRegionServer 宕机之后会通知 HMaster 进行失效备援;

2)该 HRegionServer 会停止对外提供服务,就是它所负责的 region 暂时停止对外提供服务;

3HMaster 会将该 HRegionServer 所负责的 region 转移到其他 HRegionServer 上,并且会对 HRegionServer 上存在 memstore 中还未持久化到磁盘中的数据进行恢复;

4)这个恢复的工作是由 WAL 重播来完成,这个过程如下:

· wal 实际上就是一个文件,存在/HBase/WAL/对应 RegionServer 路径下。

· 宕机发生时,读取该 RegionServer 所对应的路径下的 wal 文件,然后根据不同的region 切分成不同的临时文件 recover.edits

· 当 region 被分配到新的 RegionServer 中,RegionServer 读取 region 时会进行是否存在 recover.edits,如果有则进行恢复。

 

12.HBase 读写流程?(☆☆☆☆☆) 

读流程:

HRegionServer 保存着 meta 表以及表数据,要访问表数据,首先 Client 先去访问zookeeper,从 zookeeper 里面获取 meta 表所在的位置信息,即找到这个 meta 表在哪个HRegionServer 上保存着。

② 接着 Client 通过刚才获取到的 HRegionServer IP 来访问 Meta 表所在的HRegionServer,从而读取到 Meta,进而获取到 Meta 表中存放的元数据。

Client 通过元数据中存储的信息,访问对应的 HRegionServer,然后扫描所在HRegionServer Memstore Storefile 来查询数据。

④ 最后 HRegionServer 把查询到的数据响应给 Client

 

写流程:

Client 先访问 zookeeper,找到 Meta 表,并获取 Meta 表元数据。

② 确定当前将要写入的数据所对应的 HRegion HRegionServer 服务器。

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

Client 先把数据写入到 HLog,以防止数据丢失。

⑤ 然后将数据写入到 Memstore

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

⑦ 如果 Memstore 达到阈值,会把 Memstore 中的数据 flush Storefile 中。

⑧ 当 Storefile 越来越多,会触发 Compact 合并操作,把过多的 Storefile 合并成一个大的 Storefile

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

 

13.HBase 内部机制是什么?

HBase 是一个能适应联机业务的数据库系统物理存储:HBase 的持久化数据是将数据存储在 HDFS 上。

存储管理:一个表是划分为很多 region 的,这些 region 分布式地存放在很多 regionserverRegion 内部还可以划分为 storestore 内部有 memstore storefile

版本管理:HBase 中的数据更新本质上是不断追加新的版本,通过 compact 操作来做版本间的文件合并 Region split

集群管理:ZooKeeper + HMaster + HRegionServer

 

14.HBase 在进行模型设计时重点在什么地方?一张表中定义多少个 Column Family 最合适?为什么?

Column Family 的个数具体看表的数据,一般来说划分标准是根据数据访问频度,如一张表里有些列访问相对频繁,而另一些列访问很少,这时可以把这张表划分成两个列族,分开存储,提高访问效率。

 

15.如何提高 HBase 客户端的读写性能?请举例说明(☆☆☆☆☆)

(1). 开启 bloomfilter 过滤器,开启 bloomfilter 比没开启要快 34

create 'example table',{NAME =>'Cf',BLOOMFILTER =>'ROW'}

(2). HBase 对于内存有特别的需求,在硬件允许的情况下配足够多的内存给它

通过修改 HBase-env.sh 中的 export HBASE_HEAPSIZE=3000   #这里默认为 1000m

(3). 增大 RPC 数量

通过修改 HBase-site.xml 中的 HBase.regionserver.handler.count 属性,可以适当的放大RPC 数量,默认值为 10 有点小。

 

16.直接将时间戳作为行健,在写入单个 region 时候会发生热点问题,为什么呢?(☆☆☆☆☆)

region 中的 rowkey 是有序存储,若时间比较集中。就会存储到一个 region 中,这样一个 region 的数据变多,其它的 region 数据很少,加载数据就会很慢,直到 region 分裂,此问题才会得到缓解。

 

17.请描述如何解决 HBase 中 region 太小和 region 太大带来的冲突?

(1).Region 过大会发生多次compaction,将数据读一遍并重写一遍到 hdfs 上,占用io;

(2).Region过小会造成多次 split,Region 会下线,影响访问服务,最佳的解决方法是调整 HBase.hregion.max.filesize 256m

 

18.解释一下布隆过滤器原理(☆☆☆☆☆)? 

(1)、什么是布隆过滤器
本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构,特点是高效地插入和查询。根据查询结果可以用来告诉你 某样东西一定不存在或者可能存在 这句话是该算法的核心。
相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的,同时布隆过滤器还有一个缺陷就是数据只能插入不能删除。

(2)、数据如何存入布隆过滤器

布隆过滤器的基本原理是通过一个位(bit)数组和多个哈希函数来实现的。具体步骤如下:
‌(1).初始化‌:创建一个长度为m的位数组,所有位初始化为0。
‌‌(2).插入操作‌:对于集合中的每个元素,使用k个哈希函数将其映射到位数组的k个位置上,并将这些位置的值设为1。
‌‌(3).查询操作‌:对于要查询的元素,同样使用这k个哈希函数进行映射,检查位数组中对应的k个位置是否都为1。如果所有位置都为1,则元素可能存在于集合中;如果有任何一个位置为0,则元素一定不在集合中‌。

(3)、布隆过滤器为什么会有误判
当插入的元素越来越多时,当一个不在布隆过滤器中的元素,经过同样规则的哈希计算之后,得到的值在位数组中查询,有可能这些位置因为其他的元素先被置1了。
所以布隆过滤器存在误判的情况,但是如果布隆过滤器判断某个元素不在布隆过滤器中,那么这个值就一定不在。

 (4)、使用布隆过滤器的场景和效果 

在HBase中,布隆过滤器主要用于减少对HFile数据块的访问次数,从而提高查询效率。当查询一个行时,首先通过布隆过滤器判断该行是否在某个数据块中。如果布隆过滤器指示该行不在当前数据块,则可以避免不必要的IO操作,减少系统负载。然而,布隆过滤器的使用会增加一定的存储开销,因为需要存储额外的位数组信息‌。
综上所述,HBase中的布隆过滤器通过牺牲一定的误判率来换取查询效率的提升,适用于大数据场景下的快速数据存在性判断。

posted @ 2023-02-09 23:30  业余砖家  阅读(174)  评论(0)    收藏  举报