本文《尼恩 大数据 面试宝典》 是 《尼恩Java面试宝典》姊妹篇。
这里特别说明一下:《尼恩Java面试宝典》41个专题 PDF 自首次发布以来, 已经汇集了 好几千题,大量的大厂面试干货、正货 ,足足4800多页,帮助很多小伙伴进了大厂,拿了高薪。
《尼恩Java面试宝典》面试题集合, 已经变成Java 学习和面试的必读书籍。
于是,尼恩架构团队 趁热打铁,推出 《尼恩 大数据 面试宝典》,已经发布了几个专题:
《尼恩大数据面试宝典专题1:史上最全Hadoop面试题》
《尼恩大数据面试宝典专题2:绝密100个Spark面试题,熟背100遍,猛拿高薪》
《尼恩大数据面试宝典专题3:史上最全Hive面试题,不断迭代,持续升级》
《尼恩大数据面试宝典专题4:史上最全Flink面试题,不断迭代,持续升级》
《尼恩大数据面试宝典专题5:史上最全HBase面试题,不断迭代,持续升级》(本文)
《尼恩 大数据 面试宝典》 后面会不断升级,不断 迭代, 变成 大数据领域 学习和面试的必读书籍,帮助大家成长为 三栖合一架构师,进了大厂,拿了高薪。
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到公号【技术自由圈】取
一作:Mark, 资深大数据架构师、Java架构师,近20年Java、大数据架构和开发经验。资深架构导师,成功指导了多个中级Java、高级Java转型架构师岗位。
二作:尼恩,41岁资深老架构师, IT领域资深作家、著名博主。《Java 高并发核心编程 加强版 卷1、卷2、卷3》创世作者。 《K8S学习圣经》《Docker学习圣经》《Go学习圣经》等11个PDF 圣经的作者。 也是一个 资深架构导师、架构转化 导师, 成功指导了多个中级Java、高级Java转型架构师岗位, 最高的学员年薪拿到近100W。
HBase 是一个分布式、可扩展、高性能的列式存储系统,它基于 Google 的 Bigtable 设计。HBase 的主要存储结构包括表(Table)、区域(Region)、列族(Column Family)、列(Column)和值(Value)。
HBase 的存储结构还包括以下组件:
总之,HBase 的存储结构由表、区域、列族、列和值组成,这些组件通过 HRegionServer、HMaster 和 Store 等组件进行管理。这种结构使得 HBase 具有高性能、可扩展性和高可用性,能够轻松地处理海量数据。
HBase采用Master/Slave架构搭建集群,它隶属于Hadoop生态系统,由一下类型节点组成: HMaster 节点、HRegionServer 节点、 ZooKeeper 集群,而在底层,它将数据存储于HDFS中,因而涉及到HDFS的NameNode、DataNode等,总体结构如下:
各组件说明:
Client:
访问数据的入口,包含访问HBase的API接口,维护着一些cache来加快对HBase的访问
使用HBase RPC机制与HMaster和HRegionServer进行通信;
Client与HMaster进行通信进行管理类操作;
Client与HRegionServer进行数据读写类操作;
HMaster:NAMENODE RESOURCEMANAGER
HMaster 没有单点问题,HBase中可以启动多个HMaster,通过Zookeeper保证总有一个Master在运行。
HMaster主要负责Table和Region的管理工作:
管理用户对表的增删改查操作;
管理HRegionServer的负载均衡,调整Region分布;
Region Split后,负责新Region的分布;
在HRegionServer停机后,负责失效HRegionServer上Region 的迁移;
HRegionServer:DATANODE NODEMANAGER
HBase中最核心的模块;
维护region,处理对这些region的IO请求;
Regionserver负责切分在运行过程中变得过大的region;
Zookeeper:
zookeeper的选举机制保证任何时候,集群中只有一个master
实时监控Region Server的状态,将Region server的上线和下线信息实时通知给Master
存储HBase的schema
存贮所有Region的寻址入口
海量存储:可以存储大批量的数据。
列(簇)式存储:HBase表的数据是基于列族进行存储的,列族是在列的方向上的划分。
极易扩展:底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加 datanode节点服务(机器)就可以了;可以通过增加服务器来提高集群的存储能力。
高并发:支持高并发的读写请求。
稀疏:稀疏主要是针对HBase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间的。
数据的多版本:HBase表中的数据可以有多个版本值,默认情况下是根据版本号去区分,版本号就是插入数据的时间戳。
数据类型单一:所有的数据在HBase中是以字节数组进行存储。
HBase | Hive | |
---|---|---|
类型 | 列式数据库 | 数据仓库 |
内部机制 | 数据库引擎 | MapReduce |
增删改查 | 都支持 | 只支持导入和查询 |
Schema | 只需要预先定义列族,不需要具体到列列可以动态修改 | 需要预先定义表格 |
应用场景 | 实时 | 离线处理 |
特点 | 以K-V形式存储 | 类SQL |
Hive是一种类SQL的引擎,并且运行MapReduce任务,HBase是一种在Hadoop之上的NoSQL 的Key/vale数据库。
HBase运行在hdfs上,和hive不一样,HBase能够在数据库上实时运行,而不是运行MapReduce任务。
应用场景
Hive适合用来对一段时间内的数据进行分析查询,例如,用来计算趋势或者网站的日志。Hive不应该用来进行实时的查询。因为它需要很长时间才可以返回结果。
HBase非常适合用来进行大数据的实时查询。
首先一点需要明白:Hbase是基于HDFS来存储的。
主要原因是由其架构和底层的数据结构决定的,即由LSM-Tree(Log-Structured Merge-Tree)+HTable(region分区)+Cache决定。
客户端可以直接定位到要查数据所在的Hregion-server服务器,然后直接在服务器的一个region上查找要匹配的数据,并且这些数据部分是经过cache缓存的。
HBase会将数据保存到内存中,在内存中的数据是有序的,如果内存空间满了,会刷写到HFile中,而在HFile中保存的内容也是有序的。当数据写入HFile后,内存中的数据会被丢弃.HFile文件为磁盘顺序读取做了优化。
HBase的写入速度快是因为他其实并不是真的立即写入文件中,而是先写入内存,随后异步刷入HFile。所以在客户端看来,写入数据速度很快。另外,写入时候随机写入转换成顺序写,数据写入速度也很稳定。读取速度很快是因为他使用了LSM树形结构,而不是B或B+树。 磁盘顺序读取速度很快,但是相比而言,寻找磁道的速度就要慢很多。HBase的存储结构导致他需要磁盘寻道时间在可预测范围内,并且读取与所要查询的rowkey连续的任意数量的记录都不会引发额外的寻道开销。比如有五个存储文件,那么最多需要5次磁盘寻道就可以。而关系型数据库,即使有索引,也无法确定磁盘寻道次数。而且,HBase读取首先会在缓存(BlockCache)中查找,它采用了LRU(最近最少使用算法),如果缓存中没找到,会从内存中的MemStore中查找,只有这两个地方都找不到时,才会加载HFile中的内容。
如果是rowkey按照时间戳或者是顺序递增
那么将会产生热点现象 建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率
RowKey的长度不宜过长,不宜超过16个字节,最大长度64kb,实际应用中一般为10-100bytes,以byte[]形式保存。一条数据是根据rowkey来当成索引的,如果过长就会快速占据memstore的128M,然后被刷写到磁盘,也就是说相同的空间存贮的内容被rowkey占据了一大部分,减少了主要内容的存贮。
必须在设计上保证其唯一性, rowkey可以锁定唯一的一行数据,rowkey重复的话后put的数据会覆盖前面插入的数据
HBase的查询实现只提供两种方式:
1.按指定RowKey 获取唯一一条记录,get方法(org.apache.hadoop.HBase.client.Get)Get 的方法处理分两种 : 设置了ClosestRowBefore 和没有设置的rowlock .主要是用来保证行的事务性,即每个get 是以一个row 来标记的.一个row中可以有很多family 和column.
2.按指定的条件获取一批记录,scan方法(org.apache.Hadoop.HBase.client.Scan)实现条件查询功能使用的就是scan 方式.
1)scan 可以通过setCaching 与setBatch 方法提高速度(以空间换时间);
2)scan 可以通过setStartRow 与setEndRow 来限定范围([start,end)start 是闭区间,end 是开区间)。范围越小,性能越高。
3)scan 可以通过setFilter 方法添加过滤器,这也是分页、多条件查询的基础。
HBase中的Cell表示的是表中的单元格,由{rowkey, column Family:columu, version} 唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存贮。其中 version 就是这个单元格中的 Time Stamp。
在 HBase 中,一个 cell 的结构由以下三个部分组成:
version:version 是 cell 的时间戳,用于记录 cell 的创建时间或修改时间。在 HBase 中,每个 cell 都有一个唯一的时间戳,用于唯一确定该 cell 的版本。
数据:data 是 cell 中存储的数据,数据类型可以是任何字节码形式。在 HBase 中,数据是以字节码形式存储的,而不是特定的数据类型。这种存储方式使得 HBase 可以存储任何类型的数据,例如文本、图片、音频等。
值:value 是 cell 中存储的实际数据值。在 HBase 中,值是由字节码形式存储的,而不是特定的数据类型。这种存储方式使得 HBase 可以存储任何类型的数据,例如文本、图片、音频等。
HBase 中的 cell 是表中的基本存储单元,由 rowkey、column family、column 和 version 唯一确定。cell 中的数据是以字节码形式存储的,可以是任何类型的数据。
在 HBase 中,分布式存储的最小单元是 Region。每个 Region 都是一个独立的存储单元,包含一个或多个 StoreFile。Region 是 HBase 中数据存储和访问的基本单位,也是 HBase 中分布式存储和负载均衡的基础。
然而,Region 并不是存储的最小单元。在 HBase 中,存储的最小单元是 StoreFile。StoreFile 是 HBase 中的数据存储文件,每个 StoreFile 都包含一个或多个列族的数据。StoreFile 的大小通常由
HBase.hstore.compactionThreshold 和 HBase.hstore.blockingStoreFiles 参数控制。当一个 StoreFile 的大小达到 compactionThreshold 时,HBase 会自动将其 compact 成一个更大的 StoreFile。当一个 StoreFile 的大小超过 blockingStoreFiles 参数设定的值时,HBase 会将其拆分成多个更小的 StoreFile。
因此,虽然 Region 是分布式存储的最小单元,但 StoreFile 才是 HBase 中存储的最小单元。
在 HBase 中,region 太小和 region 太大都可能导致性能问题和数据丢失。
下面是一些解决这些问题的方法:
hbase regionsplit --region=region_name
hbase create_table -p 预分区_参数
其中,预分区参数指定了要创建的 region 数量。
通过调整 HBase.hregion.max.filesize 和 HBase.hregion.min.size 参数、使用 RegionSplitter 工具和预分区方法,可以有效地解决 HBase 中 region 太小和 region 太大带来的冲突。
在 HBase 中,compact 用于合并多个 storefile,从而减少磁盘上的文件数量,提高查询效率。Compact 操作会清理过期数据和删除标记,从而避免数据丢失和磁盘空间浪费。
Compact 的作用:
ompact 的触发条件是当 storefile 的大小达到一定程度时,HBase 系统会自动触发 compaction 操作。这个大小的阈值可以通过配置参数来设置,例如通过修改 hbase.hstore.compactionThreshold 和 hbase.hstore.compaction.max 参数来调整。
HBase 中实现了两种compaction 的方式:minor 和 major。
Minor compaction 主要用于合并多个 storefile,并对数据进行版本合并和删除标记清理。
Major compaction 则是对整个 Region 的所有 storefile 进行合并,最终生成一个更大的 storefile。
Minor compaction 和 major compaction 的区别在于合并的范围和执行的频率。
在 HBase 中,compact 相关的配置参数主要包括:
此外,还可以通过调整 HBase 的其他参数来优化 compaction 操作,例如调整 memstore.size.上限、刷新和 Compaction 策略等。
百亿数据:证明数据量非常大;
存入HBase:证明是跟HBase的写入数据有关;
保证数据的正确:要设计正确的数据结构保证正确性;
在规定时间内完成:对存入速度是有要求的。
数据量百亿条,什么概念呢?假设一整天60x60x24 = 86400秒都在写入数据,那么每秒的
写入条数高达100万条,HBase当然是支持不了每秒百万条数据的,所以这百亿条数据可能不是通
过实时地写入,而是批量地导入。批量导入推荐使用BulkLoad方式(推荐阅读:Spark之读写HBase),性能是普通写入方式几倍以上;
存入HBase:普通写入是用JavaAPI put来实现,批量导入推荐使用BulkLoad;
保证数据的正确:这里需要考虑RowKey的设计、预建分区和列族设计等问题;
在规定时间内完成也就是存入速度不能过慢,并且当然是越快越好,使用BulkLoad。
HBase默认建表时有一个region。这个region的rowkey是没有边界的,即没有startkey和endkey,在数据写入时,所有数据都会写入这个默认的region,随着数据的不断增加,此region已经不能承受不断增长的数据量,会进行split,分成2个region.。在此过程中,会产生两个问题:
基于此我们可以控制在建表的时候,创建多个空region,并确定每个region的起始和终止rowkey,这样只要我们的rowkey设计能均匀的命中各个region,就不会存在写热点问题。自然split的几率也会大大降低。当然随着数量的不断增长,该split的还是要进行split。像这样预先创建HBase表分区的方式,称之为预分区
创建预分区可以通过shell或者java代码实现
#以下是shell方式
#指明分割点
create 't1','f1',SPLITS=>['10','20','30','40']
#HexStringSplit指明分割策略,-c 10 指明要分割的区域数量,-f指明表中的列族,用":"分割
HBase org.apache.hadoop.HBase.util.RegionSpliter test_table HexStringSplit -c 10 -f f1
#根据文件创建分区并压缩
create 'split_table_test',{NAME => 'cf',COMPRESSION => 'SNAPPY'},{SPLITS_FILE => 'region_split_info.txt'}
ZooKeeper 会监控 HRegionServer 的上下线情况,当 ZK 发现某个 HRegionServer 宕机之后会通知 HMaster 进行失效备援;
该 HRegionServer 会停止对外提供服务,就是它所负责的 region 暂时停止对外提供服务;
HMaster 会将该 HRegionServer 所负责的 region 转移到其他 HRegionServer 上,并且会对 HRegionServer 上存在 memstore 中还未持久化到磁盘中的数据进行恢复;
这个恢复的工作是由 WAL 重播来完成,这个过程如下:
wal 实际上就是一个文件,存在/HBase/WAL/对应 RegionServer 路径下。
宕机发生时,读取该 RegionServer 所对应的路径下的 wal 文件,然后根据不同的region 切分成不同的临时文件 recover.edits。
当 region 被分配到新的 RegionServer 中,RegionServer 读取 region 时会进行是否存在 recover.edits,如果有则进行恢复。
start-HBase.sh 的流程如下:
1)装载相关配置,如HBase_HOME目录,conf目录,regionserver机器列表,JAVA_HOME 目录等,它会调用$HBase_HOME/conf/HBase-env.sh
2)解析参数(0.96 版本及以后才可以带唯一参数 autorestart,作用就是重启)
3)调用 HBase-daemon.sh 来启动 master
4)调用 HBase-daemons.sh 来启动 regionserver zookeeper master-backup
HBase-env.sh 的作用:主要是配置 JVM 及其 GC 参数,还可以配置 log 目录及参数,配置是否需要 HBase 管理 ZK,配置进程 id 目录等
HBase-daemons.sh 的作用:根据需要启动的进程,如 zookeeper,则调用 zookeepers.sh如 regionserver,则调用 regionservers.sh如 master-backup,则调用 master-backup.sh
zookeepers.sh 的作用:如果 HBase-env.sh 中的 HBase_MANAGES_ZK"=“true”,那么通过ZKServerTool这个类解析xml配置文件,获取 ZK 节点列表,然后通过 SSH 向这些节点发送远程命令执行。
regionservers.sh 的作用:与 zookeepers.sh 类似,通过配置文件,获取 regionserver 机器列表,然后 SSH 向这些机器发送远程命令:6.master-backup.sh 的作用:通过 backup-masters 这个配置文件,获取 backup-masters 机器列表,然后 SSH 向这些机器发送远程命令。
HBase 是一个分布式、可扩展、高性能的列式存储系统,它支持多种查询方式以满足不同场景的需求。
以下是 HBase 的查询方式的详细描述:
scan
方法对整个表进行查询。例如,要查询名为 myTable
的表,可以使用以下命令:Scanner scanner = connection.createScanner(Bytes.toBytes("myTable"));
get
方法按 rowkey 获取单行数据。例如,要获取 rowkey 为 "1"
的数据,可以使用以下命令:Result result = connection.get(Bytes.toBytes("myTable"), Bytes.toBytes("1"));
scan
方法进行基于 rowkey 的范围扫描。例如,要查询 rowkey 从 "1"
到 "2"
的数据,可以使用以下命令:Scanner scanner = connection.createScanner(Bytes.toBytes("myTable"));
scanner.setStartRow(Bytes.toBytes("1"));
scanner.setStopRow(Bytes.toBytes("2"));
get
和 scan
方法的其他用法:1)按指定的 rowkey 获取唯一一条数据,使用 get
方法。get
方法分为两种,分别是设置了 closestRowBefore
和没有设置的 rowlock
。只要保证行的事务性,即每一个 get
以一个 row 来标记的,一个 row 中可以有多个 family 和 column。例如,获取 rowkey 为 "1"
的第一列数据,可以使用以下命令:
Result result = connection.get(Bytes.toBytes("myTable"), Bytes.toBytes("1"), Bytes.toBytes("column1"));
2)按指定的条件获取一批记录,使用 scan
方法进行条件查询。scan
方法可以通过以下方式进行优化:
使用 setCaching
和 setBatch
方法来提高速度。例如,设置每次 RPC 请求返回的行数为 10,可以使用以下命令:
Scanner scanner = connection.createScanner(Bytes.toBytes("myTable"));
scanner.setCaching(10);
使用 setStartRow
和 setEndRow
方法来限定范围(左闭右开)。例如,要查询 rowkey 从 "1"
到 "2"
的数据,可以使用以下命令:
Scanner scanner = connection.createScanner(Bytes.toBytes("myTable"));
scanner.setStartRow(Bytes.toBytes("1"));
scanner.setStopRow(Bytes.toBytes("2"));
使用 setFilter
方法来添加过滤器。例如,要查询列族 cf
中的列 column1
,可以使用以下命令:
Scanner scanner = connection.createScanner(Bytes.toBytes("myTable"));
scanner.setFilter(new SingleColumnFilter(Bytes.toBytes("cf"), Bytes.toBytes("column1")));
总之,HBase 提供了多种查询方式以满足不同场景的需求。根据实际应用场景选择合适的查询方式,可以提高 HBase 的性能。
1)HRegisonServer保存着.meta.表及数据表,首先client先访问zk,访问-ROOT-表,然后在zk上面获取.meta.表所在的位置信息,找到这个meta表在哪个HRegionServer上面保存着。
2)接着client访问HRegionServer表从而读取.meta.进而获取.meta.表中存放的元数据。
3)client通过.meta.中的元数据信息,访问对应的HRegionServer,然后扫描HRegionServer的Memstore和StoreFile来查询数据。
4)最后把HRegionServer把数据反馈给client。
1)client访问zk中的-ROOT-表,然后后在访问.meta.表,并获取.meta.中的元数据。
2)确定当前要写入的HRegion和HRegionServer。
3)clinet向HRegionServer发出写相应的请求,HRegionServer收到请求并响应。
4)client先将数据写入到HLog中,以防数据丢失。
5)然后将数据写入到MemStore中。
6)如果HLog和MemStore都写入成功了,那么表示这个条数据写入成功了。
7)如果MemStore写入的数据达到了阈值,那么将会flush到StoreFile中。
8)当StoreFile越来越多,会触发Compact合并操作,将过多的StoteFile合并成一个大的StoreFile。
9)当StoreFile越来越多时,Region也会越来越大,当达到阈值时,会触发spilit操作,将这个Region一分为二。
ps:HBase中所有的更新和删除操作都会在后续的compact中进行,使得用户的写操作只需要进入内存中就行了。实现了HBase的 I/O高性能。
HBase 的 flush 流程是指将内存中的数据写入磁盘的过程,它分为三个阶段:prepare、flush 和 commit。下面对这三个阶段进行详细描述:
添加 updateLock 锁,阻塞写请求。目的是确保在 prepare 阶段,没有其他的写请求进入,以保证数据的一致性和完整性。
遍历 MemStore,将 MemStore 中的数据集 CellSkipSet 做一个快照 Snapshot。快照 Snapshot 是一个只读的、不可变的数据集,用于在 flush 阶段将数据写入磁盘。
新建 CellSkipListSet,用于保存后续的写入数据。这一步是为了隔离准备阶段和 flush 阶段的数据,以便在 flush 阶段将数据写入磁盘时,不会影响到准备阶段的数据。
阶段结束,释放 updateLock 锁。
遍历所有的 Memstore,将 prepare 阶段生成的 snapshot 文件持久化到.tmp 目录下,生成临时文件。这一步是将准备阶段的数据写入磁盘的过程,由于涉及到磁盘 I/O 操作,所以相对耗时。
刷新缓存,将新生成的 HFile 添加到缓存中。
遍历 memstore,将临时文件移动到指定的 ColumnFamily 目录下。这一步是将 flush 阶段生成的临时文件替换掉准备阶段的 Snapshot,完成数据的持久化。
针对 HFile 生成对应的 storefile 和 Reader,把 storefile 添加到 HStore 的 storefiles 列表中。
最后再清空 prepare 阶段生成的 snapshot。
HBase 的 flush 流程旨在确保数据的一致性、完整性和高效性。通过将内存中的数据写入磁盘,可以释放内存资源,以便后续的读写操作。同时,flush 流程的设计也保证了数据在写入磁盘过程中的高可用性和可靠性。
HBase 是一个面向列的数据库,所以在进行模型设计时,重点在于如何高效地存储和查询数据。HBase 的设计目标是尽可能地利用列存储和查询的优势,提高系统的性能和可扩展性。
在设计 HBase 模型时,需要关注以下几个方面:
列族的设计:列族是 HBase 中列的集合,一个表可以包含多个列族。列族在存储和查询时具有独立的特性,因此需要根据数据的访问模式和特点来设计列族。一般来说,划分标准是根据数据访问频度,如一张表里有些列访问相对频繁,而另一些列访问很少,这时可以把这张表划分成两个列族,分开存储,提高访问效率。
列的设计:列是 HBase 中数据的基本单元,一个表可以包含多个列。在设计列时,需要考虑数据的类型、长度和访问频度等因素,以便合理地分配存储资源和提高查询效率。HBase 中的列数据类型包括字节数组、字符串、数字、日期等,每个列都有对应的数据类型和长度限制。
行键的设计:行键是 HBase 中数据的唯一标识,通过行键可以快速地定位和查询数据。在设计行键时,需要考虑数据的唯一性、分区性和排序性等因素,以便合理地分配存储资源和提高查询效率。HBase 支持两种行键类型,分别是自然行键和合成行键。自然行键是数据的自然标识,如 ID、用户名等;合成行键是由多个字段组合而成的,如时间、地点、用户名等。
二级索引的设计:HBase 对于多条件的组合查询支持不好,一般 HBase 的查询都是通过 RowKey(要把多条件组合查询的字段都拼接在 RowKey 中显然不太可能),或者全表扫描再结合过滤器筛选出目标数据 (太低效)。因此,通过设计 HBase 的二级索引可以提高查询效率。二级索引是基于行键的,可以通过索引定位到具体的行,然后再进行查询。
在一张表中定义多少个 Column Family 最合适,这个问题没有一个确切的答案,因为 Column Family 的个数具体看表的数据。一般来说,划分标准是根据数据访问频度,如一张表里有些列访问相对频繁,而另一些列访问很少,这时可以把这张表划分成两个列族,分开存储,提高访问效率。
另外,也需要考虑数据的类型、长度和访问模式等因素,以便合理地分配存储资源和提高查询效率。在实际应用中,根据业务场景和数据特点进行合理的列族和列的设计,以及行键和二级索引的设计,以最大化地利用 HBase 的存储和查询优势。
提高 HBase 客户端的读写性能需要从多个方面进行优化。
以下是一些可能有用的优化方法:
开启 bloomfilter 过滤器。Bloomfilter 是一种数据结构,用于判断一个 key 是否可能存在于某个集合中。在 HBase 中,开启 bloomfilter 可以显著提高读性能。根据实际测试,开启 bloomfilter 比没开启要快 3、4 倍。
配置足够的内存。HBase 对于内存有特别的需求,因为它需要存储大量的数据和索引。在硬件允许的情况下,为 HBase 配置足够的内存可以提高读写性能。可以通过修改 HBase-env.sh 文件来设置 Java Heap Size。例如:
export HBase_HEAPSIZE=3000 # 这里默认为 1000m
增大 RPC 数量。RPC(远程过程调用)是 HBase 区域服务器(RegionServer)之间通信的方式。通过增大 RPC 数量,可以提高 HBase 集群的并发处理能力。可以修改 HBase-site.xml 文件中的 HBase.regionserver.handler.count 属性来适当放大 RPC 数量。默认值为 10,可以根据实际情况适当调整。
优化 Compaction 策略。Compaction 是 HBase 中一种重要的性能优化手段,用于合并多个 MemStore 文件为一个更大的文件。优化 Compaction 策略可以提高 HBase 的读写性能。HBase 提供了多种 Compaction 策略,可以根据实际情况选择合适的策略。
使用适当的缓存策略。HBase 提供了两种缓存策略:LRU(最近最少使用)和 LRU_CLOCK。使用适当的缓存策略可以提高 HBase 的读性能。可以通过修改 hbase.hstore.compactionThreshold 和 hbase.hstore.blockingStoreFiles 属性来配置缓存策略。
合理设置 MemStore 大小。MemStore 是 HBase 中存储数据的内存结构。合理设置 MemStore 大小可以避免频繁的 Compaction 操作,从而提高读性能。可以通过修改 hbase.hstore.memstore.size 属性来设置 MemStore 大小。
合理配置读写负载。合理分配读写负载可以提高 HBase 的性能。可以通过为不同的客户端分配不同的区域(Region)来实现。
总之,优化 HBase 客户端的读写性能需要从多个方面进行考虑,包括内存配置、Compaction 策略、缓存策略、MemStore 大小以及读写负载的分配等。根据实际情况调整这些参数,可以显著提高 HBase 的性能。
某个小的时段内,对HBase的读写请求集中到极少数的Region上,导致这些region所在的RegionServer处理请求量骤增,负载量明显偏大,而其他的RgionServer明显空闲。
HBase中的行是按照rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。然而糟糕的rowkey设计是热点的源头。
热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region,由于主机无法服务其他region的请求。
为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个。常见的方法有以下这些:
加盐:在rowkey的前面增加随机数,使得它和之前的rowkey的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。
哈希:哈希可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据
反转:第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。反转rowkey的例子以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题
时间戳反转:一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用Long.Max_Value - timestamp
追加到key的末尾,例如[key][reverse_timestamp],[key]
的最新值可以通过scan [key]
获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。
比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设计rowkey的时候,可以这样设计[userId反转] [Long.Max_Value - timestamp]
,在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000]
,stopRow是[userId反转][Long.Max_Value - timestamp]
如果需要查询某段时间的操作记录,startRow是[user反转][Long.Max_Value - 起始时间]
,stopRow是[userId反转][Long.Max_Value - 结束时间]
HBase建表预分区:创建HBase表时,就预先根据可能的RowKey划分出多个region而不是默认的一个,从而可以将后续的读写操作负载均衡到不同的region上,避免热点现象。
HBase 中的大合并和小合并都是针对 HFile 文件的管理操作。HFile 是 HBase 中的存储文件,每个 HFile 文件都包含一个或多个 Region 的数据。当数据在 HFile 文件中被删除时,该记录会被打上标记 DeleteColumn,并且使用 get 和 scan 查询不到,但是该记录仍然存在于 HFile 文件中。
大合并:是指将一个 Region 的所有 HFile 文件合并成一个 HFile 文件。在大合并过程中,HBase 会首先将所有 HFile 文件中的数据进行合并,然后将合并后的数据写入一个新的 HFile 文件中。在这个过程中,HBase 会删除标记为 DeleteColumn 的记录,从而真正删除这些记录。大合并通常在 HBase 集群中进行,以确保数据的一致性和完整性。
小合并:是指将多个小的 HFile 文件合并成一个大的 HFile 文件,并将新文件设置为激活状态,删除小文件。小合并通常在 HBase 集群中进行,以减少 HFile 文件的数量,从而提高查询效率。在小合并过程中,HBase 会首先将所有参与合并的 HFile 文件中的数据进行合并,然后将合并后的数据写入一个新的 HFile 文件中。在新的 HFile 文件中,HBase 会设置激活状态,并将原来的小文件删除。
HBase 中的大合并和小合并都是通过 HFile 文件进行数据管理的操作。大合并用于删除标记为 DeleteColumn 的记录,并确保数据的一致性和完整性;小合并用于减少 HFile 文件的数量,提高查询效率。这两种合并操作在 HBase 集群中进行,以确保数据的安全性和一致性。
…
由于字数限制,此处省略
完整内容,请参见《尼恩 大数据 面试宝典》,pdf 找尼恩 取
…
由于字数限制,此处省略
完整内容,请参见《尼恩 大数据 面试宝典》,pdf 找尼恩 取
…
由于字数限制,此处省略
完整内容,请参见《尼恩 大数据 面试宝典》,pdf 找尼恩 取
…
由于字数限制,此处省略
完整内容,请参见《尼恩 大数据 面试宝典》,pdf 找尼恩 取
…
由于字数限制,此处省略
完整内容,请参见《尼恩 大数据 面试宝典》,pdf 找尼恩 取
…
由于字数限制,此处省略
完整内容,请参见《尼恩 大数据 面试宝典》,pdf 找尼恩 取
本文《尼恩 大数据 面试宝典》 是 《尼恩Java面试宝典》 姊妹篇。
这里特别说明一下:《尼恩Java面试宝典》41个专题 PDF 自首次发布以来, 已经收集了 好几千题,大量的大厂面试干货、正货 ,足足4000多页,帮助很多小伙伴进了大厂,拿了高薪。 所以,《尼恩Java面试宝典》面试题集合, 已经变成Java 学习和面试的必读书籍。
于是,尼恩架构团队趁热打铁,推出 《尼恩 大数据 面试宝典》,已经发布了三个专题:
《尼恩大数据面试宝典专题1:史上最全Hadoop面试题》
《尼恩大数据面试宝典专题2:绝密100个Spark面试题,熟背100遍,猛拿高薪》
《尼恩大数据面试宝典专题3:史上最全Hive面试题,不断迭代,持续升级》
《尼恩大数据面试宝典专题4:史上最全Flink面试题,不断迭代,持续升级》
《尼恩大数据面试宝典专题5:史上最全HBase面试题,不断迭代,持续升级》(本文)
完整的pdf,可以到文末公号【技术自由圈】取。
并且,《尼恩 大数据 面试宝典》、 《尼恩Java面试宝典》 都会持续迭代、不断更新,以 吸纳最新的面试题,最新版本,具体请参见 文末公号【技术自由圈】
未来职业,如何突围: 成长为 三栖架构师, Java 架构+GO 架构 + 大数据 架构
尼恩即将为大家编写,《大数据 Flink学习圣经》 《大数据 HBase 学习圣经》
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓