1、数据查找和传输
LSM
- LSM树,输入数据首先被存储在日志文件,这些文件内的数据完全有序,当有日志文件被修改时,对应的更新会被先保存在内存中来加速查询。
- 当系统经历过多次数据修改,且内存空间被逐渐占满,LSM树会把有序的键记录对写到磁盘中,同时创建一个新的数据存储文件。内存中保存的内容可丢弃掉。
- 所有节点都是满的并按页存储
多次刷写后产生许多数据存储文件,后台线程就会自动将小文件聚合成大文件。
查询时先查找内存中的存储,再查找磁盘上的文件。
删除是一种特殊的更改,查找时会跳过删除过的键。
https://blog.csdn.net/MingYueZh/article/details/80839868
在没有太多修改时,B+树表现更好,因为这些修改要求执行高代价的优化操作以保证查询能在有限时间内完成。
在内存中排序,将随机写转换成顺序写,保证稳定的数据插入速率。
2、存储
HBase透明地操作存储在HDFS上文件的概览主要处理预写日志和实际数据文件。主要由HRegionServer管理。
- 客户端首先联系ZooKeeper子集群查找行键,获取含有-ROOT-的region服务器来完成。
- 通过-ROOT-的region服务器可以查到.META.表中对应的region服务器名。
- 通过.META.服务器来获取客户端查询行键数据所在region的服务器名。
HRegionServer负责打开region,并创建对应的HRegion实例。为每个表的HColumnFamily创建Store实例,Store实例包含一个或多个StoreFile实例,是HFile轻量封装,HFile实际存储数据文件。每个Store还有对应一个MemStore。
写
- 是否需要写到Hlog预写日志中。
- 一旦数据写入到WAL中,数据就会被放到MemStore中。如果MemStore满了就会进行刷写。
- 刷写通过另一个HregionServer线程处理,会把数据写成HDFS中的一个新HFile。
文件
- 根级文件,被HLog实例管理的WAL文件,存储在.logs目录中。一个Region服务器的所有region共享同一组HLog文件。
- 表级文件,位于文件系统中HBase根木兰路下。每张表目录包括一个名为.tableinfo顶层文件,存储表对应序列化后的HTableDescriptor。
- region级文件,包含regioninfo文件。在WAL回放时,未提交的修改都会被写入到每个region的一个单独的文件中。一旦region超过了配置中region大小的最大值,region就需要拆分,会创建一个对应的splits目录
- 合并文件,minor合并负责重写最后生成的几个文件到一个更大的文件中。major合并吧所有文件压缩成一个单独文件。
HFile格式
- 文件是可变长度,固定的块是File Info和Trailer,Trailer是持久化到文件结束时写入的。
- Index块记录Data和Meta块的偏移量。
- 块大小建议8KB~1MB。如果主要涉及顺序访问则较大的块合适,较小的块更有利于随机数据访问,不过需要更多的内存存储索引。
KeyValue格式
HFile中的每个KeyValue都是一个低级的字节数据,允许零复制访问数据。
KeyValue格式
键包含行键、列族名、列限定符等。
3、WAL
MemStore存储在内存中相对是不稳定的,WAL可以解决这一问题。
WAL存储了对数据的所有更改。
所有修改先保存到WAL再传递给MemStore
- HRegion先写WAL然后在放入MemStore
- memstore在到达一定大小后,异步地连续写入到文件系统中。数据以一种不稳定的状态存放在内存中,即使再服务器完全崩溃的情况下,WAL也能够保证数据不会丢失。
HLog类
HRegion被实例化时,HLog实例会被当做一个参数传入到HRegion的构造器中。
追踪修改,内部使用一个进程安全的AtomicLong,当region打开它的存储文件时,它读取存储在每一个HFile中meta域中最大的序列号,并且如果这个序列号大于之前记录的序列号,它就会被初始化以反映存储在哪里结束以及从哪里继续存储。
- HLogKey会存储region和表明以及序列号。
- WALEdit是客户端发送的修改封装成的实例。
回放
集群启动或服务失效时会进行回放。
region首先检查recovered.edits目录是否存在。由于文件是按照含序列ID文件名排序的,region可以按照序列ID的顺序来恢复。如果这个ID比硬盘上存的ID小就会被胡烈。
一旦recovered.edits文件中的文件都处理完,且其中的数据更改也都被写入到硬盘后,该文件删除。
4、读路径
HBase每个列族使用多个存储文件来进行存储,这些文件包含着实际的数据单元或KeyValue实例。
所有存储文件都是不可变的,从这些文件中删除一个特定的值是做不到的。
实际上数据存储在分离的KeyValue实例中,横跨任意数目个存储文件。
- HBase中没有可以使我们直接访问特定行或列的索引文件。HFile中最小的单元是块,Store实例必须载入整个可能存储这所需数据的块并且扫描这个块。
- 扫描是通过RegionScanner类实现的,该类为每一个Store实例获取一个StoreScanner,每个Store实例代表着一个列族。
- StoreScanner类合并了Store实例包含的存储文件和memstore。基于布隆过滤器或时间戳的筛选发生的地方。
- StoreScanner类包含了QueryMatcher,记录到底哪个KeyValue需要被包含在最终结果中。
- RegionScanner在内部使用KeyValueHeap类,并按时间戳排序来处理存储扫描器。
skipped根据时间戳和布隆过滤器。
ResultScanner会重复调用next()直到到达结束行或表的结尾,或者已经读取到缓存设定的足够多行。
5、region查找。
- ROOT表用来查询多有.META.表中region的位置。只有一个root region。
- .META.表汇总查找用户表对应的region的位置。
- 目录表中的行键由region的表名、起始行和ID连接而成。
如果region、meta region和root region缓存失效,还需要额外3次查询。
6、复制
HBase复制中最基本的架构模式是主推送模式。
集群复制架构
- WALEdit会被复制程序检查,并以列族为单元复制数据。
- 另一个线程从日志中读取数据,只有可复制的KeyValue被保存下来。当缓冲区满了或读取到文件尾,缓冲区中的修改被发送到集群一个随机的region服务器上。
- region服务器收到这些修改后,会顺序读取这些修改信息,并把它们分成不同的缓冲区,每张表一个缓冲区。
- 在主集群region服务器中,当前WAL中被复制的位置会在ZooKeeper中注册。
网友评论