HBase是什么
Apache HBase(Hadoop DataBase)是一个开源的、高可靠性、高性能、面向列、可伸缩、及时读写的分布式数据库,其设计思想来源于 Google 的 BigTable 论文。利用 Hadoop HDFS 作为其文件存储体系,利用 ZooKeeper 作为其分布式协同服务。重要用来存储非结构化和半结构化的疏松数据(列式存储 NoSQL 数据库)。 HBase 属 于 CP 架构,降低了可用性,具备强同等性读/写。
特点:
1. 易扩展
一个是基于运算能力(HRegionServer)通过增长 HRegionServer 节点数量提高其运算能力,一个是基于存储能力的扩展(HDFS)通过增长 DataNode 节点数提高数据储存能力
2. 容量大
HBase 单表可以有十亿行、百万列,数据矩阵横向和纵向两个维度所支持的数据量级都非常具有弹性。HBase 的重要作用就是面向 PB 级别数据的及时入库和快速随机访问。
3. 面向列
HBase 是根据列族来存储数据的,列族下面可以有非常多的列。列式存储的最大利益就是,其数据在表中是按照某列存储的,如许在查询只需要少数几个字段时,能大大减少读取的数据量。还可以动态增长列,可单独对列举行各方面的操作。
4. 多版本
HBase 的每个列的数据存储支持多个 Version,比如住址列,大概有多个变更。
5. 稀疏性
为空的列并不占用存储空间,表可以设计的非常稀疏。不必像关系型数据库那样需要预先知道所有列名然后再举行 null 添补。
6. 高可靠
WAL(Write Ahead Log)日志先行机制,保证数据写入的时间不会因为集群非常而导致写入数据丢失。Replication 机 制,保证了集群在出现严重题目的时间,数据不会发生丢失或者损坏。HBase 底层使用 HDFS,本身也有备份。
7. 高性能
底层的 LSM 树数据结构和 RowKey 有序分列等架构上的独特设计,使得 HBase 写入性能非常高。HRegion 切分、主键 索引、缓存机制使得 HBase 在海量数据下具备一定的随机读取性能,该性能针对 RowKey 的查询能够到达毫秒级别。LSM 树属于树形结构,最末端的子节点是以内存的方式举行存储的,内存中的小树会 Flush 到磁盘中(当子节点达到一定阈值 以后,会放到磁盘中,且存入的过程会举行及时 Merge 成一个主节点,然后磁盘中的树定期会做 Merge 操作,合并成一棵大树,以优化读性能)。
HBase 数据模子
在 HBase 表中,一条数据拥有一个全局唯一的主键(RowKey)和任意数量的列(Column Qualifier),每个列的数据 存储支持多个版本(Version),一列或多列组成一个列族(Column Family),同一个列族中列的数据在物理上都存储在同一个 HFile 中。如许基于列存储的数据结构有利于数据缓存和查询。
所以,在 HBase 中定位一条数据需要通过:RowKey → Column Family → Column Qualifier → Version。
HBase 表中的数据是疏松地存储的,因此用户可以动态地为数据定义各种不同的列。HBase 中的数据按主键排序(字 典序),同时 HBase 会将表按主键划分为多个 HRegion 存储在不同的 HRegionServer 上,以完成数据的分布式存储和读取。
1. NameSpace
命名空间类似于关系型数据库中的数据库的概念,他其实是表的逻辑分组。这种抽象为多租户相关功能奠定了基础。 命名空间是可以管理维护的,可以创建,删除或更改命名空间。HBase 有两个特别预定义的命名空间:
- default:没有明白指定命名空间的表将自动落入此命名空间
- hbase:体系命名空间,用于包罗 HBase 的内部表和元数据表
2. Table
Table 和关系型数据库中的表一个意思,由行和列组成。
3. RowKey
RowKey 的概念与关系型数据库中的主键相似,是一行数据的唯一标识。RowKey 可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100 Bytes),RowKey 以字节数组生存。存储数据时,数据会按照 RowKey 的字典序排序存储,所以设计 RowKey 时,要充实利用排序存储这个特性,将常常一起读取的行存放到一起。
访问 HBase 数据的方式有三种:
- 基于 RowKey 的单行查询;
- 基于 RowKey 的范围查询;
- 全表扫描查询。
4. Column Family
Column Family 即列族,HBase 基于列划分数据的物理存储,同一个列族中列的数据在物理上都存储在同一个 HFile 中。一个列族可以包罗任意多列,一般同一类的列会放在一个列族中,每个列族都有一组存储属性:
- 是否应该缓存在内存中;
- 数据如何被压缩或行键如何编码等。
HBase 在创建表的时间就必须指定列族。HBase 的列族不是越多越好,官方保举一个表的列族数量最好小于或者即是三,过多的列族不利于 HBase 数据的管理和索引。
5. Column Qualifier
列族的限定词,明白为列的唯一标识。但是列标识是可以改变的,因此每一行大概有不同的列标识。使用的时间必须 列族 : 列 ,列可以根据需求动态添加或者删除,同一个表中不同行的数据列都可以不同。
6. Timestamp
Timestamp 是实现 HBase 多版本的关键。在 HBase 中,使用不同的 Timestamp 来标知趣同 RowKey 对应的不同版本 的数据。相同 RowKey 的数据按照 Timestamp 倒序分列,默认查询的是最新的版本,当然用户也可以指定 Timestamp 的值 来读取指定版本的数据。
为了避免数据存在过多版本而造成管理(包括存贮和索引)负担,HBase 提供了两种数据版本采取方案:
- 一是生存数据的最后 n 个版本
- 二是生存最近一段时间内的版本(比如最近七天)
7. Cell
Cell 由 Row,Column Family,Column Qualifier,Version 组成。Cell 中的数据是没有范例的,全部使用字节码情势存贮,因为 HDFS 上的数据都是字节数组。
HBase架构模子
流程:
客户端根据 RowKey 发出读哀求给 Zookeeper -> Zookeeper 拿到客户 RowKey -> Zookeeper 发给 HMaster Active -> HMaster Active 根据 RowKey 找到具体的 HRegionServer -> HRegionServer 先去BlockCache块缓存 找数据 -> 未找到去 MemStore 缓存中找数据 -> 未找到去磁盘中的 StoreFile 找数据 -> 从 HFile 中找到记载所存在的 HDFS 中 DataNode 的位置 -> HDFS Client -> DataNode
1. ZooKeeper
HBase 通过 ZooKeeper 来完成选举 HMaster、监控 HRegionServer、维护元数据集群配置等工作。
- 选举 HMaster: 保证集群中只有一个 HMaster 。实现 HMaster 主从节点的 Failover(主从故障切换);
- 监控 HRegionServer(节点探活):监控 HRegionServer 的状态,将其状态及时报告给 HMaster
- 维护元数据和集群配置: 存放整个 HBase 集群的元数据以及集群的状态信息,包括:
- 存储所有 HRegion 的寻址入口(META 元数据表),存储所有的的元数据信息;
- 存储 HBase 的 Schema,包括有哪些 Table,每个 Table 有哪些 Column Family。
2. Client
HBase Client 为用户提供了访问 HBase 的接口,可以通过元数据表(客户端负责发送哀求到数据库)来定位到目标数据的 HRegionServer。客户端连接的方式有很多种:
发送的哀求重要包括:
- DDL:数据库定义语言(表的建立,删除,添加删除列族,控制版本)
- DML:数据库操作语言(增删改)
- DQL:数据库查询语言(查询,全表扫描,基于主键,基于过滤器)
Client 维护着一些 Cache 来加快对 HBase 的访问,比如 HRegione 的位置信息。
3. HMaster
HMaster 是 HBase 集群的主节点,负责整个集群的管理工作,HMaster 可以实现高可用(Active 和 Standby),通过 ZooKeeper 来维护主备节点的切换。HMaster 重要工作职责如下:
- 管理分配:管理和分配 HRegion,负责启动的时间分配 HRegion 到具体的 HRegionServer,又或者在分割 HRegion 时关于新 HRegion 的分配。管理用户对 Table 结构的 DDL(创建,删除,修改)操作。
- 表的元数据信息存储在 ZooKeeper
- 表的数据存储在 HRegionServer 上(实际存储在 HDFS 上)
- 负载均衡:一方面负责将用户的数据均衡地分布在各个 HRegionServer 上,防止 HRegionServer 数据倾斜过载。另一 方面负责将用户的哀求均衡地分布在各个 HRegionServer 上,防止 HRegionServer 哀求过热;
- 维护数据:发现失效的 HRegion,并将失效的 HRegion 分配到正常的 HRegionServer 上。当某个 HRegionServer 下线 时迁移其内部的 HRegion 到其他 HRegionServer 上。
- 权限控制。
4. HRegionServer
HRegionServer 直接对接用户的读写哀求,是真正干活的节点,属于 HBase 具体数据的管理者。重要工作职责如下:
- 及时和 HMaster 保持心跳,报告当前节点的信息;
- 当接收到 HMaster 的命令创建表时,会分配一个 HRegion 对应一张表;
- 负责切分在运行过程中变得过大的 HRegion;
- 当 HRegionServer 意外关闭的时间,
- 当前节点的 HRegion 会被其他 HRegionServer 管理;
- 维护 HMaster 分配给它的 HRegion,处理对这些 HRegion 的 IO 哀求;
- 当客户端发送 DML 和 DQL 操作时,HRegionServer 负责和客户端建立连接;
- WAL:Write Ahead Log 日志先行。记载了数据写入、更新日志,它被用来做故障恢复;
- MemStore:写缓存,数据起首会被写入到 MemStore 中。每个 HRegion 的每个 Column Family 都会有一个 MemStore。
- 负责与底层的 HDFS 交互,存储数据(HLog、HFile)到 HDFS。
- BlockCache:读缓存,在内存中存储了最常访问的数据,采用 LRU 机制举行淘汰。
5. HRegion
一个 HRegionServer 包罗了多个 HRegion。HBase 将表中的数据基于 RowKey 的不同范围划分到不同 HRegion 上,每个 HRegion 都负责一定范围的数据存储和访问。
HRegion 是 HBase 中分布式存储和负载均衡的最小单位,不同的 HRegion 可以分布在不同的 HRegionServer 上。每个表一开始只有一个 HRegion,随着数据不停插入表,HRegion 不停增大,当增大到指定阀值(10G)的时间,HRegion 就会等分成两个 HRegion,切分后其中一个 HRegion 会被转移到其他的 HRegionServer 上,实现负载均衡。
当 Table 中的行不停增多,就会有越来越多的 HRegion。为了防止前期数据的处理都集中在一个 HRegionServer,我们可以根据自己的业务举行预分区。
由于数据被划分到不同的 HRegion上,每个 HRegion 都可以独立地举行读写, HBase 读写数据的时间还可以与多 HRegion 分布式并发操作,所以访问速度并不会有太大的降低。
6. Store
一个 HRegion 由多个 Store 组成,每个 Store 都对应一个 Column Family,Store 包罗 1 个 MemStore 和 0 或多个 StoreFile 组成。
- MemStore: 作为 HBase 的内存数据存储,数据的写操作会先写到 MemStore 中,当 MemStore 中的数据增长到指定阈值(默认 128M)后,HRegionServer 会启动 FlushCache 进程将 MemStore 中的数据写入 StoreFile 持久化存储,每次写入后都形成一个单独的 StoreFile。当客户端检索数据时,先在 MemStore 中查找,不存在,则会在 StoreFile 中继续查找。
- StoreFile:MemStore 中的数据写到文件后就是 StoreFile,StoreFile 底层是以 HFile 格式 生存的。根据其大小来确定是否切分 HRegion ,切分后将另外一个转移到其他的 HRegionServer 上,实现负载均衡。
- HFile:HFile 和 StoreFile 是同一个文件,只不过站在 HDFS 的角度称这个文件为 HFile,站在 HBase 的角度就称这个文 件为 StoreFile。
7. HFile
StoreFile(HFile) 是 HBase 最终存储数据的介质,这里需要相识几个相关的名词:
- Block:每个 HFile 由 N 个 Block 组成。
- KeyValue:每个 Block 又是由多个 KeyValue 数据组成,KeyValue 对象是数据存储的焦点,KeyValue 包装了一个字节数 组,同时将偏移量 offsets 和 lengths 放入数组中,这个数组指定从哪里开始剖析数据内容。
8. HLog
一个 HRegionServer 只有一个 HLog 文件。负责记载数据的操作日志,当 HBase 出现故障时可以举行日志重放、故障恢复。比方磁盘掉电导致 MemStore 中的数据没有持久化存储到 StoreFile,这时就可以通过 HLog 日志重放来恢复数据。
9. HDFS
HDFS 为 HBase 提供底层数据存储服务,同时为 HBase 提供高可用支持。HBase 将 HLog 存储在 HDFS 上,当服务器发 生非常宕机时,可以重放 HLog 来恢复数据。
比如:MySQL 数据直接落入磁盘,HBase 数据落入 HDFS,HDFS 数据落入磁盘。
三层索引
1. HBase 0.96 以前
HBase 0.96 以前内部维护了两张特别的表: -ROOT- 表和 .META. 表,用来查找各种表的 HRegion 位置。这两张特别 的表也像 HBase 中的其他表一样会切分成多个 HRegion。 -ROOT- 表比 .META. 更特别一些,永远不会切分凌驾一个 HRegion,如许保证了只需要三次跳转,就能定位到任意 HRegion。
- -ROOT- :记载 .META. 表的 HRegion 信息。
- .META. :记载用户的表的 HRegion 信息。
整个流程为: Client → ZooKeeper → -ROOT- → .META. → 用户的表的 HRegion 。
-ROOT- 表永远只有一个 HRegion,也就是说只会存放在一台 HRegionServer 上,这个信息至关紧张,是所有客户端定位 HRegion 的入口,所以这个映射信息存储在 ZooKeeper 上面。
2. HBase 0.96 以后
HBase 0.96 以后,-ROOT- 表被移除,直接将 .META. 表 HRegion 位置信息存放在 ZooKeeper 中,并将 .META. 表更名为 hbase:meta 。
此时整个流程为: Client → ZooKeeper → hbase:meta → 用户的表的 HRegion 。
hbase:meta 表结构如下:
- rowkey:表名,格式为 表名,起始键,HRegion的时间戳.Encode编码. ;
- table:state:表的状态,启用照旧禁用状态;
- info:state:HRegion 的状态,正常环境下为 OPEN;
- info:server:HRegionServer 的地址和端口,如 node03:16020;
- info:serverstartcode:HRegionServer 启动的 13 位时间戳;
- info:sn:server 和 serverstartcode 的组合,如 node03:16020,1662183040273;
- info:seqnumDuringOpen:HRegion 在线时长的二进制串;
- info:regioninfo:HRegion 的详细信息,如:ENCODED、NAME、STARTKEY、ENDKEY 等。
部分内容如下:
读取数据流程
- Client 访问 ZooKeeper,获取 hbase:meta(记载所有HRegionServer节点的元数据) 所在 HRegionServer 的节点信息;
- Client 访问 hbase:meta 所在的 HRegionServer,获取 hbase:meta 记载的元数据后先加载到内存中,然后再从内存中查询出 RowKey 所在的 HRegion (HRegion 所在的 HRegionServer);
- Client 对 RowKey 所在的 HRegion 对应的 HRegionServer 发起读取数据哀求;
- HRegionServer 构建 RegionScanner(需要查询的 RowKey 分布在多少个 HRegion 中就需要构建多少个 RegionScanner),用于对该 HRegion 的数据检索;
- RegionScanner 构建 StoreScanner(HRegion 中有多少个 Store 就需要构建多少个 StoreScanner,Store 的数量取决于 Table 的 ColumnFamily 的数量),用于对该列族的数据检索;
- 所有的 StoreScanner 合并构建最小堆(已排序的完全二叉树)StoreHeap
riorityQueue;
- StoreScanner 构建一个 MemStoreScanner 和一个或多个 StoreFileScanner(数量取决于 StoreFile 数量);
- 过滤掉能够确定所要查询的 RowKey 一定不在的 StoreFileScanner 或 MemStoreScanner(布隆过滤器);
- 颠末筛选后留下的 Scanner 开始做读取数据的预备,将对应的 StoreFile 定位到满足的 RowKey 的起始位置;
- 将所有的 StoreFileScanner 和 MemStoreScanner 合并构建最小堆 KeyValueHeap
riorityQueue,排序的规则按照 KeyValue 从小到大排序;
- 从 KeyValueHeap
riorityQueue 中颠末一系列筛选后一行行的得到需要查询的 KeyValue。
默认环境下:先从 BlockCache 查找数据,如果没有,再从 MemStore 上查找,如果 MemStore 中也没有,再到 StoreFile 上举行查找。其中 StoreFile 的扫瞄先会使用 Bloom Filter(布隆过滤器) 过滤那些不大概符合条件的 HFile,然后使用 Data Block Index 快速定位 Cell(细胞,单位格),并将其加载到 BlockCache 中,然后从 BlockCache 中读取,目标是为了加快后续的查询,然后在返回结果给客户端。
口试题:为什么 HBase 可以做到百亿数据秒级查询?
- 通过 hbase:meta 表可以帮我们敏捷定位到该记载所在的数据节点,以及数据节点中的 HRegion,目前我们有 100 亿条记载,占空间 10TB。所有记载被切分成 5000 个 HRegion,每个 HRegion 约莫 2G。
- 由于 HBase 存储数据是按照列族存储的。这四个列族是分开存储的,假设 2G 的 HRegion 文件中,分为 4 个列族,那么每个列族就是 500M。我们只需要遍历这 500M 的列族,就可以找到对应的记载。
- 1 个列族在 HDFS 中会包罗 1 个或者多个 HFile(StoreFile)。如果一个 HFile 的大小为 100 M,那么该列族包罗 5 个 HFile 在磁盘上或内存中。由于 HBase 内存 Flush 到磁盘中的数据是排好序的,要查询的记载有大概在最前面,也有大概在最反面,按匀称来算,我们只需遍历 2.5 个 HFile 共 250M,就可以找到对应的记载。
- 每个 HFile 中,是以键值对(Key/Value)方式存储,只要遍历文件中的 Key 位置并判定符合条件即可。一般 Key 是有限的长度,假设 Key/Value 比是 1:24,最终只需要 10M 的数据量,就可以找到对应的记载。如果是 SSD 的话,0.01 秒即可查到。当然,扫描 HFile 时还可以通过布隆过滤器快速定位到对应的 HFile,以及 HBase 是有内存缓存机制的,如果数据在内存中 (BlockCache),服从会更高。
- HFile 继续划分,有 Data Block,Data Block Index,Trailler 等组成,已经定位到 RowKey 所在的 HFile 时,会先读取 HFile 的 Trailer 的信息以获取 Data Block Index 的位置。Data Block Index 的 Key 就是 Data Block 的 RowKey,所以通过 Data Block Index 的 Key 就能准确的定位到要检索的 RowKey 在哪个 Data Block 上,然后直接将该 Data Block 读取到内存,需要留意的是这里的 Data Block 已经很小了(默认是 64K,不同于 HDFS 上的 Block 默以为 128M,HBase 的 HFile 中的 Block 要小的多)如许子足以读取该 Block 到内存中,将该 Block 举行遍历就能获取到需要的 RowKey 并取出数据。因为这里的 Block 只有 64K,所以遍历会非常敏捷。这就是为什么 HFile 的 Data Block 要设置的如此之小的缘故起因。
总结:
正因为以上流程,即使数据量剧增,也不会导致 HBase 的查询性能下降。同时,HBase 是一个面向列存储的数据库 (列族机制),当表字段非常多时,可以把其中一些字段独立出来放在一部分机器上,而另外一些字段放到另一部分机器 ,分散存储,分散列查询。 正是由于如许复杂的存储结构和分布式的存储方式,保证了 HBase 海量数据下的查询服从。
数据刷写
1. 触发机遇
1. 内存阈值
HRegion 中的每个 MemStore 占用的内存凌驾相关阈值 hbase.hregion.memstore.flush.size 时会触发刷写,默以为 128MB。
如果我们的数据增长得很快,达到了 512MB 的时间,除了触发 MemStore 刷写之外,HBase 还会在刷写的时间阻塞所有写入该 Store 的哀求。
2. 内存总和
整个 HRegionServer 的 MemStore 占用内存总和大于相关阈值时会触发刷写。如果达到了 HRegionServer 级别的刷写, 当前 HRegionServer 的所有写操作将会被阻塞,这个阻塞大概会持续到分钟级别。
3. 日志阈值
HBase 使用了 WAL 机制(日志先行),当数据到达 HRegion 时是先写入日志的,然后再被写入到 MemStore。如果日志的数量越来越大,这就意味着 MemStore 中未持久化到磁盘的数据越来越多。当 HRegionServer 挂掉的时间,恢复时间将会变得很长,所以有必要在日志到达一定的数量时举行一次刷写操作。
4. 定期刷写
当定时器到达 1 小时 时, HBase 会自动触发刷写。一般发起调大,比如 10 小时,因为很多场景下 1 小时 Flush 一次会产生很多小文件,一方面导致 Flush 比较频繁,另一方面导致小文件很多,影响随机读性能。
5. 更新频率
如果 HBase 的某个 HRegion 更新的很频繁,而且既没有达到自动刷写阀值,也没有达到内存的使用限制,但是内存中的更新数量已经足够多,比如凌驾 hbase.regionserver.flush.per.changes 参数配置,默以为 30000000 次,也会触发刷写。
6. 手动刷写
- hbase> flush 'TABLENAME' //TABLENAME(表名)
- hbase> flush 'REGIONNAME' //REGIONNAME(区名)
- hbase> flush 'ENCODED_REGIONNAME' //ENCODED_REGIONNAME(编码区名)
- hbase> flush 'REGION_SERVER_NAME' //区服务器名
复制代码 7. 留意
以上所有条件触发的刷写操作最后都会查抄对应的 Store 包罗的 StoreFiles 文件数是否凌驾 hbase.hstore.blockingStoreFiles 参数配置的个数,默以为 16。如果满足这个条件,那么当前刷写会被推迟到 hbase.hstore.blockingWaitTime 参数设置的时间后再刷写。
如果是阻塞刷写,HBase 还会哀求压缩 Compaction 或者分割 Split 操作。
刷写策略
HBASE 1.1 之前:MemStore 刷写是 HRegion 级别的。就是说,如果要刷写某个 MemStore ,MemStore 所在的 HRegion 中其他的 MemStore 也是会被一起刷写的(简单的明白:Flush 一个列族时其它列族也会一起 Flush)。
HBASE 2.x 之后:
- FlushAllStoresPolicy:HBASE 1.1 的策略。
- FlushAllLargeStoresPolicy:判定 HRegion 中每个 MemStore 的使用内存是否大于指定阀值,大于阀值的 MemStore 将会 被刷写。阈值计算公式: flushSizeLowerBound = max((long)128 / 3, 16) = 42 。
- FlushNonSloppyStoresFirstPolicy:将 Region 中的 MemStore 按照 isSloppyMemStore 分到两个 HashSet 里面 ( sloppyStores 和 regularStores )然后:
- 判定 regularStores 里面是否有 MemStore 内存占用大于相关阀值的 MemStore,有的话就会对这些 MemStore 举行刷写,其他的不做处理,这个阀值计算和 FlushAllLargeStoresPolicy 的阀值计算逻辑同等。
- 如果 regularStores 里面没有 MemStore 内存占用大于相关阀值的 MemStore,这时间就开始在 sloppyStores 里面寻找是否有 MemStore 内存占用大于相关阀值的 MemStore,有的话就会对这些 MemStore 进 行刷写,其他的不做处理。
- 如果上面 sloppyStores 和 regularStores 都没有满足条件的 MemStore 需要刷写,这时间就将 FlushNonSloppyStoresFirstPolicy 策略久退化成 FlushAllStoresPolicy 策略了。 \
数据合并
承载了大量 IO 哀求但是文件很小的 HFile,Compaction 本身不会斲丧太多 IO,而且合并完成之后对读的性能会有显 著提升。
1. 合并分类
HBase 根据合并规模将压缩 Compaction 分为了两类:Minor Compaction 和 Major Compaction。
1. Minor Compaction(次要/小 | 小合并)
选取一些小的、相邻的 StoreFile 将他们合并成一个更大的 StoreFile,在这个过程中不做任何删除数据、多版本数据的清理工作,但是会对 minVersion=0 而且设置 TTL 的过期版本数据举行清理。一次 Minor Compaction 的结果是让小的 StoreFile 变的更少而且产生更大的 StoreFile。
2. Major Compaction(重要/大)
将所有的 StoreFile 合并成一个 StoreFile 清理三类无意义数据:被删除的数据、TTL 过期数据、版本号凌驾设定版本号 的数据。一般环境下,Major Compaction 时间会持续比较长,整个过程会斲丧大量体系资源,对上层业务有比较大的影 响。因此线上业务都会关闭自动触发 Major Compaction 功能,改为手动在业务低峰期触发。
2. 合并机遇
触发 Compaction 的方式有三种:MemStore 刷盘、后台线程周期性查抄、手动触发。
1. MemStore 刷盘
MemStore Flush 会产生 HFile 文件,文件越来越多就需要 Compact。每次实行完 Flush 操作之后,都会对当前 Store 中 的文件数举行判定,一旦文件数大于配置,就会触发 Compaction。Compaction 都是以 Store 为单位举行的,整个 HRegion 的所有 Store 都会实行 Compact。
2. 周期性查抄
后台线程定期触发查抄是否需要实行 Compaction,查抄周期可配置。线程先查抄文件数是否大于配置,一旦大于就 会触发 Compaction。如果不满足,它会接着查抄是否满足 Major Compaction 条件(默认 7 天触发一次,可配置手动触发)。 周期性查抄线程 CompactionChecker 大概 2hrs 46mins 40sec 实行一次。默认值 1000万毫秒
3. 手动实行
一般来讲,手动触发 Compaction 通常是为了实行 Major Compaction,一般有这些环境需要手动触发合并:
- 因为很多业务担心自动 Major Compaction 影响读写性能(可以选择直接关闭),因此会选择低峰期手动触发;
- 用户在实行完 alter 操作之后盼望立刻生效,手动实行触发 Major Compaction;
- HBase 管理员发现硬盘容量不够的环境动手动触发 Major Compaction 删除大量过期数据。
3. 合并策略
1. 线程池
HBase CompacSplitThread 类内部对于 Split、Compaction 等操作专门维护了各自所使用的线程池。和 Compaction 相关的是 longCompactions 和 shortCompactions。前者用来处理大规模 Compaction,后者处理小规模 Compaction。默认值 为 2 * maxFlilesToCompact(默以为 10) * hbase.hregion.memstore.flush.size,如果 flush size 大小是 128M,该参数默认值就是 2 * 10 * 128M = 2.5G。
2. 合并策略
HBase 重要有两种 Minor Compaction 策略:RatioBasedCompactionPolicy(0.96.x 之前) 和 ExploringCompactionPolicy(当前默认)。
- RatioBasedCompactionPolicy(基于比列的合并策略):从老练新逐一扫描 HFile 文件,满足以下条件之一制止扫描:当 前文件大小 < 比当前文件新的所有文件大小总和 * Ratio(高峰期1.2,非高峰期5),当前所剩候选文件数 <= 阈值(默以为 3)。比方:当前文件 2G < 所有文件大小总和 1G * 1.2,高峰期不合并,非高峰期合并;
- ExploringCompactionPolicy 策略(默认策略):基于 Ratio 策略,不同之处在于 Ratio 策略找到一个合适文件聚集就制止 扫描,而 Exploring 策略会记载所有合适的文件聚集,然后寻找最优解,待合并文件数最多或者待合并文件数相同的 环境下文件较小的举行合并;
- FIFO Compaction 策略:网络过期文件并删除,对应业务的列族必须设置有 TTL;
- Tier-Based Compaction 策略(分层策略):针对数据热门环境设计的策略,根据候选文件的新老程度将其划分为不同的 品级,每个品级都有对应的 Ratio,表示该品级文件比选择为到场 Compation 的概率(基于 Ratio 策略根据热门环境设 置不同的 Ratio);
- Stripe Compation 策略(条纹策略):将整个 Store 中的文件按照 Key 划分为多个 Range,此处称为 Stripe,一个 Stripe 内 部就类似于一个小 HRegion,可以实行 Minon Compation 和 Major Compation。
3. 文件合并
分别读出待合并 HFile 文件的 KV,并顺序写到位于 ./tmp 目次下的临时文件中,再将临时文件移动到对应 HRegion 的数据目次。将 Compaction 的输入文件路径和输出文件路径封装为 KV 写入 WAL 日志,并打上 Compaction 标记,最后强制实行 Sync。将对应 HRegion 数据目次下的 Compaction 输入文件全部删除。
数据切分
通过切分,一个 HRegion 变为两个近似相同大小的子 HRegion,再通过 balance 机制均衡到不同 HRegionServer上,使体系资源使用更加均衡。
1. 切分缘故起因
1. 数据分布不匀称
同一 HRegionServer 上数据文件越来越大,读哀求也会越来越多。
2. Compaction 性能损耗严重
Compaction 本质上是一个排序合并的操作,合并操作需要占用大量内存,因此文件越大,占用内存越多。
3. 资源泯灭严重
HBase 的数据写入量也是很惊人的,每天都大概有上亿条的数据写入不做切分的话一个热门 HRegion 的新增数据量就 有大概几十G,用不了多长时间大量读哀求就会把单台 HRegionServer 的资源耗光。
2. 触发机遇
在 HBase 中 Split 是一个很紧张的功能,HBase 是通过把数据分配到一定数量的 HRegion 来达到负载均衡的。
在 0.94 版本之前 ConstantSizeRegionSplitPolicy 是默认和唯一的 Split 策略。当某个 Store(对应一个 Column Family) 的大小大于配置值 hbase.hregion.max.filesize 的时间(默认 10G)HRegion 就会自动分裂。
而 0.94 版本之后 IncreasingToUpperBoundRegionSplitPolicy 是默认的 Split 策略。这个策略中,最小的分裂大小和 Table 的某个 HRegionServer 的 HRegion 个数有关,当 StoreFile 的大小大于以下公式得出的值的时间就会 Split。
比方:
- hbase.hregion.memstore.flush.size 默认值 128MB。
- hbase.hregion.max.filesize 默认值为 10GB。
- 如果初始时 R=1 ,那么 Min(128MB, 10GB)=128MB ,也就是说在第一个 Flush 的时间就会触发分裂操作。
- 当 R=2 的时间 Min(2*2*128MB, 10GB)=512MB ,当某个 StoreFile 大小达到 512MB 的时间,就会触发分裂。
- 如此类推,当 R=9 的时间,StoreFile 达到 10GB 的时间就会分裂,也就是说当 R>=9 的时间,StoreFile 达到 10GB 的时间就会分裂。
我们可以通过配置体系文件来指定 Split 策略,也可以写我们自己的 Split 策略。
HBase 的 RowKey 设计需要遵循以下原则(办理 ROW_KEY 热门题目)
列族设计
1. 最优设计
寻求原则:在公道范围内,尽大概的减少列族。
最优设计:将所有相关性很强的 key-value 都放在同一个列族。如许既能做到查询服从最高,也能保证尽大概少的访问不同的磁盘文件。
控制长度:列族名的长度要尽量小,一个为了节省空间,一个为了加快服从,最好是一个字符,比如 d 表示 data 或 default,v 表示 value。
2. 列族属性
HFile 会被切分为多个大小相称的 Block,每一个 Block 大小可以在创建表列族的时间通过 BlockSize 参数指定,默认是 64K。Block 大的话一次加载进内存的数据就多,扫描查询 Scan 效果好,但是 Block 小的话,随机查询 Get 效果好。
BlockCache:数据块缓存默认是打开的,如果一些比较少访问的数据可以选择关闭缓存。
Compression:压缩会提高磁盘利用率,但是会增长 CPU 的负载,看环境举行控制。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |