架构图


架构图摘自网络,后续例子使用个人集群进行讲解

hbase 写数据流程 简述hbase写数据流程_zookeeper

HBase写流程详解

假如我们有三台机器,ruozedata001 ruozedata002 ruozedata003

写流程:

首先要写数据,要有客户端、zookeeper

架构图中的:Put:table/RowKey/CF/Column: V,例如插入一条数据:

数据表:bigdata:student ,RowKey:1001,info列族,字段name,值为zhangsan

1.Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server,请求到meta信息后,zookeeper将信息返回给客户端。

例如meta信息为ruozedata001

2.访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey, 查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以 及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问。

例如RegionServer信息为ruozedata003

3.与目标 Region Server 进行通讯

例如获取到的RegionServer信息为RegionServer信息为ruozedata003,那么zookeeper会向ruozedata003发送写的请求。

4.此时会进行真正的写操作。

例如此时会将数据写入到ruozedata003中

写操作的详细步骤:

  • (a)将数据顺序写入(追加)到 WAL
  • (b)将数据写入对应的 MemStore,数据会在 MemStore 进行排序

5.向客户端发送 ack,通知客户端写操作结束

6.等达到 MemStore 的刷写时机后,将数据刷写到 HFile。

关于HBase读的流程实际操作查看

1.在zookeeper中,找 meta表所在的位置 

通过客户端工具zkCli.sh,进入zookeeper

get /hbase/meta-region-server

在zookeeper中,可以查看到HBase的RegionServer的信息,可以看到meta表在ruozedata001来维护

[zk: ruozedata001:2181(CONNECTED) 6] get /hbase/meta-region-server
�regionserver:60020�ac�%���PBUF

ruozedata001������-
cZxid = 0xd0000012a
ctime = Sat Oct 12 01:33:50 CST 2019
mZxid = 0xd0000012a
mtime = Sat Oct 12 01:33:50 CST 2019
pZxid = 0xd0000012a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 66
numChildren = 0

我们也可以通过HBase web界面来查看meta表在哪台机器维护:

hbase 写数据流程 简述hbase写数据流程_hbase 写数据流程_02

即 客户端找到 meta表在ruozedata001来维护

2.请求ruozedata001,读regision server内容

进入hbase shell执行

scan 'hbase:meta'

查看我们创建的 bigdata:student表,一共四个列

主要看的信息, info:server(标红部分)

column=info:server

column=info:serverstartcode,

在info:server中能够找到维护这张表的机器,例如执行 scan 'hbase:meta' 获取到的信息:value=ruozedata003:60020

bigdata:student,,1570815704167.86c3a column=info:regioninfo, timestamp=1570815744872, value={ENCODED => 86c3a55ff244676f7ae33bec6bc88311, NAME =>
 55ff244676f7ae33bec6bc88311.         'bigdata:student,,1570815704167.86c3a55ff244676f7ae33bec6bc88311.', STARTKEY => '', ENDKEY => ''}
 bigdata:student,,1570815704167.86c3a column=info:seqnumDuringOpen, timestamp=1570815744872, value=\x00\x00\x00\x00\x00\x00\x00\x05
 55ff244676f7ae33bec6bc88311.
 bigdata:student,,1570815704167.86c3a column=info:server, timestamp=1570815744872, value=ruozedata003:60020
 55ff244676f7ae33bec6bc88311.
 bigdata:student,,1570815704167.86c3a column=info:serverstartcode, timestamp=1570815744872, value=1570815142190
 55ff244676f7ae33bec6bc88311.

该信息也可以通过hbase的web界面,通过table regions 找到

hbase 写数据流程 简述hbase写数据流程_数据_03

3.客户端请求ruozedata003服务器的RegionServer,并进行数据写入的操作

注意

早期版本hbase,存在 -ROOT-  表用来存储meta信息,但是新版本不存在-ROOT-表,

历史版本流程:

zookeeper获取-ROOT- 表的信息,-ROOT-存储 meta表信息,meta表存储数据表信息。

早起考虑到 meta表过大,可能或对meta表进行切分,如果meta表切分之后,就无法通过zookeeper获取到meta表完整的信息

关于数据写入WAL的详细流程

可在hbase源码:HRegion.java中查看到详细步骤

https://github.com/apache/hbase/blob/rel/1.4.10/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Region.java

 

1.Try to acquire as many locks as we can,and ensure we accquire at least one

尽可能多地获取锁,并确保至少获取一个,用到的锁是 java.util.concurrent.locas.Lock;来保证读写分离

获取行锁、Region更新共享锁: HBase中使用行锁保证对同一行数据的更新都是互斥操作,用以保证更新的原子性,要么更新成功,要么失败。

2.Update any LATEST_TIMESTAMP timestamp

更新最后的时间戳

即我们写入数据的时候,hbase添加的时间戳,即hbase此时用的是hbase的时间戳

3.Buil WAL edit

构建 WAL,仅仅在内存构建,但是没有写入到hdfs。

4.Append the final edit to WAL. Do not sync wal.

把最后的内容追加到最后的 WAL中,此时不需要执行sync操作

5.Write back to memstore

把数据写入内存中。

HBase中每个列族都会对应一个store,用来存储该列族数据。每个store都会有个写缓存memstore,用于缓存写入数据。HBase并不会直接将数据落盘,而是先写入缓存,等缓存满足一定大小之后再一起落盘。

6.Release row locks, etc.

释放锁以及共享锁

7.Sync wal.

同步

8.Advance mvcc. This will make this put visible to scanners and getters.

WAL写入成功,会将数据写入到内存中

如果Sync失败,将memstore中已经写入的数据移除,即执行回滚操作。