《HBase原理与实践》笔记

《HBase原理与实践》

HBase

概念

HBase是一个稀疏的、分布式的、多维排序的Map。

特征

多维:这个特征是相对于普通Map而言,HBaseMap中的Key是多维(四元组)的,(<rowkey, column family: qualifier, type, timestamp>, value)。

稀疏:即不是所有的列都需要有值,可以为空(不需要占用存储空间),这也是为了可以随时扩充列(否则每添加一个列都需要向其他列插入空值)。

排序:构成HBase的KV在同一个文件中都是有序的,排序的规则是,RowKey > Column family:Qualifier > timestamp(timestamp大的排在前面)。这个特征对于HBase的读取性能有很大的提升。

分布式:HBase中的数据分布在整个集群中。

体系结构

IMG_8553

HBase中的重要组件

Zookeeper

  • 实现Master的高可用性:系统中同一时间内只能有一个Master处于工作状态,当Master挂掉时,需要快速选出另一台机器当选Master,以保证集群正常运行。
  • 管理系统核心元数据:比如存储当前系统的所有RegionServer集合,保存系统元数据表hbase:meta表所在的RegionServer地址。
  • 参与RegionServer的宕机恢复:Zookeeper通过心跳可以感知RegionServer是否宕机,如果宕机,需要通知Master采取措施。
  • 实现分布式锁:HBase中对一张表进行各种管理操作(alter)需要先加表锁,防止其他用户对同一张表进行管理操作。

Master

  • 处理用户的各种请求:包括建表、修改表、权限操作、切分表、合并数据分区以及Compaction。
  • 管理集群中所有的RegionServer:包括RegionServer中的Region的负载均衡、RegionServer的宕机恢复以及Region的迁移等。
  • 清理过期的日志和文件:Master每隔一段时间都会检查HDFS中的HLog是否过期、HFile是否已经被删除,并在过期之后将其删除。

RegionServer

  • WAL(HLog):HLog在HBase中有两个核心作用:①用于实现数据的高可用性:HBase写数据时,先将数据写入HLog中,然后在合适的时机将数据flush到磁盘。②实现HBase集群间的主从复制,通过回放主集群推送过来的HLog日志实现主从复制。
  • BlockCache:HBase系统中的读缓存。客户端从磁盘读取数据后会将一块数据缓存的内存中。一个Block默认为64K,由物理上的多个KV数据组成,BlockCache利用了时间局部性和空间局部性原理,前者表示最近将读取的KV数据很可能与当前读取的KV在地址上是临近的。后者表示一个KV数据现在被访问,那么近期它有可能会再次被访问,主要由两种实现(LRUBlockCache和BucketCache)。
  • Region:数据表的一个横向切片,当数据表大小超过一定阈值时会水平切割,分裂为多个Region,Region是集群负载均衡的基本单位,通常一个表的多个Region会被分散在集群的多个机器上。
  • Store:一个Region由多个Store组成,每一个Column family对应一个Store。每一个Store又由一个Memstore和多个HFile组成。Memstore被称为写缓存,用户写入的数据会被先写入到Memstore,当MemStore写满之后,系统会异步的将数据flush成一个HFile文件。随着HFile文件越来越多,系统会执行Compact操作,将这些HFile文件合并成一个或多个HFile文件。

HDFS

  • HBase实际存储数据的地方,用户数据文件、HLog日志文件最终都会落盘到HDFS,并且HBase内部封装了一个名为DFSClient的HDFS客户端组件,负责对HDFS的实际数据进行读写访问。

缺点

  • 无法进行复杂的聚合操作(Join、Group By),如果业务中需要使用聚合运算,可以在HBase中假设Phoenix组件或者Spark组件,前者适用于小规模的OLTP场景,后者适用于大规模的OLAP场景。
  • 没有实现二级索引功能,即只能指定RowKey的查找范围,而无法指定其他的列。一般用Phoenix实现。
  • HBase原始不支持全局跨行操作,只支持单行事务模型。一般用Phoenix弥补此缺陷。

设计一个类似HBase的KV数据库

核心设计

IMG_8554

MiniBase是一个标志的LSM树索引结构,分为内存部分和磁盘部分。

内存部分

内存部分为MenStore,客户端不断写入数据,当MemStore的内存超过一定阈值时,会把MemStore flush到磁盘形成一个DiskStore。并且MemStore分成MutableMemstore和ImmutableMemstore两个部分,这两个都是由ConcurrentSkipListMap组成。初始时,MutableMemstore = new ConcurrentSkipListMap(); ImmutableMemstore = null;,当需要flush时,令ImmutableMemstore = MutableMemstore;MutableMemstore = new ConcurrentSkipListMap();

磁盘部分

磁盘部分分为多个DiskStore,由多个DiskFile组成。并且每执行一次flush操作,都会生成一个新的DiskFile,并且当DiskStore达到一定数量时,会进行Compact操作,将多个DiskFile合并成一个DiskStore。

由于磁盘空间很大,内存空间相对较小,所以DiskFile必须分成多个块,一次IO操作只读取一小部分的数据,通过读取多个数据块来完成一次区间的扫描。

IMG_8555

DataBlock:用来存储有序的KeyValue集合,一个Block大约为64KB。

IndexBlock:一个DiskFile中仅有一个IndexBlock。主要用来存储多个DataBlock的索引数据,每个DataBlock都应该包含4个字段。

  • lastKV:该DataBlock的最后一个KV。
  • offset:该DataBlock在DIskFile中的偏移量。查找时,用offset和size直接去文件中读取DataBlock的数据。
  • size:该DataBlock占用的字节长度。
  • bloomFilter:该DataBlock内所有KeyValue计算出的布隆过滤器字节数据。即输入多个字节数组,通过过滤器生产算法生成过滤器,然后可以通过过滤器判断某个字节数据可能存在或者一定不存在

MetaBlock:一个DiskFile中仅有一个MetaBlock,并且MetaBlock是定长的,主要用MetaBlock来存储DiskFile级别的元数据信息,主要包括以下4种信息。

  • fileSize:该DIskFile的文件总字节数,可以用来判断文件是否损坏。
  • blockCount:该DiskFile中拥有的Block数量。
  • blockIndexOffset:该DiskFile中IndexBlock的偏移位置。
  • blockIndexSize:IndexBlock的字节长度。
如何使用

当用户需要读取DiskFile中key='abc’的数据时,可以按照以下流程进行IO读取:因为MetaBlock长度是确定的,所以可以很容易定位到MetaBlock的位置,并且读取数据,然后获取到IndexBlock的偏移和长度,通过偏移和长度获得IndexBlock中的数据,这样就获取了这个DIskFile中所有的DataBlock索引,可以通过二分查找来确定对应DataBlock的offset和size,就能顺利完成DataBlock的IO读取。

KeyValue的设计
public class KeyValue {
    private byte[] key;
    private byte[] value;
    private Op op;
    private long sequenceId;
}
/*
sequenceId字段:每次Put/Delete都会被分配一个自增的唯一sequenceId,
这样没一个操作都对应一个sequenceId,读取的时候只能得到小于等于当前sequanceId
的Put/Delete操作,这样保证了本次读取不会得到未来某个时间点的数据,
实现了最简单的Read Commited的事务隔离级别。
*/

LSM树种存放的是操作记录,而不是真实数据(因为要保持顺序写,所以不直接修改数据)。

读写流程

写入流程:当写入MemStore之后,需要考虑进行flush操作时,需要令ImmutableMemstore = MutableMemstore;MutableMemstore = new ConcurrentSkipListMap();执行此代码时需要确保没有写入操作,所以应该用一个读写锁来控制写入操作和flush的切换操作的互斥,当需要执行写入操作时,先拿到读锁,写完再释放;当需要执行切换操作时,需要拿到写锁,切换完之后再释放锁。

读取操作:因为数据可能会存在MutableMemstore或者ImmutableMemStore或者多个DIskFile的DataBLock中,并且三者都是有序的KV集合,所以可以对三者进行多路归并排序,然后过滤掉不符合条件的版本,将正确的KV返回给用户。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值