概念:
数据模型:表由行和列组成。表格的“单元格”(cell)由行和列的坐标交叉决定,是有版本的。默认情况下,版本号是自动分配的
Hbase内部保留名为hbase:meta的特殊目录表(catalog table)。他们维护着当前集群上所有区域的列表、状态和位置。
NoSQL的基础
1、not only sql
2、回顾:关系型数据库:Oracle、MySQL等 ——> 面向行
适合insert,update,delete
不适合查询
3、常见的NoSQL数据库
基于Key——Value模型:Redis(基于内存)
前身:MEMCached(不足:不支持持久化)
面向列的模型:Hbase、Cassandra
适合select(查询)
基于文档型:MongoDB
文档:BSON文档(json的二进制)
1.Hbase的表结构
BigTable:大表
思想:通过牺牲存储的空间,来换取性能
把所有的数据存入一张表,完全违背了关系型数据库范式的要求
HBase 基于HDFS之上的NoSQL数据库、列式数据库
表 ——> 目录
数据 ——> 文件
2.Hbase 在ZK中保存数据
配置信息、Hbase集群结构信息
表的元信息
实现Hbase的HA(high avaibility)高可用性
3.Hbase配置信息
4.操作Hbase
4.1 Web Console网页:端口-16010
4.2 命令行
hbase shell
1)创建表
create 'students','info','grade'
创建表'students'相当于创建一个目录
2)查看表结构
desc 'students'
describe 'students'
hbase:003:0> desc 'students'
Table students is ENABLED
students
COLUMN FAMILIES DESCRIPTION
{NAME => 'grade', BLOOMFILTER => 'ROW', IN_MEMORY => 'false', VERSIONS => '1', KEEP_DELETED_CE
SIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
{NAME => 'info', BLOOMFILTER => 'ROW', IN_MEMORY => 'false', VERSIONS => '1', KEEP_DELETED_CEL
IONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s)
Quota is disabled
Took 0.0337 seconds
3)插入数据
put 'students','stu001','info:name','Tom'
put 'students','stu001','info:age','24'
put 'students','stu001','info:gender','Male'
put 'students','stu001','grade:math','80'
put 'students','stu002','info:name','Mike'
4)查询数据
scan 相当于:select * from students
scan '表名'
get 相当于 select * from students where rowkey=?
get '表名','行健'
get 'student','stu001'
5)关闭和开启表
disable '表名'
enable '表名'
6)删除表
disable '表名'
drop '表名'
7)清空表中的数据
truncate '表名'
truncate本质:先删除表,再重建
日志:
Truncating 'students' table (it may take a while):
- Disabling table...
- Truncating table...
0 row(s) in 4.0840 seconds
5.数据保存的过程
注意:region分裂
HBase 架构
ZooKeeper 作为分布式的协调。RegionServer也会把自己的信息写到ZooKeeper中。
HDFS是Hbase运行的底层文件系统
RegionServer,数据节点,存储数据
Master,RegionServer要实时向Master报告信息。Master知道全局的RegionServer运行情况,可以控制RegionServer的故障转移和Region的切分。
架构细化
HMaster 是Master Server的实现,负责监控集群中的Region Server实例,同时是所有metadata改变的接口,在集群中,通常运行在NameNode上
HMasterInterface暴露的接口,Table(createTable,modifyTable,removeTable,enable,disable),ColumnFamily(addColumn,modifyColumn,removeColumn),Region(move,assign,unassign)
Master运行的后台线程:LoadBalancer线程,控制region来平衡集群的负载。CatalogJanitor线程,周期性的检查hbase:meta表。
HRegionServer 是RegionServer的实现,服务和管理Regions,集群中RegionServer运行在DataNode
HRegionInterface暴露接口:Data(get,put,delete,next,etc.),Region(splitRegion,compactRegion,etc.)
RegionServer后台线程:CompactSplitThread,MajorCompactionChecker,MenStoreFlusher,LogRoller
Regions,代表table,Region有多个Store(列簇),Store有一个Memstore和多个StoreFiles(HFiles),StoreFiles的底层是Block。
Hbase 存储设计
在Hbase中,表被分割成多个更小的块然后分散的存储在不同的服务器上,这些小块叫做Regions,存放Regions的地方叫做RegionServer。Master进程负责处理不同的RegionServer和Region。HRegionServer除了包含一些HRegions之外,还处理两种类型的文件用于数据存储
HLog,预写日志文件,也叫做WAL(write-ahead log)
HFile 真实的数据存储文件
Hlog
MasterProcWAL:HMaster记录管理操作,比如解决冲突的服务器,表创建和其他DDLs等操作到它的WAL文件中,这个WALs存储在MasterProcWALs目录下,它不像RegionServer的WALs,Hmaster的WAL也支持弹性操作,就是如果Master服务器挂了,其他的Master接管的时候继续操作这个文件。
WAL记录所有的Hbase数据改变,如果一个RegionServer在MemStore进行Flush的时候挂掉了,WAL可以保证数据的改变被应用到。如果写WAL失败了,那么修改数据的完整操作就是失败的。
通常情况,每个RegionServer只有一个WAL实例。在2.0之前,WAL的实现叫做HLog
WAL位于/hbase/WALs/ 目录下
MultiWAL:如果每个RegionServer只有一个WAL,由于HDFS必须是连续的,导致必须写WAL连续的,然后出现性能问题。MultiWAL可以让RegionServer同时写多个WAL并行的,通过HDFS底层的多管道,最终提升总的吞吐量,但是不会提升单个Region的吞吐量。
WAL的配置
// 启用multiwal
<property>
<name>hbase.wal.provider</name>
<value>multiwal</value>
</property>
HFile
HFile 是Hbase在HDFS中存储数据的格式,它包含多层的索引,在Hbase检索数据的时候就不用完全的加载整个文件。索引的大小(keys的大小,数据量的大小)影响block的大小,在大数据的情况下,block的大小设置为每个RegionServer 1GB也是常见的。
HFile生成方式
起初,HFile中并没有任何Block,数据还存在于MemStore中。
Flush发生时,创建HFile Writer,第一个空的Data Block出现,初始化后的Data Block中为Header部分预留了空间,Header部分用来存放一个Data Block的元数据信息。而后,位于MemStore中的KeyValues被一个个append到位于内存中的第一个Data Block中:
注:如果配置了Data Block Encoding,则会在append KeyValue的时候进行同步编码,编码后的数据不再是单纯的KeyValue模式。Data Block Encoding是为了降低KeyValue结构性膨胀而提供的内部编码机制。
读写简流程
HBase Region管理
HFile 合并
每个RegionServer包含多个Region,而每个Region又对应多个Store,每一个Store对应表中一个列簇的存储,且每个Store由一个MemStore和多个StoreFile文件组成。
StoreFile在底层文件系统中由HFile实现,也可以把Store看作由一个MemStore和多个HFile文件组成。MemStore充当内存写缓存,默认大小64MB,当MemStore超过阈值时,MemStore中的数据会刷新到一个新的HFile文件中来持久化存储。
久而久之,每个Store中的HFile文件会越来越多,I/O操作的速度也随之变慢,读写也会延时,导致慢操作。因此,需要对HFile文件进行合并,让文件更紧凑,让系统更有效率。
HFile的合并分为两种类型,分别是Minior合并和Major合并。这两种合并都发生在Store内部,不是Region的合并,如下图所示。
Minor合并
Minor合并是把多个小HFile合并生成一个大的HFile。
执行合并时,Hbase读出已有的多个HFile的内容,把记录写入一个新文件中。然后把新文件设置为激活状态,并标记旧文件为删除。
在Minor合并中,这些标记为删除的旧文件是没有被移除的,仍然会出现在HFile中,只有在进行Major合并时才会移除这些旧文件。对需要进行Minor合并的文件的选择是触发式的,当达到触发条件才会进行Minor合并,而触发条件有很多,例如,在将MemStore的数据刷新到HFile时会申请对Store下符合条件的HFile进行合并,或者定期对Store内的HFile进行合并。
另外,对选择合并的HFile也是有条件的,如下表所示。
参数名配置项默认值备注
minFileToCompacthbase.hstore.compaction.min3至少需要三个满足条件的 HFile 才启动合并
minFileToCompacthbase.hstore.compaction.max10一次合并最多选择 10 个
maxCompactSizehbase.hstore.compaction.max.sizeLong.MAX_VALUEHFile 大于此值时被排除合并,避免对大文件的合并
minCompactSizehbase.hstore.compaction.min.sizeMemStoreFlushSizeHFile 小于 MemStore 的默认值时被加入合并队列
在执行Minor合并时,系统会根据上述配置参数选择合适的HFile进行合并。Minor合并对HBase的性能是有轻微影响的,因此,合并的HFile数量是有限的,默认最多为10个。
Major合并
Major合并针对的是给定Region的一个列簇的所有HFile,如图1所示。它将Store中的所有HFile合并成一个大文件,有时也会对整个表的同一列簇的HFile进行合并,这是一个耗时和耗费资源的操作,会影响集群性能。
一般情况下都是做Minor合并,不少集群是禁止Major合并的,只有在集群负载较小时进行手动Major合并操作,或者配置Major合并周期,默认为7天。另外,Major合并时会清理Minor合并中被标记为删除的HFile。
Region的相关知识
Region在HBase中的角色
Table (HBase表)
Region (Region)
Store (每个Region的每个列簇独立存储)
MemStore (MemStore每个Store有一个,用于在内存中保存数据)
StoreFile (StoreFile对应于Store,是具体存储在磁盘的文件)
Block (Blocks是HDFS上的存储单元)
Region的管理
一般来说对于每个Region Server,官方推荐最好是控制Region的数量在20-200个、大小在5-20Gb左右。
为什么要控制Region的数量呢?
1、默认MemStore需要2MB的空间用来存储数据,如果一台机器上有1000个Region,每个有两个列簇,那就需要3.9GB的数据。
2、如果同时以某个相同的频率更新所有的Region,当同时进行数据持久化的时候也会有问题
3、Master对于维护大量的Region有很大的性能问题,因为在平衡Region的时候,在ZK中的操作都是同步的。
4、Region Server需要维护Region的索引信息
Region Server如何管理Region
启动
1、HMaster 创建 AssignmentManager
2、AssignmentManager查看当前的Region分配信息
3、满足条件后,通过LoadBalancerFactory创建LoadBalancer,1.0后的版本默认是StochasticLoadBalancer
Region的状态机
HBase中每个Region自己维护其在hbase:meta表中的信息。
状态机中包含下面几种状态:
offline:region离线没有开启
opening:region正在被打开
open:region正在打开,并且region server通知了master
failed_open:region server打开失败
closing:region正在被关闭
closed:region server正在关闭,并且已经通知了master
failed_close:region server关闭失败了
splitting:region server通知master,region正在被切分
split:region server通知master,region已经被切分完了
spliting_new:region是切分过程中新建的文件
merging:region server通知master,region正在合并
merged:region server 通知master,region合并完了
merging_new:region是合并新建出来的
不同的颜色是不同含义:
棕色:离线状态,属于一种短暂的瞬间状态(比如关闭后开启的中间状态)、停止状态或者初始化的时候的状态
绿色:正常的状态,可以支持请求访问
蓝色:短暂的状态
红色:失败
黄色:合并或者切分的状态
灰色:刚开始的状态
各个序号代表不同的操作场景:
1、Master向Region server发起region从offline到openning的状态请求,region server如果没有收到,master会尝试重试几次。RegionServer接收到请求后,region状态变为opening
2、如果Master发起的open请求超过次数,那么无论RegionServer是否已经打开region,master都会命令RegionServer关闭文件,状态变为closing
3、当RegionServer打开region后,会尝试通知Master,让它把region状态修改为open状态
4、如果RegionServer打开失败,会尝试通知Master,让它把region状态修改为closed,并且尝试去其他的RegionServer打开region
5、如果Master尝试几次后,都没有打开region,就会把状态变更为failed_open
6、master通知RegionServer关闭region,如果没有反应,会重试
7、如果RegionServer没有在线,会抛出异常。然后region的状态会变成closing
8、如果RegionServer在线,但是好几次都没响应,就会更新状态为failed_closed。并且把region分配给其他的server
10、再分配之前,master会先把region从closed状态变为offline
11、如果RegionServer正在切分region,会通知master。master把region状态由open变为splitting,并且新增两个region的信息,这两个region都是splitting_new状态
12、如果region切分成功,当前的region状态从splitting变成split;新增的两个region状态从splitting_new变成open
13、如果切分失败,状态从splitting回到open,两个region也从splitting_new变成offline
14、如果RegionServer想要合并两个region,那么也会先通知master。master把两个region从open变为merging,然后增加一个新的region,状态为merging_new
15、如果合并成功,旧的region状态从merging变为merged,新的region从merging_new变为open
16、如果合并失败,region的状态从merging变回open,新建的一个region状态又变成offline
17、如果管理员通过hbase shell操作分配region,master会尝试把失败的状态变成close
Region的数据本地性
数据本地性通过来自于hdfs client和hdfs block存储的节点差异性,针对数据备份来说,会按照下面的机制进行:
1、第一个备份会优先选择本地node节点上
2、第二个备份会随机选择一个不同的机架
3、第三个备份会在第二个备份所在的机架上,在随机选择一个节点
4、如果还有其他的备份节点,就在集群中随机选择了
这样HBase在刷新或者压缩时,可以体现数据的本地性。如果一个RegionServer出现故障,那么就没有数据本地性可言了,因为它的备份都在其他的节点上。
Region拆分
Region拆分是HBase能够拥有良好扩展性的最重要因素。一旦Region的负载过大或者超过阈值时,它就会被分裂成两个新的Region,如图所示。
这个过程是由RegionServer完成的,其拆分流程如下。
1、将需要拆分的Region下线,阻止所有对该Region的客户端请求,Master会检测到Region的状态为SPLITTING。
2、将一个Region拆分成两个子Region,先在父Region下建立两个引用条件,分别指向Region的首行和末行,这时两个引用文件并不会从父Region中复制数据。
3、之后在HDFS上建立两个子Region的目录,分别复制上一步建立的引用文件,每个子Region分别占父Region的一半数据。复制登录完成后删除两个引用文件。
4、完成子Region创建后,向Meta表发送新产生的Region的元数据信息。
5、将Region的拆分信息更新到HMaster,并且每个Region进入可用状态。
以上是Region的拆分过程,那么,Region在什么时候才会触发拆分呢?常用的拆分策略如下表所示
策略原理描述
ConstantSizeRegionSplitPolicyRegion 中最大 Store 的大小大于设置阈值(hbase.hregion.max.filesize)之后才会触发拆分。 拆分策略原理相同,只是阈值的设置不同拆分策略对于大表和小表没有明显的区分。阈值设置较大时小表可能不会触发分裂。如果阈值设置较小,大表就会在整个集群产生大量的 Region,影响整个集群的性能
IncreasingToUpper BoundRegionSplitPolicy阈值在一定条件下不断调整,调整规则与 Region 所属表在当前 Region 服务器上的 Region 个数有关系很多小表会在大集群中产生大量小 Region,分散在整个集群中
SteppingSplitPolicy阈值可变。如果 Region 个数等于 1,则拆分阈值为 flushsize × 2;否则为 MaxRegionFileSize小表不会再产生大量的小 Region,而是适可而止
DisabledRegionSplitPolicy关闭策略,手动拆分可控制拆分时间,选择集群空闲时间
Region 合并
从Region的拆分过程中可以看到,随着表的增大,Region的数量也越来越大。如果有很多Region,它们中MemStore也过多,会频繁出现数据从内存被刷新到HFile的操作,从而会对用户请求产生较大的影响,可能阻塞该Region服务器上的更新操作。过多的Region会增加ZooKeeper的负担。
因此,当Region服务器中的Region数量达到阈值时,Region服务器就会发起Region合并,其合并过程如下。
1、客户端发起Region合并处理,并发送Region合并请求给Master。
2、Master在Region服务器上把Region移到一起,并发起一个Region合并操作的请求。
3、Region服务器将准备合并的Region下线,然后进行合并。
4、从Meta表删除被合并的Region元数据,新的合并了的Region的元数据被更新写入Meta表中。
5、合并的Region被设置为上线状态并接受访问,同时更新Region信息到Master。
Region 负载均衡
当Region分裂之后,Region服务器之间的Region数量差距变大时,Master便会执行负载均衡来调整部分Region的位置,使每个Region服务器的Region数量保持在合理范围之内,负载均衡会引起Region的重新定位,使涉及的Region不具备数据本地性。
Region的负载均衡由Master来完成,Master有一个内置的负载均衡器,在默认情况下,均衡器每5分钟运行一次,用户可以配置。负载均衡操作分为两步进行:首先生成负载均衡计划表,然后按照计划表执行Region的分配。
执行负载均衡前要明确,在以下几种情况时,Master是不会执行负载均衡的。
均衡负载开关关闭
Master没有初始化
当前有Region处于拆分状态
当前集群中有Region服务器出现故障
Master内部使用一套集群负载评分的算法,来评估HBase某一个表的Region是否需要进行重新分配。这套算法分别从Region服务器中Region的数目、表的Region数、MemStore大小、StoreFile大小、数据本地性等几个维度来对集群进行评分,评分越低代表集群的负载越合理。
确定需要负载均衡后,再根据不同策略选择Region进行分配,负载均衡策略有三种,如下表所示。
策略原理
RandomRegionPicker随机选出两个 Region 服务器下的 Region 进行交换
LoadPicker获取 Region 数目最多或最少的两个 Region 服务器,使两个 Region 服务器最终的 Region 数目更加平均
LocalityBasedPicker选择本地性最强的 Region
根据上述策略选择分配Region后再继续对整个表的所有Region进行评分,如果依然未达到标准,循环执行上述操作直至整个集群达到负载均衡的状态。
Region/Store/StoreFile/Hfile之间的关系
1、Region
table在行的方向上分隔为多个Region。Region是Hbase中分布式存储和负载均衡的最小单元,即不同的Region可以分别在不同的Region Server上,但同一个Region是不会拆分到多个Server上。
Region按大小分隔,表中每一行只能属于一个region。随着数据不断插入表,region不断增大,当region的某个列簇达到一个阈值(默认值)时就会分成两个新的region。
2、Store
每一个region有一个或多个store组成,至少是一个store,hbase会把一起访问的数据放在一个store里面,即为每个ColumnFamily建一个store(即有几个ColumnFamily,也就有几个Store)。一个Store由一个memStore和0或多个StoreFile组成。
注:Hbase以store的大小来判断是否需要切分region
3、MemStore
memStore是放在内存里的。保存修改的数据即keyValues。当memStore的大小达到一个阈值(默认值)时,memStore会被flush到文件,即生成一个快照。目前hbase会有一个线程来负责memStore的flush操作。
4、StoreFile
memStore内存中的数据写到文件后就是StoreFile(即memStore的每次flush操作都会生成一个新的StoreFile),StoreFile底层是以HFile的格式保存。
5、HFile
HFile是Hbase中KeyValue数据的存储格式,是hadoop的二进制格式文件。一个StoreFile对应着一个HFile。而HFile是存储在HFDS之上的。HFile文件格式是基于Google Bigtable中的 SS Table,如下图所示:
Data Block段:保存表中的数据,这部分可以被压缩。Data Block是 HBase I/O的基本单元,为了提高效率。HRegion Server中有基于LRU的Block Cache机制,每个Data Block大小可以在创建一个Table的时候通过参数指定,较大的Data Block有利于顺序scan,小的Data Block有利于随机查询
Meta Block段:保存用户自定义的kv对,可以被压缩。
File Info段:HFile的元信息,不被压缩,用户也可以在这一部分添加自己的元信息,记录了文件的META信息,例如:AVG_KEY_LEN,ACG_VALUE_LEN,LAST_KEY,COMPARATOR,MAX_SEQ_ID_KEY等
Data Block Index段:Data Block的索引。每条索引的key是被索引的block的第一条记录的key
Meta Block Index段:Meta Block的索引
Trailer:这一段是定长的。保存了每一段的偏移量,读取一个HFile时,会首先读取Trailer,Trailer保存了每个段的起始位置(段的Magic Number用来做安全check),然后,DataBlock Index会被读取到内存中,这样,当检索某个key时,不需要扫描整个HFile,而只需要从内存中找到key所在的block,通过一次磁盘io将整个block读取到内存中,再找到需要的key。DataBlock Index采用LRU机制淘汰。
HFile的Data Block,Meta Block通常采用压缩方式存储,压缩之后可以大大减少网络IO和磁盘IO,随之而来的开销当然是需要花费cpu进行压缩和解压缩。
HFile里面的每个key-value对就是一个简单的byte数组,这个byte数组具有固定结构。
(1)KeyLength和ValueLength:两个固定的长度,分别代表Key和Value的长度
(2)Key部分:Row Length是固定长度的数值,表示RowKey的长度,Row 就是RowKey
(3)Column Family Length是固定长度的数值,表示Family的长度
(4)接着就是Column Family,再接着是Qualifier,然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)
(5)Value部分没有这么复杂的结构,就是纯粹的二进制数据
首先HFile文件是不定长的,长度固定的只有其中的两块:Trailer和FileInfo。Trailer中指针又指向其它数据块的起始点,FileInfo记录了文件的一些meta信息。
HBase 在HDFS上的存储结构
Hbase表的HDFS目录结构为:
/hbase /data /<Namespace> (集群里的Namespaces) /<Table> (该集群的Tables) /<Region> (该table的Regions) /<ColumnFamily> (该Region的列族) /<StoreFile> (该列族的StoreFiles)
HLog的HDFS目录结构:
/hbase /WALs /<RegionServer> (RegionServers) /<WAL> (WAL files for the RegionServer)
6、Meta表
有了 Region 标识符,就可以唯一标识每个 Region。为了定位每个 Region 所在的位置,可以构建一张映射表。
映射表的每个条目包含两项内容,一项是 Region 标识符,另一项是 Region 服务器标识。这个条目就表示 Region 和 Region 服务器之间的对应关系,从而就可以使用户知道某个 Region 存储在哪个 Region 服务器中。这个映射表包含了关于 Region 的元数据,因此也被称为“元数据表”,又名“Meta表”。
使用 scan 命令可查看 Meta 表的结构,如图所示。
Meta 表中的每一行记录了一个 Region 的信息。RowKey 包含表名、起始行键和时间戳信息,中间用逗号隔开,第一个 Region 的起始行键为空。时间戳之后用.隔开的为分区名称的编码字符串,该信息是由前面的表名、起始行键和时间戳进行字符串编码后形成的。
Meta 表里有一个列簇 info。info 包含了三个列,分别为 Regionlnfo、RegioninfoServer 和 Serverstartcode。Regionlnfo中记录了 Region 的详细信息,包括行键范围 StartKey 和 EndKey、列族列表和属性。
Server 记录了管理该 Region 的 Region 服务器的地址,如 localhost:16201。
Serverstartcode 记录了 Region 服务器开始托管该 Region 的时间。
当用户表特别大时,用户表的 Region 也会非常多。Meta 表存储了这些 Region 信息,也变得非常大。Meta 表也需要划分成多个 Region,每个 Meta 分区记录一部分用户表和分区管理的情况。
hbase:meta表的一个rowkey对应一个region,rowkey设计如下:
表名,region的startRowkey,region创建时的时间戳.EcodedName
例:test:vt_article,66192017090716590_4149388609714192,1542770105784.5c44f752e1012fba9eacad769185b9dd
表名 : test:vt_article
开始rowkey :66192017090716590_4149388609714192
创建Region时间戳:1542770105784
EncodedName :5c44f752e1012fba9eacad769185b9dd = MD5(test:vt_article,66192017090716590_4149388609714192,1542770105784)
网友评论