HBASE的寻址机制和存储机制
hbase的寻址机制
- hbase 的一个表最终拆分成 一个个region,每一个region可能会存储在不同的regionserver上,会有独立编号。
- 无论是 读|写 操作,首先要快速定位到 写|读 是在哪一个region中进行,然后到对应的存储的regionserver上找对应的region,直接读取数据。
快速定位哪一个region存在哪一个regionServer上的过程,就叫寻址,要想知道寻址机制,需要先了解hbase的存储机制。
hbase的存储机制
hbase的存储机制:0.96及之前版本
- 原始表:存储原始数据的
- .meta表: 原始表 按照rowkey 创建索引,是原始表的索引目录。
- -root-表:.meta表的索引表,是终极索引,无论多大,都只有一个region,不可分割。
- -root- 表的存储位置:zookeeper中,zk中存储的是hbase的寻址路径的开始。
hbase的寻址过程:0.96及之前版本
1)客户端先去访问zk,获取-root-表的存储regionserver位置,以及region编号。
2)访问 -root- 表的region,获取 .meta表对应的regionserver的region编号。
3)访问.meta表,需要查询的rk所在的region,获取原始数据的regionserver的region编号。
4)开始真正的访问对应的regionserver的region 表数据。
3个来回之后,才找到真正要访问的的regionServer和region表。
hbase的存储机制:0.96之后版本
- 原始表:存储原始数据
- .meta 表:存储原始数据的索引,. meta 无论多大,只存储在一个region上,不可分割,这个region也只会存储在一个regionserver上。
- .meta表的寻址路径,也就是.meta表的位置,最终存储在zookeeper上。
hbase的寻址过程:0.96之后版本
1)客户端先去访问zk,获取.meta 表的存储regionserver位置以及region编号。
2)访问.meta 表的region,获取原始数据表对应的regionserver的region编号。
3)开始真正的访问对应的regionserver的region 表数据。(开始读取数据)
0.96版本之后,对寻址做了优化,提升查询效率。
现在假设我们要从 user_info 里面寻找一条 RowKey 是 rk0001 的数据。那么我们应该遵循以下步骤:
- 从.META.表里面查询哪个 Region 包含这条数据。
- 获取管理这个 Region 的 RegionServer 地址。
- 连接这个 RegionServer,查找对应region,扫描region,查到这条数据。
系统如何找到某个 RowKey (或者某个 RowKey range)所在的 region。
bigtable 使用三层类似 B+树的结构来保存 region 位置。
第一层是 zookeeper 里面保存的数据,它持有 root region 的位置。
第二层 root region 是.META.表的第一个 region 其中保存了.META.表其它 region 的位置。通过root region,我们就可以访问.META.表的数据。
第三层是.META.,它是一个特殊的表,保存了 hbase 中所有数据表的 region 位置信息。
说明:
1、root region 永远不会被 split,保证了最多需要三次跳转,就能定位到任意 region。 2、.META.表每行保存一个 region 的位置信息,rowkey 采用表名+表的最后一行编码而成。3、为了加快访问,.META.表的全部 region 都保存在内存中。4、client 会将查询过的位置信息保存缓存起来,缓存不会主动失效,因此如果 client 上的缓存全部失效,则需要进行最多 6 次网络来回,才能定位到正确的 region(其中三次用来发现缓存失效,另外三次用来获取位置信息)。
写机制
写数据包括 put 和 delete
- 1、客户端根据 rowkey 经过3次往返(寻址机制)找到对应的 region 所在的 regionserver。
- 2、client 向 regionserver 提交写请求。
- 3、regionserver 找到目标 region。
- 4、region 检查数据是否与 schema(表结构:表名-列族) 一致,如果一致,允许写入;如果不一致,直接返回,报错。
- 5、如果客户端没有指定版本,则获取当前系统时间作为数据版本。如果给定时间版本,以客户端给定的为准。
- 6、将更新写入 WAL log。
- 7、将更新写入对应的store中的 Memstore。
- 8、判断 Memstore 的是否需要 flush 为 Storefile 文件。
当memstore 的文件大小达到阈值128M的时候,开始执行flush,形成多个storefile文件。 - 9、当一个store中的storefile个数达到一定的阈值的时候就会触发compact 合并。
-
- minor compact
storefile个数达到一定阈值进行的合并叫:minor compact 小合并
触发条件在 hbase-default.xml文件中已经配置了。
- minor compact
<property>
<name>hbase.hstore.compactionThreshold</name>
<value>3</value>
<description>
If more than this number of HStoreFiles in any one HStore
(one HStoreFile is written per flush of memstore) then a compaction
is run to rewrite all HStoreFiles files as one. Larger numbers
put off compaction but when it runs, it takes longer to complete.
</description>
</property>
当一个store中的stotrefile文件个数达到3个时候,触发这个 minor compact 操作。将多个(3个)storefile 合并为 1个storefile文件。
minor compact 没有任何逻辑操作的,只有物理操作。简单地将多个storefile的文件进行累加合并,只是在文件个数上减少了。数据不会执行真正的删除,将需要删除的数据打了标记。这个数据对客户端不可见。
-
- major compact
当达到一定的阈值的时候,进行major compact。
- major compact
<property>
<name>hbase.hregion.majorcompaction</name>
<value>604800000</value>
<description>The time (in miliseconds) between 'major' compactions of all
HStoreFiles in a region. Default: Set to 7 days. Major compactions tend to
happen exactly when you need them least so enable them such that they run at
off-peak for your deploy; or, since this setting is on a periodicity that is
unlikely to match your loading, run the compactions via an external
invocation out of a cron job or some such.</description>
</property>
默认7天触发一次。将7天的多个hfile,合并为一个hfile。
执行逻辑操作。
major compact 进行数据的真正删除,将所有的需要删除的数据进行真正的合并并删除。真正需要删除的数据有:
1)执行delete操作的数据。
2)版本超过给定需要保存的版本的数据,过期版本数据。eg:数据最多保存2个版本,实际存了3个版本,那么第一个存入的数据就过期了。
3)TTL (Time To Live)过期的数据。
- 10、判断一个store中的所有文件的总大小是否达到region切分的标准。
- 11、达到region切分的标准,就会region切分,hmaster 进行新的region的重新分配。
总结: 写数据流程:
Client 写入 -> 存入 MemStore,一直到 MemStore 满 -> Flush 成一个 StoreFile,直至增长到一定阈值 -> 触发 Compact 合并操作 -> 多个 StoreFile 合并成一个 StoreFile,同时进行版本合并和数据删除 -> 当 StoreFiles Compact 后,逐步形成越来越大的 StoreFile -> 单个 StoreFile大小超过一定阈值后,触发 Split 操作,把当前 Region Split 成 2 个 Region,Region 会下线,新 Split 出的 2 个孩子 Region 会被 HMaster 分配到相应的 HRegionServer 上,使得原先 1 个Region 的压力得以分流到 2 个 Region 上由此过程可知,HBase 只是增加数据,并不真正写入磁盘。增加数据、删除操作,是在 Compact 阶段做的,所以,用户写操作只需要进入到内存即可立即返回,从而保证 I/O 高性能。
读机制
读数据包括 get | scan
- 1)客户端根据 rowkey 经过3次往返(寻址机制)找到对应的 region 所在的 regionserver。
- 2)客户端开始向对应的regionserver的region发送读数据的请求。
- 3)客户端会先在region的对应的store的memstore(blockcache)中进行读取。
- 4)如果memstore 中有数据,直接返回。
- 5)如果没有数据,到hfile 文件中进行读取(磁盘读取)。