
HBase 是 Google Bigtable 的开源实现,是一个 sparse, distributed, persistent multi- dimensional sorted map,map 的 key 由 rowkey,column family,qualifier,timestamp,type 组成,并据此排序。
架构图
Hbase 的架构是存算分离的,方便扩展,底层存储使用 HDFS,HBase 相关组件提供计算功能,部分元数据存储在 ZK 中。架构图如下:
数据模型
table:表,一个表包含多行数据
row:行,一行数据包含一个唯一标识 rowkey、多个 column 以及对应的值。在 HBase 中,一张表中所有 row 都按照 rowkey 的字典序由小到大排序。
column:列,与关系型数据库中的列不同,HBase 中的 column 由 column family(列簇)以及 qualifier(列名)两部分组成,两者中间使用":"相连。比如 contents:html,其中 contents 为列簇,html 为列簇下具体的一列。column family 在表创建的时候需要指定,不能随意增减。一个 column family 下可以有任意多个 qualifier,也就是 HBase 中的列可以动态增加,理论上甚至可以扩展到上百万列。
timestamp:时间戳,每个 cell 在写入 HBase 的时候都会默认分配一个时间戳作为该 cell 的版本,当然,用户也可以在写入的时候自带时间戳。HBase 支持多版本特性,即同一 rowkey、column 下可以有多个 value 存在,这些 value 使用 timestamp 作为版本号,版本越大,表示数据越新。
cell:单元格,由五元组(row, column, timestamp, type, value)组成的结构,其中 type 表示 Put/Delete 这样的 *** 作类型,timestamp 代表这个 cell 的版本。这个结构在数据库中实际是以 KV 结构存储的,其中(row, column, timestamp, type)是 K,value 字段对应 KV 结构的 V。在每个 HFile 文件中,KV 按序存储,按照 KV 中 key 的字典序进行排序。先比较 rowkey,rowkey 小的排在前面;如果 rowkey 相同,再比较 column,即 column family:qualifier,column 小的排在前面;如果 column 还相同,再比较时间戳 timestamp,即版本信息,timestamp 大的排在前面(也就是最新的排在前面)。
数据文件的物理存储
HFile 在 HDFS 上按照 table、region、column family 分目录存储,如下所示:
/hbase/data/default/table-name/region-name/column-family-name/hfile-name
其中 default 是默认 namespace,一个列簇下的所有 HFile 文件都在同一个列簇目录下,按照文件的新旧程度放置在 LSM-tree 的不同 level,每个 level 只有一个 HFile 文件。
Compact
Minor Compact:选取部分尺寸小的、LSM-tree 中相邻 level 的 HFile,将它们合并成更大的 HFile,但是不清理 type 为 deletes 或 expired versions 的数据。
Major Compact:将一个 Store 中所有的 HFile 合并成一个 HFile,由于只有一个 HFile 文件,这个文件可能会很大,这也是 HFile 文件结构中索引是多层结构的原因。这个过程还会完全清理三类无意义数据:被删除的数据、TTL 过期数据、版本号超过设定版本号的数据。
RegionServer
一个 RegionServe r由一个(或多个)HLog、一个 BlockCache 以及多个 Region 组成。其中,HLog 用作 WAL;BlockCache 可以将 block 缓存在内存中以提升数据读取性能;Region 是 HBase 中数据表的一个数据分片,一个 RegionServer 通常会负责多个 Region 的数据读写,Region 可以来自相同或不同表。Region 由多个 Store 组成,一个 Store 负责一个列簇的数据,比如一个表中有两个列簇,这个表的所有 Region 就都会包含两个 Store。每个 Store 包含一个 MemStore 和多个 HFile,用户数据写入时会先写 HLog,然后将对应列簇数据写入相应的 MemStore,一旦 MemStore 大小超过设定阈值,系统就会将 MemStore 中的数据落盘形成 HFile 文件,HFile 存放在HDFS上。
这里 HLog、MemStore、HFile 与 LevelDB 中对应的相关文件:日志文件、memtable、sstable,格式也有相似之处,先不展开介绍。
ACID
HBase 保证单行事务的 ACID 特性,跨行无法保证。作为该限制的结果之一就是不支持辅助索引,对数据项的更新需要同时对辅助索引进行更新,而这不是原子的。单行事务的保证是通过将单行中涉及的多个 column 修改编码为一条 WAL 来完成的,即使跨多个 column family 也可以。
hbase:meta 表
hbase:meta 表就是分区表,分区表作用可以参考
狂奔的蜗牛:可扩展性之数据分区
该表存储了 Region 到 Region Server 的映射,用来路由 client 读写请求、进行负载均衡等 *** 作。该表的所在 RS 节点存储在 ZK 上。表结构如下:
Key
Region key of the format ([table],[region start key],[region id])
Values
info:regioninfo (serialized HRegionInfo instance for this region)
info:server (server:port of the RegionServer containing this region)
info:serverstartcode (start-time of the RegionServer process containing this region)
当 Region 发生 split 时候,values 中会新建两列:info:splitA 和 info:splitB。这两列代表两个新的子 Region,列值同 info:regioninfo 一样,也是 serialized HRegionInfo instance,在 Region 完成 split 后,对应的旧行将被删除。
空的 start key 表示 HBase 一张表的 start 或者 end,hbase:meta 表中如果一个 Region 有空的 start key,那么这个 Region 是对应表的第一个 Region,如果 start key 和 end key 都为空,那么这个 Region 是表的唯一 Region。
Region 的划分使用范围分区策略,按照 rowkey 划分。
数据写入
客户端将用户的写入请求进行预处理,并根据集群元数据定位写入数据所在的 RegionServer,将请求发送给对应的 RegionServer。
RegionServer 接收到写入请求之后,先写 WAL,再写入对应 Region 列簇的 MemStore。
当 Region 中 MemStore 容量超过一定阈值,系统会异步执行 flush *** 作,将内存中的数据写入 HFile。
数据读取
读取有 get 和 scan 两种 API,get 通常根据给定 rowkey 查找一行记录,scan 通常根据给定的 start key 和 stop key查找多行满足条件的记录。技术实现上,get 是特殊的 scan,scan 的条数为 1。scan 并没有设计为一次 RPC 请求,因为一次 scan *** 作的扫描结果可能数据量非常大。HBase 会根据设置条件将一次大的 scan 拆分为多个 RPC 请求,每个 RPC 请求称为一次 next 请求,每次只返回规定数量的结果。
1、client 根据集群元数据定位查询数据所在的 RegionServer,将请求发送给对应的 RegionServer。
2、对包含用户查询数据的 Region 的 HFile 进行过滤,过滤方法主要有三种:
根据 KeyRange 过滤:因为 HFile 中所有 KeyValue 数据都是有序的,所以如果待检索 row 范围 [ start row,stop row ] 与文件起始 key 范围 [ first key,last key ] 没有交集,就可以过滤掉该 HFIle。
根据 TimeRange 过滤:HFile 中元数据有一个关于该 File 的 TimeRange 属性 [ miniTimestamp, maxTimestamp ],如果待检索的 TimeRange 与该文件时间范围没有交集,就可以过滤掉该 HFile;另外,如果该文件所有数据已经过期,也可以过滤淘汰。
根据布隆过滤器进行过滤:根据待检索的 rowkey 获取对应的 Bloom Block 并加载到内存(通常情况下,热点 Bloom Block 常驻内存),使用布隆过滤器中的数据确定待检索 rowkey 是否一定不存在于该 HFile。
3、从剩余 HFile 中读取待查找 key:首先根据 HFile 中的索引定位目标 block,然后看 Block Cache 中是否存在,不存在则从 HDFS 中 seek 读取,之后在 block 中顺序查找指定 key。由于不同 HFile 文件之间的数据是无序的,因此需要归并排序,实际上 MemStore 使用 MemStoreScanner 读取数据,HFile 使用 StoreFileScanner 读取数据,最后 KeyValueScanner 将使用 MemStoreScanner 和多个 StoreFileScanner 来构建最小堆,保证所有数据有序。
1 可以通过使用Java中的Scanner类来获取input中的变量。
2 Scanner类可以实例化一个对象,并使用next()或nextLine()方法来获取输入的值。
3 例如,如果我们想获取一个整数,我们可以使用以下代码:
```
Scanner scanner = new Scanner(Systemin); //创建Scanner对象
int num = scannernextInt(); //获取输入的整数
```
这样就能够获取input中的变量并赋值给num变量。
4 除了Scanner,还可以使用System类的getenv()方法来获取系统环境变量,或者使用SystemgetProperty()方法来获取JVM系统属性。
在Java中,可以使用Scanner类从控制台读取输入。以下是一个读取圆半径并计算其面积的示例代码:
在上述代码中,通过创建Scanner对象实例,并使用 nextDouble() 方法从控制台获取用户输入的圆的半径值。随后,使用输入的半径值计算圆的面积并输出结果。
主要基于两个方面的原因:
Client首先会从ZooKeeper中获取元数据hbase:meta表所在的RegionServer,然后根据待读写rowkey发送请求到元数据所在RegionServer,获取数据所在的目标RegionServer和Region(并将这部分元数据信息缓存到本地),最后将请求进行封装发送到目标RegionServer进行处理。
3)KeyValueScanner合并构建最小堆
最小堆管理Scanner可以保证取出来的KeyValue都是最小的,这样依次不断地pop就可以由小到大获取目标KeyValue集合,保证有序性。
1)检查该KeyValue的KeyType是否是Deleted/DeletedColumn/DeleteFamily等
2)检查该KeyValue的Timestamp是否在用户设定的Timestamp Range范围
3)检查该KeyValue是否满足用户设置的各种filter过滤器
4)检查该KeyValue是否满足用户查询中设定的版本数
以上就是关于region下所有的hfile默认存放全部的内容,包括:region下所有的hfile默认存放、input中的变量怎么调用java、java从控制台输入圆半径怎么输入等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)