什么是HBASE(一) PUT流程想到的
HBase的整体架构:
HBase的体系整体氛围两部分,client和Server集群;Server集群由三部分组成,zookeeper,用于存储HBaes集群的元数据信息(比如META表所在的region server);Master负责DDL操作以及管理操作(比如扩容等);Region Server则是负责表存储,这里的表有两列表一类是meta表,用于保存region信息(比如rowkey范围);另外是表中数据;
到底什么是HBase,HBase就是hadoop生态里面的数据库;有人认为HBase就是存储引擎,因为HBase数据并没有负责存储,hdfs才是负责存储;但是要清楚hdfs技术定位是文件操作系统,和Linux的FS对标;其实关系型数据库本身也是不负责存储,存储是交给操作系统的文件系统来处理的。
HBaseClient发送一个PUT请求,这个put请求其实并没有直接发送过来,而是首先放置到了HTable缓存起来,然后将会批量的发送到HBase的Region Server中,Region Server首先是将put的数据写入到WAL(Write Ahead Log,对应HLog类)中,然后写入到Memstore中;当memstore的达到一定阈值后,将会flush到HFile中。
下图是HBase的交互流程图。
针对上面的流程做几点说明:
1. 关于hbase client的HTable将会缓存起来,毕竟对于大批量的put来讲,每次put都来一次RPC是不经济的;于是hbase client默认是会将数据缓存起来,当达到一定大小(currentWriteBufferSize)之后将会自动批量一次性发送给region server端;如果不希望缓存,直接发送,就需要设置htbale的autoflush设置为true,这样每次put都会被直接发送到region server端。如果currentWriteBufferSize始终都没有被满足,那么在将会在table.close()的时候进行批量提交。
2. 在put之前,还有一个问题要解决,就是如何来确定regin server;主要的依据就是rowkey,根据rowkey来和各个region的startRowkey,endRowKey进行比较;然后确定region,这部分处理是通过访问zookeeper获得META表所在region server,然后再获取.META.表内信息,获取rowkey范围信息,进而确定region信息,然后根据region来获得region server;
3. 为什么需要WAL+memstore,这是因为hdfs的文件被设计为一旦被写入,就无法进行修改;而HBase其实设计为希望数据被排序放置,另外每次都刷hdfs也不经济;于是设计出了一套WAL+memstore的机制,put数据首先写入到wal(HLog)中,wal也是写到hdfs中;然后写入到内存memstore中,每个column family一个memstore,这个其实还有一个HBase的内部组织的问题,见下图;
当memstore的总量达到了指定大小之后,将会进行flush,flush的过程下面有介绍;这样的机制不仅减少了和hdfs的交互,保证了每个hfile的有序性,还可以保证可用性,即使hbase挂了,再启动,memstore数据是丢了,但是可以通过wal进行恢复memstore的数据,然后进行flush;wal的作用和mysql的binlog有些类似,都是可以用于追溯;不过mysql比hbase可靠性要高得多。但是强调一点,memstore的flush是全部column family的flush,而且每个memstore(column family)都会形成一个hfile文件;这个也是后面要介绍的合并操作的缘由。所以如果数据分布不均衡的化,可能会因为某个memstore达到一定大小,产生了hfile,导致其他几乎没有数据的memstore也刷了一个hfile;因此cf的设计很重要;所以cf的数量要控制,能用一个就用一个。
hdfs文件的这种不修改(只能append)的方式,hbase做了一些妥协处理;
1)删除,不是物理删除而是设置了一个墓碑标记(tombstone marker);只有在文件合并(compact)的时候,才会真实的删除内容;
2)更新,并不是真实的删除,而只是做了版本,这个是hbase版本功能的由来吧;我推测设置默认版本为三个,到了第四个版本的时候,第一个版本就被标记为了tombstone;
4. flush的过程其实是和HDFS交互的过程,首先是访问HDFS的客户端,然后调用其写文件的API,Client端将会和HDFS的NameNode进行交互,返回副本地址;因为hdfs写默认是向三个地方写,就近的DataNode(一般就是hdfs client所在的机器),然后是两个副本地址;hdfs的这种机制保证了region server就是hfile所在的机器,减少网络开销(但是在配置HBase的时候,hbase的region server的分布要和HDFS的data node的分布一致);这样未来hbase client在发起检索的时候可以直接定位到region server,其实也就是定位到了对应的hdfs的data node上面了。
flush之后,将会把这部分操作内容从WAL中清除掉,为WAL瘦身。
5. 每次flush其实都是小文件,这种机制将会导致一些问题,比如查文件需要在多个文件中切换;于是hbase设计了大小两种合并;一种基于时间,对于某段时间内的文件进行合并,这个是小合并;另外一种是大合并,就是把所有的文件都合并,形成一个大的文件。在合并的过程我推测应该是一个文件内容遍历重组的过程,怎么讲呢,因为tombstone的数据在这个阶段被物理删除;另外,因为hfile都是顺序文件,所以一定在合并的时候对数据进行重排。
下图描述的是写入WAL到memstore,最后flush到hdfs的过程;Flush之后还会有大合并,小合并;
最右侧描述了HFile的发展过程;首先是sequenceFile,后来转到MapFile,但是v0.20HBase推出了自己的HFile格式:HFile v1.0,到了HBase 0.92版本,推出了HFile v2。
参考:
介绍Memstore的触发机制
讲述HFile的演变史
《HBase企业应用实战开发》核心概念章节