Skip to content

Commit

Permalink
hbase
Browse files Browse the repository at this point in the history
  • Loading branch information
lan-dian committed Apr 10, 2024
1 parent bf667a9 commit 2db0236
Show file tree
Hide file tree
Showing 5 changed files with 231 additions and 3 deletions.
6 changes: 5 additions & 1 deletion docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export default defineConfig4CustomTheme<VdoingThemeConfig>({
{
text: '技术学习',
link: '/web/',
items: [
{ text: "docker", link: '/pages/479a6c/' },
{ text: "hbase", link: '/pages/0d9ac7/' }
]
},
{ text: '关于', link: '/about/' },
{
Expand Down Expand Up @@ -281,7 +285,7 @@ export default defineConfig4CustomTheme<VdoingThemeConfig>({

markdown: {
lineNumbers: true,
extractHeaders: ['h1','h2', 'h3', 'h4', 'h5', 'h6'], // 提取标题到侧边栏的级别,默认['h2', 'h3']
extractHeaders: ['h2', 'h3', 'h4', 'h5', 'h6'], // 提取标题到侧边栏的级别,默认['h2', 'h3']
},

// 监听文件变化并重新构建
Expand Down
2 changes: 1 addition & 1 deletion docs/00.目录页/01.技术学习.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pageComponent:
name: Catalogue
data:
path: 02.技术学习
description: 工作中常用的中间件
description: 研发常用中间件学习
title: 技术学习
date: 2024-04-08 15:26:53
permalink: /web/
Expand Down
2 changes: 1 addition & 1 deletion docs/02.技术学习/01.docker/01.入门.md
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:
Expand Down
117 changes: 117 additions & 0 deletions docs/02.技术学习/02.hbase/01.入门.md
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宕机了,集群依然可以正常地运行,依然可以存储和删除数据。
107 changes: 107 additions & 0 deletions docs/02.技术学习/02.hbase/02.原理.md
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上获取备份数据,实现高可用性。



0 comments on commit 2db0236

Please sign in to comment.