1. HBase的结构(基础 & 重点!!!)
图片来源:尚硅谷大数据HBase课程
HBase的结构非常重要!!!一定要牢记分清!
对比MySQL记忆
HBase | MySQL |
---|---|
NameSpace | DataBase |
Table | Table |
Row key | id |
columns family | columns... |
Region | SELECT * FROM TABLE WHERE nu BETWEEN AND j |
Store | SELECT columns... FROM TABLE WHERE id BETWEEN AND j |
2. Read
2.1 读数据的流程
- Step1:客户端递交请求到ZooKeeper,获取HBase集群的meta表存放在哪一个RegionServer(Linux设备)上
meta表记录了HBase中所有表的元数据,包括各个表的Region的元数据(分配在哪个RegionServer上、Row key范围等等)。注意:meta本身也是一张表,因此也需要存储在RegionServer上
- Step2:客户端根据ZooKeeper返回的meta表找到meta表存放的RegionServer,并和该RegionServer建立通信,读取meta表信息,获取查询指令【查询指令中包含条件:Table & Row key】需要检索的Region存放在哪个RegionServer上
Step1得到的mata表元数据(meta表的存储位置)和Step2得到的Region的元数据(该Region的所在位置和Row key范围)会被客户端作为缓存,一定时间内查询相近数据时能够直接读取缓存进行定位,提高查询效率
- Step3:客户端得到需要的Region位置后,与该Region所在的RegionServer进行通信并读取需要的数据记录(重点分析步骤)
2.2 Step3的深入分析
对Step3的深入分析前首先必须明确Store的结构:MemStore(内存) + HFile(写入到磁盘的文件) + Block Cache(一个缓存区,也是内存)。MemStore和Block Cache都是实时运行的内存,前者存放着尚未Flush为HFile的数据,后者则保存着之前读取的缓存记录(缓存的是HFile中的数据记录,MemStore本身也是内存,没必要进行缓存)
以上图为例,当Block Cache中无缓存时,读取数据的数据流程相当于将HFile1和HFile2加载到内存MemStore中,与MemStore中本就存在的数据记录一起进行筛选,返回符合查找条件的数据记录。而如果在HFile2中找到了满足条件的记录,Block Cache会对HFile2进行缓存,下一次的查找就会检索Block Cache、MemStore和HFile1中的数据,少了一次文件的IO,会提升查找效率
3. Write
3.1 写数据的流程
写数据的流程前两步和读数据一样,都是经过ZooKeeper定位到所需要进行操作的RegionServer
一般来说,写入数据的流程应该是先写入到内存,[进行排序(写入多条时)],然后再刷写到磁盘上。但这个机制在大数据场景下有很严重的风险,当大量数据写入并在MemStore中进行排序时,如果设备出现断电等故障,将会丢失大量数据。因此在Hbase中,RegionServer维护了一个WAL文件,充当临时的写入文件,当发生写入时,数据行先是写入到WAL中,然后再加载到MemStore中进行排序后刷写到HFile中,这样即便中途断电等故障,事后重启HBase服务也不会丢失这些数据。
3.2 Flush机制
那么,Hbase什么时候,或者说什么条件下才会触发刷写(Flush)机制,将MemStore中的数据写入磁盘成为HFile文件呢?
- 手动Flush:在HBase客户端命令行中执行
flush + 表名
即可将当前表的所有Store中MemStore的所有数据排序后刷写为一个HFile文件 - MemStore达到内存限制:阻塞写的Flush和不阻塞写的Flush
<!--触发该条件的Flush不会阻塞写操作,可并发进行-->
<!--单个MemStore的最大内存,当实际达到这个限制,会触发Flush-->
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value>
<description>
Memstore will be flushed to disk if size of the memstore
exceeds this number of bytes. Value is checked by a thread that runs
every hbase.server.thread.wakefrequency.
</description>
</property>
<!--触发以下参数的Flush会阻塞写操作,即Flush完成前不支持写入-->
<!--Region中所有MemStore实际大小总和为默认单个MemStore分配内存大小的倍数-->
<property>
<name>hbase.hregion.memstore.block.multiplier</name>
<value>4</value>
</property>
<!--可以理解为一个安全的设置,有时候集群的“写负载”非常高,写入量一直超过flush的量,
这时,我们就希望memstore不要超过一定的安全设置。在这种情况下,写操作就要被阻塞一直
到memstore恢复到一个“可管理”的大小, 这个大小就是默认值是堆大小 * 0.4 * 0.95,也就
是当regionserver级别的flush操作发送后,会阻塞客户端写,一直阻塞到整个regionserver级
别的memstore的大小为 堆大小 * 0.4 *0.95为止 -->
<property>
<name>hbase.regionserver.global.memstore.size.lower.limit</name>
<value></value>
</property>
<!--整个RegionServer中为所有Store分配的MemStore内存大小占堆内存的比例,默认为0.4-->
<property>
<name>hbase.regionserver.global.memstore.size</name>
<value></value>
</property>
- 到达自动刷写时间
<!--这个时间是指内存中最后一条数据最后一次编辑的时间之后如果1小时没有数据操作,将会触发自动刷写-->
<property>
<name>hbase.regionserver.optionalcacheflushinterval</name>
<value>3600000</value>
<description>
Maximum amount of time an edit lives in memory before being automatically
flushed. Default 1 hour. Set it to 0 to disable automatic flushing.
</description>
</property>
- WAL文件数量达到限制:当WAL文件的数量超过32个时,region 会按照时间顺序依次进行刷写,直到WAL文件数量减小到32以下
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。