-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
231 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
--- | ||
title: docker入门 | ||
title: 入门 | ||
date: 2024-04-08 07:24:40 | ||
permalink: /pages/479a6c/ | ||
categories: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
--- | ||
title: 入门 | ||
date: 2024-04-10 18:33:46 | ||
permalink: /pages/0d9ac7/ | ||
categories: | ||
- 技术学习 | ||
- hbase | ||
tags: | ||
- | ||
author: | ||
name: lan-dian | ||
link: https://github.com/lan-dian | ||
--- | ||
## 是什么 | ||
|
||
Hbase是一个分布式数据库,可以存储互联网的海量数据。 | ||
HBase是在HDFS的基础之上构建的,HDFS是分布式文件系统。 | ||
可以支持千万的QPS、PB级别的存储。 | ||
|
||
## 为什么 | ||
|
||
> 为什么不是MySql | ||
| **HBase的** | **关系数据库管理系统(RDBMS)** | | ||
| ----------------------------------------------------- | ------------------------------------------- | | ||
| HBase是无架构的,它没有固定列架构的概念;仅定义列族。 | RDBMS由其架构控制,该架构描述表的整个结构。 | | ||
| 它是**为宽表而设计**的。HBase是水平可伸缩的。 | 它很薄,专为小表而建。难以扩展。 | | ||
| HBase中**没有事务**。 | RDBMS是事务性的。 | | ||
| 它具有**非规范化**的数据。 | 它将具有标准化的数据。 | | ||
| 对于半结构化数据和结构化数据都非常有用。 | 这对结构化数据很有用。 | | ||
|
||
因为Mysql无法存储互联网的海量数据,只能使用NoSql的解决方案。 | ||
|
||
> 为什么不是ES | ||
因为ES的成本比较好,支持了分词等等逻辑,主要用在搜索领域,远高于我们的需求。 | ||
|
||
> 为什么不是HDFS | ||
| **HDFS** | **HBase** | | ||
| ---------------------------------------- | ------------------------------------------------------------ | | ||
| HDFS是适用于存储大文件的分布式文件系统。 | HBase是建立在HDFS之上的数据库。 | | ||
| HDFS不支持快速的单个记录查找。 | HBase为大型表提供快速查找。 | | ||
| 它提供高延迟的批处理;没有批处理的概念。 | 它提供了数十亿条记录对单行的低延迟访问(随机访问)。 | | ||
| 它仅提供数据的顺序访问。 | HBase在内部使用哈希表并提供随机访问,并且将数据存储在索引的HDFS文件中,以加快查找速度。 | | ||
|
||
HDFS是一个分布式的文件系统,他可以存储海量的数据,但是功能太底层,不方便我们去操作。 | ||
|
||
--- | ||
|
||
**HBase可以以低成本来存储海量的数据并且支持高并发随机写和实时查询。** | ||
|
||
## 概念 | ||
|
||
### 列式存储 | ||
|
||
| **面向行的数据库** | **列式数据库** | | ||
| -------------------------------- | -------------------------------- | | ||
| 它适用于在线事务处理(OLTP)。 | 它适用于在线分析处理(OLAP)。 | | ||
| 此类数据库设计用于少量的行和列。 | 面向列的数据库是为大型表设计的。 | | ||
|
||
我们可以对比的去学习,MySQL是行存储,每一行有一个id,然后有若干字段。那列式存储,从形式上来看,就是就是把一行拆分开,每一行只有一个id和一个字段。 | ||
这样做有什么好处吗,为什么要这么做? | ||
首先,在MySQL中如果有的字段为空,或者有的一列字段很多重复的,都会照成空间的浪费,如果是列式存储的话,这些空间都是可以压缩的。而且一个id对应一个字段这样的结构,就是NoSql最典型的k-v结构。 | ||
|
||
### 基本概念 | ||
|
||
> 表 | ||
首先,Hbase里面也有表的概念这个和Mysql是一样的 | ||
|
||
> 行键(RowKey) | ||
这个其实就是id | ||
|
||
> 列族 | ||
一个列族下面有多个列 | ||
|
||
区别于MySql,有了列族的概念,而且行与行之间不需要相同的列。数据写到HBase的时候都会被记录一个时间戳,这个时间戳被我们当做一个版本。比如说,我们**修改或者删除**某一条的时候,本质上是往里边**新增**一条数据,记录的版本加一了而已。 | ||
|
||
## 架构 | ||
|
||
Client客户端,它提供了访问HBase的接口,并且维护了对应的cache来加速HBase的访问。 | ||
Zookeeper存储HBase的元数据(meta表),无论是读还是写数据,都是去Zookeeper里边拿到meta元数据告诉给客户端去哪台机器读写数据。 | ||
HRegionServer它是处理客户端的读写请求,**负责与HDFS底层交互**,是真正干活的节点。 | ||
|
||
大概的流程就是:client请求到Zookeeper,然后Zookeeper返回HRegionServer地址给client,client得到Zookeeper返回的地址去请求HRegionServer,HRegionServer读写数据后返回给client。 | ||
|
||
### HRegionServer | ||
|
||
很明显的,这个Server肯定是核心的内容。 | ||
|
||
> HRegion | ||
HBase一张表的数据会分到多台机器上的。用的就是RowKey来切分,其实就是表的横向切割。一个HRegionServer上面管理了多个HRegion,存储了HBase表的一部分数据。 | ||
|
||
> Store | ||
HRegion下面有Store,那Store是什么呢?我们前面也说过,一个HBase表首先要定义列族,然后列是在列族之下的,列可以随意添加。 | ||
**一个列族的数据是存储**在一起的,所以一个列族的数据是存储在一个Store里边的。 | ||
|
||
> Store内部 | ||
HBase在写数据的时候,**会先写到Mem Store,当MemStore超过一定阈值,就会将内存中的数据刷写到硬盘上**,形成StoreFile,而**StoreFile底层是以HFile的格式**保存,HFile是HBase中KeyValue数据的存储格式。 | ||
MemStore的作用不是为了加快写速度,而是为了对Row Key进行排序。 | ||
|
||
> Hlog | ||
这里看到了内存写入,我们学过MySQL原理的同学肯定第一时间就想到了内存有丢失的风险,同理,Hbase在解决这个问题的时候,也是通过一个顺序写日志的方式解决的,也就是HLog。顺序写磁盘,直接写内存,批量持久化内存,所以说性能还是非常高的。 | ||
在HBase中,每个RegionServer只需要维护一个WAL,所有Region对象共用一个WAL,而不是每个Region都维护一个WAL。这种方式对于多个Region的更新操作所发生的的日志修改,只需要不断地追加到单个日志文件中,不需要同时打开并写入多个日志文件,这样可以减少磁盘寻址次数,提高写性能。 | ||
|
||
> HMaster | ||
到这里我们还有一个最关键的点不知道,HRegion到底是怎么划分的呀,具体是谁管理的,那么这个时候就需要一个Master来管理了。 | ||
**首先,读写请求都不经过Hmaster**,只是为了管理。HMaster会处理 HRegion 的**分配或转移**。如果我们HRegion的**数据量太大的话**,HMaster会对**拆分**后的Region重新分配RegionServer。(如果**发现失效的HRegion**,也会将失效的HRegion分配到正常的HRegionServer中) | ||
Master只负责各种协调工作,比如建表、删表、移动Region、合并等操作。这些操作有一个共性的问题:就是需要跨RegionServer。所以,HBase就将这些工作分配给了Master服务。这种结构的好处是大大降低了集群对Master的依赖。而Master节点一般只有一个到两个,一旦宕机,如果集群对Master的依赖度很大,那么就会产生单点故障问题。在HBase中即使Master宕机了,集群依然可以正常地运行,依然可以存储和删除数据。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
--- | ||
title: 原理 | ||
date: 2024-04-10 18:34:01 | ||
permalink: /pages/67ef0c/ | ||
categories: | ||
- 技术学习 | ||
- hbase | ||
tags: | ||
- | ||
author: | ||
name: lan-dian | ||
link: https://github.com/lan-dian | ||
--- | ||
## 存储引擎 | ||
|
||
底层存储引擎是基于LSM-Tree数据结构设计的。写入数据时会先写WAL日志,再将数据写到写缓存MemStore中,等写缓存达到一定规模后或满足其他触发条件才会flush刷写到磁盘,这样就将磁盘随机写变成了顺序写,提高了写性能。**每一次刷写磁盘都会生成新的HFile文件**。 | ||
随着时间推移,写入的HFile会越来越多,查询数据时就会因为要进行多次io导致性能降低,为了提升读性能,HBase会定期执行compaction操作以**合并HFile**。 | ||
|
||
> 读优化 | ||
此外,HBase在读路径上也有诸多设计,其中一个重要的点是设计了**BlockCache读缓存**。这样以后,读取数据时会依次从BlockCache、MemStore以及HFile中seek数据,再加上一些其他设计比如**布隆过滤器、索引**等,保证了HBase的高性能。 | ||
|
||
## 写流程 | ||
|
||
1. 访问Zookeeper获取具体交互的服务器地址,并且缓存在客户端。 | ||
2. 追加到WAL中,写在MemStore中**并且排序**。 | ||
1. 会先写WAL再写内存,如果同步日志失败,那么内存也会被回滚 | ||
3. MemStore刷盘(基本上包含了所以刷盘的可能性,非常值得学习) | ||
1. Region的**memstore太大**了会刷盘 | ||
2. **写入的太快会阻塞写入**,抛出异常,并且刷新memstore | ||
3. 总的RegionServer太大也会刷盘,因为都在一个JVM内存里面,所以在**内存占用过高的时候,减少gc的影响**,从大到小开始刷数据 | ||
4. **定时刷新**,避免如果没有数据写入就不刷新到磁盘的问题 | ||
5. **更新次数太多**,如果更新的量很小,但是更新的次数多,也不会导致内存扩张,所以在更新次数多的时候也刷盘 | ||
6. **WAL文件太大**的时候也会刷新 | ||
|
||
## 读流程 | ||
|
||
1. 访问Zookeeper获取具体交互的服务器地址,并且缓存在客户端。 | ||
2. 分别在 Block Cache(读缓存),MemStore 和 Store File(HFile)中查询目标数据,并将查到的所有数据进行合并。**此处所有数据是指同一条数据的不同版本(time stamp)或者不同的类型(Put/Delete)**。 | ||
|
||
### Block Cahce | ||
|
||
HBase缓存不像对传统缓存理解的一样读了内存如果有数据就不再读磁盘,因为它是以时间戳进行版本控制的,所以**不能只读内存**。 | ||
HBase读数据无论如何都会扫描HDFS磁盘,只是在 BlockCache 中存在的数据不再读取,**BlockCache 只是提高了读磁盘的效率**。如:磁盘中有数据A和B,BlockCache 中有数据A,则扫描磁盘时只读取B,不再读取A。 | ||
所以 HBase 是写比读快(读不仅扫磁盘,还要合并选取数据)。 | ||
|
||
## 合并 | ||
|
||
由于memstore每次刷写都会生成一个新的HFile,**且同一个字段的不同版本(timestamp)和不同类型(Put/Delete)有可能会分布在不同的 HFile 中,因此查询时需要遍历所有的 HFile**。 | ||
为了减少 HFile 的个数,以及清理掉过期和删除的数据,会进行 StoreFile Compaction。Compaction 分为两种,分别是 Minor Compaction 和 Major Compaction。 | ||
|
||
> Minor Compaction | ||
Minor Compaction 是指选取一些**小的、相邻的 HFile 将他们合并成一个更大的 HFile**。默认情况下,Minor Compaction 会删除所合并 HFile 中的 TTL 过期数据,但是不会删除手动删除(也就是 Delete 标记作用的数据)不会被删除。 | ||
|
||
> Major Compaction | ||
Major Compaction 是指将一个 **Store 中所有的 HFile 合并成一个 HFile**,这个过程会清理三类没有意义的数据:**被删除的数据**(打了 Delete 标记的数据)、**TTL 过期数据**、**版本号超过设定版本号的数据**。 | ||
另外,一般情况下,Major Compaction 时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此,生产环境下通常关闭自动触发 Major Compaction 功能,改为手动在业务低峰期触发。 | ||
|
||
### 触发时机 | ||
|
||
> MemStore Flush | ||
HBase 每次Flush 之后,都会判断是否要进行 Compaction,一旦满足 Minor Compaction 或 Major Compaction 的条件便会触发执行。 | ||
|
||
> 后台线程周期性检查 | ||
这里主要考虑的是一段时间内没有写入仍然需要做 Compact 检查。 | ||
|
||
> 手动触发 | ||
compact、major_compact | ||
|
||
## 数据切分 | ||
|
||
默认情况下,**每个 Table 起初只有一个 Region,随着数据的不断写入,Region 会自动进行拆分**。刚拆分时,**两个子 Region 都位于当前的 Region Server**,但处于负载均衡的考虑,**HMaster 有可能会将某个 Region 转移给其他的 Region Server**。 | ||
数据切分会造成数据倾斜(region 大小分布不均),带来热点数据问题。所以建表时进行预分区来尽量避免这种问题。 | ||
|
||
## Hfile结构 | ||
|
||
HFile中包含了**一个多层索引系统**。这个多层索引是的HBase可以**在不读取整个文件的情况下查找数据**。这一多层索引类似于一个B+树。 | ||
文件结尾指向meta block。因为meta block是在数据写入硬盘操作的结尾写入该文件中的。文件的结尾同时还包含一些别的信息。比如 bloom filter 及时间信息。bloom filter可以帮助HBase加速数据查询的速度。因为HBase可以利用 bloom filter 跳过不包含当前查询的键的文件。时间信息则可以帮助HBase在查询时跳过读操作所期望的时间区域之外的文件。HFile的索引在HFile被打开时会被读取到内存中。这样就可以保证数据检索只需一次硬盘查询操作。 | ||
|
||
## 并发控制 | ||
|
||
> 写写并发 | ||
多个写入/更新同时进行会导致数据不一致的问题,HBase通过获取**行锁**来实现写写并发,如果获取不到,就需要不断重试等待或者自旋等待,直至其他线程释放该锁。拿到锁之后开始写入数据,写入完成之后释放行锁即可。这种行锁机制是实现写写并发控制最常用的手段,MySQL也使用了行锁来实现写写并发。 | ||
|
||
> 读写并发 | ||
HBase中**MVCC**机制实现主要分为两步: | ||
(1) 为每一个写入/更新事务分配一个**Region级别自增的序列号**。 | ||
(2) 为每一个读请求分配一个已完成的最大写事务序列号。 | ||
|
||
## 宕机恢复 | ||
|
||
当Region Server宕机的时候,其所管理的region在这一故障被发现并修复之前是不可访问的。ZooKeeper负责根据服务器的**心跳信息**来监控服务器的工作状态。当某一服务器下线之后,ZooKeeper会发送该服务器下线的通知。HMaster收到这一通知之后会进行恢复操作。 | ||
HMaster会首先将宕机的Region Server所管理的region分配给其他仍在工作的活跃的Region Server。然后HMaster会将该服务器的**WAL分割并分别分配给相应的新分配的Region Server进行存储**。新的Region Server会读取并顺序执行WAL中的数据操作,从而重新创建相应的MemStore。 | ||
|
||
## 高可用 | ||
|
||
HBase使用Hadoop的HDFS作为底层存储,数据被分散存储在多个RegionServer上。每个RegionServer都负责管理一部分数据,这些数据通过HBase的分区机制进行划分。同时,**HBase还使用了Hadoop的复制机制,将数据复制到多个RegionServer上,以实现数据的冗余备份**。当一个RegionServer出现故障时,系统可以从其他RegionServer上获取备份数据,实现高可用性。 | ||
|
||
|
||
|