Hbase数据存储需要依赖HDFS,集群交互需要依赖zookeeper。首先说明zookeeper在Hbase中的作用。其实zookeeper在各分布式组件中的作用都是大同小异的。

Zookeeper

zookeeper在大数据领域中能占据如此重要的地位,是因为解决了分布式系统中的最基本问题:

        1、提供极低延迟超高可用的内存kv数据服务。

        2、提供中心化的服务故障发现服务

3、提供分布式锁,counter和Queue等协调服务

zookeeper也是集群模式,zookeeper的主节点是通过活跃的节点选举机制选出来的。在zookeeper集群中,任何zookeeper节点都可能成为主节点。各节点都存储同一份数据,通过ZAB协议作为数据行一致算法。

zookeeper核心特性:

1、多类型节点:可以分为四种类型的节点

持久节点

创建后一直存在,直到主动进行删除

临时节点

临时节点生命周期和客户端session绑定,session失效节点会被自动清理。

临时节点下不能创建子节点

持久顺序节点

具有持久性和顺序性。持久性和上面持久节点一致。

顺序性指父节点会维护一份时序,记录每个子节点的先后顺序。

临时顺序节点

包含了临时性和顺序性,和上面一致

2、watcher机制:

        是一种事件异步反馈机制,类似于公众号订阅推送,或者观察者模式。

watcher设置:可以为所有读操作设置watcher,包括getChildren(),exists(),getData()。

      getChildren()设置子节点watcher,关注子节点的创建,删除等

      exists()和getData()设置数据watcher,关注数据更新,子节点创建删除等。

watcher触发反馈:客户端与服务端长连接。一但发生事件,就会通知给服务端。

watcher特性:事件是一次性的触发器。触发一次之后需要重新设置watcher。

3、session机制:客户端通过配置逐个尝试连接zookeeper服务器,直到建立连接成功或者都不能连接而失败。

        连接一但建立就会创建session,zookeeper长期没有收到任何请求,时间超过超时时间,session就会过期清理,临时节点和watcher时间都会清理。

zookeeper典型应用场景

在hbase中,hbase通过zookeeper实现了高可用和regionserver宕机检测分布式锁等功能。

以分布式锁为例,主要实现以下步骤。

      1、客户端通过create创建临时顺序节点

      2、客户端通过getchildren获取所有已经创建的子节点

      3、获取到的所有子节点都会带有序号(时序),如果序号最小,则认为当前客户端拿到了锁

      4、如果不是最小的,客户端会找到最小的节点,追后设置watcher进行监听。

      5、监听的节点执行完成释放锁,客户端收到通知调用getchildren(),回到第三步

Hbase在Zookeeper中的布局:

meta-region-server

存储hbase:meta元数据表所在的RegibServer地址

master/backup-masters

记录主备Master节点,主节点只有一个在运行,备用节点可以有多个

table

集群中所有表的信息

region-in-transition

regionserver在这个节点中记录region状态,master通过监听对应节点,region状态发生变化后通知master,master更新region在元数据表中的状态和在内存中的状态

table-lock

表锁。因为一个表会被分割成多个region,所以在DDL操作时,需要通过锁保持数据一致。每次执行DDL操作时,都需要获取对应的表锁。

online-snapshot

在线快照操作。master通过zookeeper下达快找指令给regionserver,regionserver通过zookeeper将快照状态反馈给master

replication

hbase复制功能

splitWAL/

recovering-regions

用于hbase故障恢复,为提高恢复速度,zookeeper协调所有regionserver都参与日志回放

rs

集群中正在运行的regionserver

HDFS: 分布式文件系统

        目前主流的大数据存储都是存储在hdfs上,其实现的高可用,容灾备份等机制,在大量廉价机器上布置也可以实现系统数据的准确性。

        HDFS擅长大文件(文件存储按照块进行划分)的顺序读,随机读,顺序写。HDFS也是主从架构的,大多数大数据组建基本都是主从架构,通过主节点的备份来实现高可用。

        HDFS分为以下4个服务组成

NameNode

线上一般部署两个,一个active(工作的),一个standby(备份)。在主节点发生故障后,zookeeper会将备份节点变为活跃节点。

比较重要的是,namenode需要存储所有操作步骤,和Hbase的Hlog一样,通过记录操作,在出现问题后,可以通过Hlog进行执行恢复。

NameNode会将原数据存储在FsImage和EditLog中。每次文件元数据的写入,都是EditLog的一次顺序写,NameNode在内部的线程,会周期性的将变更写成Fsimage,持久化在磁盘。生成的时间点为t,那么在这之前的EditLog就是过期可删除的。

DataNode

数据存放的节点,一个数据块的多个备份会根据副本存放策略存放在不同的DataNode上。

JournaNode

内部通过Paxos协议保证数据一致性,保证两个NameNode中的数EditLog数据保持一致。

ZKFailoverController

实现NameNode的主备切换

Hdfs的写流程

        1、向NameNode申请一个唯一文件表示fileld,返回一个OutPutStream,包括了将要写出的DataNode的队列。

        2、在数据写入的过程中,数据都是按照块进行存储,写满了一个数据块之后,会重新执行第一步。在写入数据块时,并不是一次直接写入大量数据,而是将数据分为更小的部分packet(64k),每次写满一个packet,就会将它放入到Dataqueue中。之后通过异步线程的方式把数据写入到DataNode,packet会循环的流转在NameNode分配的DataNode之间(第一步分配的几个DataNode),数据都写入成功,就会发送ACK(确认回执)返送到Dfs client,packet写入成功。

        3、关闭OutPutStream,若不进行关闭,则会导致缓存(Packet和PacketQueue)在DFSClient中的数据丢失。

这里有两种数据写入的方式:

        hflush:数据成功发送到所有的Datanode上,并且至少有一个DataNode,正常运行hflush返回成功。但是数据可能还没有写入磁盘,仍在缓存中。

        hsync:数据不但都发送到了DataNode上,并且数据都持久化在了磁盘上。

HDFS数据读取:

        DFS申请Block(多个),DFSClient会选择一个合适的DataNode创建BlockReader进行数据读取(影响因素有是否同一个机架,是否在同一个网段,是否跨网进行传输)

        HDFS读取流程很简单,但对于HBase的读取性能影响重大,尤其Locality和短路度两个核心因素:

        Locality:一般情况下,DataNode(磁盘消耗型)和Hbase的RegionServer(内存Cpu消耗型)部署在统一台机器上。对某个DFSClient来说,这台机器的Locality可以定义为:
                locality=该文件存储在本地机器的字节数之和/该文件总字节数  =>(文件分为好几个Block,是否都存储在同一个机器上)。这样Locality是一个[0-1] 之间的数字。Locality越高,本地化率越高,文件都存储在本地。

        短路读:需要读取的Block和DFSClient在同一台机器上,则可以直接读取本地服务器上的数据,这样节省了TCP协议读取数据的网络开销。

        HBASE在HDFS中的布局:

.hbase-snapshot

snapshot文件存储目录

.tmp

临时文件目录,主要用于Hbase表的创建和删除。创建时会先在tmp目录下执行,成功后将tmp目录下的表信息移动到实际目录。删除时即哪个表目录移动到tmp下,一段时间后删除

MasterProcWALs

用于实现可恢复的分布式DDL操作。MasterProcedure功能使用WAL记录DDL执行的中间状态,异常发生时通过WAL回放继续执行后续操作。

WALs

存储集群所有RegionServer的Hlog日志

archive

文件归档目录。

        1、Hfile的删除都会临时放到该目录

        2、进行Snapshot或者升级时

        3、Compaction(hbase hfile合并)删除hfile时。

corrupt

存储损坏的Hlog或Hfile文件

data

存储集群中所有Region的Hfile文件。其路径构造为

        /hbase/data/default(表schema)/test(表名)/region名称/TK(列簇名)/hfile名

除了存储hfile外,还存储一些重要的子目录和子文件。

  .tabledesc:表文件描述

  .tmp:表临时目录。主要存储Flush和Compaction过程中的中间结果。Memostore数据刷到Hfile中时,会先存储在此目录,成功后在移动到实际对应的目录下。

  .regioninfo:region描述文件

  recovered.edits:存储故障恢复时,该Region需要回放的WAL日志数据。RegionServer宕机之后,那些没来得及flush到磁盘的数据需要通过WAl回放。WAL首先会按照Region进行切分,回放时只需要回放自己的WAL数据片段即可。


集群启动初始化的时候,创建集群唯一id

hbase.version

Hbase版本号

oldWALs

WAL归档目录,一旦一个WAL中记录的多有kv数据都已经从MemoStore持久化到了hfile中,那么该WALs就会移动到此目录

本文内容均来自《Hbase原理与实践》的读书心得。有兴趣的可以读一读原书。