美文网首页HBase
Hbase-2.4.2(一)概念

Hbase-2.4.2(一)概念

作者: _大叔_ | 来源:发表于2021-08-08 13:09 被阅读0次

    Hbase 是什么

    HBase是一种构建在HDFS之上的分布式、面向列的存储系统。在需要实时读写、随机访问超大规模数据集时,可以使用HBase。

    尽管已经有许多数据存储和访问的策略和实现方法,但事实上大多数解决方案,特别是一些关系类型的,在构建时并没有考虑超大规模和分布式的特点。许多商家通过复制和分区的方法来扩充数据库使其突破单个节点的界限,但这些功能通常都是事后增加的,安装和维护都和复杂。同时,也会影响RDBMS的特定功能,例如联接、复杂的查询、触发器、视图和外键约束这些操作在大型的RDBMS上的代价相当高,甚至根本无法实现。

    HBase从另一个角度处理伸缩性问题。它通过线性方式从下到上增加节点来进行扩展。HBase不是关系型数据库,也不支持SQL,但是它有自己的特长,这是RDBMS不能处理的,HBase巧妙地将大而稀疏的表放在商用的服务器集群上。

    HBase 是Google Bigtable 的开源实现,与Google Bigtable 利用GFS作为其文件存储系统类似, HBase 利用Hadoop HDFS 作为其文件存储系统;Google 运行MapReduce 来处理Bigtable中的海量数据, HBase 同样利用Hadoop MapReduce来处理HBase中的海量数据;Google Bigtable 利用Chubby作为协同服务, HBase 利用Zookeeper作为对应。

    Hbase 表结构

    Hbase以表的形式存储数据,表有行(row)和列族(column-family)组成,列族划分若干个个列(column)。

    row-key

    Hbase 本质上也是一种key-value的存储系统。key相当于row-key,value相当于列族的集合。与noSql数据库一样,row-key是用来检索记录的主键。

    访问Hbase中的行,只有三种方式:

    • 通过单个row-key访问
    • 通过row-key的range访问
    • 全表扫描

    row-key 行键(Row key)可以是任意字符串(最大长度是64KB,实际应用中长度一般为10-1000bytes),在Hbase 内部,row-key 保存为字节数组。存储时,数据按照 row-key 的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。(位置相关性)

    columns-family 列族

    Hbase 表中的每个列,都归属于某个列族。列族是表的 schema 的一部分(而列不是),必须在使用表之前定义。列名都以列族作为前缀。例如courses:history,courses:math 都属于courses这个列族。

    访问控制、磁盘和内存的使用统计都是在列族层面进行的。实际应用中,列族上的控制权限能帮助我们管理不同类型的应用,如:我们允许一些应用可以添加新的基本数据、一些应用可以读取基本数据并创建集成的列族、一些应用则是允许浏览数据。

    最好将具有相近 IO 特性的 Column 存储在一个 ColumnFamily,以实现高效的读取(数据局部性原理,可以提高混村的命中率)

    cell与时间戳

    由{row-key,column,version} 唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存储。每个cell都保存着同一份数据的多个版本,版本通过时间戳来索引。

    行列读写对比

    写入

    行存储的写入是一次完成,数据的完整性因此可以确定。列存储需要把一行记录拆分成单列保存,写入次数明显比行存储多。行存储在写入上占有很大的优势

    数据修改

    行存储是在指定位置写入一次,列存储是将磁盘定位到多个列上分别写入。行存储在数据修改也是占优的

    数据读取

    行存储通常将一行数据完全读出,如果只需要其中几列数据,就会存在冗余列。列存储每次读取的数据是集合中的一段或者全部。由于列储存的数据是同质的,这种情况使数据解析变得容易。行存储则复杂的多,因为在一行记录中保存了多种类型的数据,数据解析需要在多种数据类型之间频繁转换,这个操作很消耗cpu,所以列存储的解析过程中更有利于分析大数据

    显而易见,两种存储格式都有各自的优缺点:行存储的写入是一次性完成,消耗的时间比列存储少,并且能够保证数据的完整性,缺点是数据读取过程中会产生冗余数据,如果只有少量数据,此影响可以忽略;数量大可能会影响到数据的处理效率。列存储在写入效率、保证数据完整性上都不如行存储,它的优势是在读取过程,不会产生冗余数据,这对数据完整性要求不高的大数据处理领域,比如互联网,犹为重要。

    Hbase 存储架构

    Hbase里的一个Table在行的方向上分割为多个Hregion,Hregion可以动态扩展并且 Hbase保证 Hregion 的负载均衡。Hregion实际上是行键排序后的按规则分割的连虚的存储空间。

    一张Hbase表,可能有多个HRegion,每个Hregion达到一定的大小(默认10G)时,进行分裂。

    Hregion 是按大小分割的,每个表以开始只有一个Hregion,随着数据不断插入表,Hregion不断增大,当增大到一个阀值得时候,Hregion就会等分两个新的Hregion。当table中的行不断增多,就会有越来越多的Hregion。

    Hregion 默认10GB,可以通过如下参数指定:

    # 修改 hbase/hbase-site.xml 文件,单位为字节
    hbase.hregion.max.filesize
    

    Hregion 的拆分和转移是又Hbase自动完成的,用户感知不到。

    Hregion是 Hbase 中分布式存储和负载均衡的最小单元,但不是存储的最小单元,事实上,Hregion由一个或多个HStore组成,每个HStore 保存一个 ccolumnsFamily。HStore由一个memStore(写缓存,默认128M)和零至多个StoreFile组成。StoreFile以HFile格式保存在HDFS上。

    Hregion 是分布式的存储最小单位,StoreFile(HFile)是存储最小单位

    Hbase Hadoop 体系

    HMaster

    HMaster 没有单点故障的问题,可以启动多个HMaster,通过Zookeeper的MasterElection 机制保证同时只有一个HMaster处于Active状态,其他的HMaster则处于热备份状态。一般情况下会启动两个HMaster,非Active的HMaster会定期的和Active Hmaster通信以获取其最新的状态,从而保证它时实时更新的,因而如果启动了多个 Hmaster 反而会增加了 Active HMaster 的负担。

    HMaster 的主要主责由两个方面
    1. 协调 HregionServer:启动时 Hregion 的分配,以及负载均衡和修复时 Hregion 的重新分配;监控集群中所有的 HregionServer 的状态(通过 Heartbeat 和监听 zookeeper 中的状态)

    2. Admin直能:创建、删除、修改 Table 的定义。

    作用
    • 管理 HregionServer,实现负载均衡。
    • 管理和分配 Hregion,比如在 Hregion Split 时分配新的 Hregion;在HregionServer退出时,迁移其内的Hregion到其他HregionServer上。
    • 实现DDL操作(namespace和table的增删改,column family的增删改)
    • 管理namespace和table的元数据(实际存储在HDFS上)
    • 权限空(ACL)

    HregionServer

    Hbase 使用 row-key 将表水平切割成多个 Hregion,从 HMaster 的角度,每个 Hregion 都记录了它的 startKey 和 endKey,由于 row-key 是排序的,因而 Client可以通过 HMaster 快速的定位每个 row-key在哪个 Hregion 中。Hregion 由 HMaster 分配到相应的 HregionServer 中,然后由 HregionServer 负责 Hregion 的启动和管理,和 Client 的通信,负责数据的读(使用HDFS)。每个 HregionServer 可以同时管理1000个左右的 Hregion。

    作用
    • 存放和管理本地Hregion。
    • 读写HDFS,管理Table中的数据。
    • Client直接通过HregionServer读写数据(从 HMaster中获取元数据,找到row-key所在的Hregion/HregionServer后)。

    zookeeper

    zookeeper 为 Hbase集群提供协调服务,它管理折 HMaster 和 HregionServer 的状态(available/alive等),并且会在其他们宕机时通知到给 HMaster,从而HMaster可以实现HMaster之间的failover(失败恢复),或对宕机的 HregionServer 中的 Hregion 集合的修复(将它们分配给其他的 HregionServer)。

    HMaster 通过监听 zookeeper 中的 Ephemeral 节点(默认:/hbase/re/*)来监控 HregionServer 的加入和宕机。在第一个 HMaster 连接到 zookeeper 时会创建 Ephemeral(短暂) 节点(默认:/hbase/master)来表示 active 的 HMaster,其后加进来的 HMaster 则监听该 Ephemeral 节点,如果当前 Active 的 HMaster 宕机,则该节点消失,因而其他的 HMaster 得到通知,而将自身转换成 Active 的 HMaster,在变为
    Active 的 HMaster之前,它会创建在 /hbase/back-masters/ 下创建自己的 Ephemeral 节点。

    作用
    • 存放整个Hbase集群的元数据以及集群的状态信息,以及HregionServer服务器的运行状态
    • 实现 HMaster 主备节点的 failover

    HregionServer 解析

    HregionServer 一般和 DataNode 在同一台机器上运行,实现数据本地性,避免网络传数据。HregionServer 存活和管理多个 Hregion,由 WAL(HLog)、BlockCache、MemStore、HFile 租场。

    Hlog 即 WAL(新版本叫法)write Ahead Log, 写之前日志,是HDFS上的一个文件,会先把写操作数据写到日志里,在写到 memStore 缓存里,最后写到 HFile中。采用这种模式 HregionServer 宕机后,我们依然可以从该 Log 文件中恢复数据,Replay 所有的操作,而不至于数据丢失。

    BlockCache 是一个读缓存,即 “引用全局性” 原理(也应用于CPU,分空间局部性和时间局部性,空间局部性是指CPU在某一时刻需要某个数据,那么有很大的概率在下一时刻它需要的数据在其附近;时间局部性是指某个数据在被访问过一次后,他有很大的概率在不久的将来会被再次的访问),将数据预读取到内存中,以提升读的性能。Hbase 中默认 on-heap LruBlockCache 策略来清除 读缓存。

    MemStore 是一个写缓存,所有数据的写在完成WAL日之后,会写入MemStore中,由MemStore 根据一定的算法(LSM-TREE算法,这个算法的作用是将数据顺序写磁盘,而不是随机写,减少磁盘头调度时间,从而提高写入性能)将数据Flush到底层的HDFS文件中(HFile),通常每个 Hregion 中的每个 ColumnFamily 有一个自己的 MemStore

    Hfile(StoreFile)用于存储 Hbase的数据(Cell/KeyValue)。在HFile中的数据是按 row-key、ColumnFamily、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒叙排列。因为Hbase 的HFile是存到HDFS上,所以Hbase实际上是具备数据的副本冗余机制的。

    缓存回收测策略:

    1. LRU 最近最少使用的:移除最长时间不被使用的对象
    2. FIFO 先进显出:按对象进入缓存的顺序来移除它们。
    3. SOFT 软引用:移除基于垃圾回收状态和软引用。
    4. WEAK 弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象。

    读写数据流程

    读写都会执行以下方式,去确定 到底往哪个 HRegionServer 读写:

    • Client访问zookeeper,获取hbase:meta所在HRegionServer的节点信息
    • Client访问hbase:meta所在的HRegionServer,获取hbase:meta记录的元数据后先加载到内存中,然后再从内存中根据需要查询的RowKey查询出RowKey所在的HRegion的相关信息(Region所在RegionServer)
    • Client访问RowKey所在Region对应的HRegionServer,发起数据读取请求
    读流程

    都流程以以上图的方式,总结是:Client->Zookeeper->Meta RS->RS->BlockCache->MemStore->HFile(index+BloomFilter)

    相同Cell(数据)可能存在三个地方:首先对新写入的Cell,它会存在于MemStore中;然后对之前已经Flush到HFile中的Cell,它会存在于某个或某些HFile中;最后对刚读取过的Cell,它可能存在于 BlockCache中。既然相同的Cell可能存在三个地方,在读取的时候只需要扫描三个地方,然后将结果合并即可(Merge Read),在HBase中扫描的顺序一次是:BlocalCache、MemStore、HFile。其中 HFile 的扫描先会使用Bloom Filter过滤那些不可能符合条件的 HFile,然后使用 Block Index 快速定位Cell,并将其加载到 BlockCache 中,然后从 BlockCache 中读取。我们直到一个 HStore 可能存在多个 HFile,此时需要扫描多个 HFile,如果HFile过多是会引起性能问题。

    写流程

    写流程和都流程不太一样,总结是:Client->Zookeeper->RS->WAL->MemStore->HFile->HDFS

    当确定了写到哪个 HRegionServer 后,client 发起请求,会先在该 HRegionServer 的日志(WAL)记录,然后写入 MemStore 缓存,在缓存中进行排序(LSM-TREE),当缓存达到三种情况触发 Flush 到 HDFS(HFile)里。

    1. 当一个 Hregion 中的MemStore的大小超过了默认 128M 内存使用量,此时当前的MemStore会Flush到HFile中。
    hbase.hregion.memstore.flush.size=128MB
    
    1. 当 HregionServer 服务器上所有的 MemStore 的大小超过了 本机内存 35% 的内存使用量,此时当前的 HregionServer 中所有 Hregion 中的 MemStore 可能都会 Flush。从最大的 MemStore 开始 Flush。
    hbase,refionserver.global.memstore.upperLimit=35
    
    1. 当前 HRegionServer 中WAL的带下超过了1GB,hbase.regionserver.hlog.blocksize(32MB) * hbase.regionserver.max.logs(32个) 的数量,当前HRegionServer 中所有 HRegion 中的MemStore都会Flush。
    Compaction(合并) 机制

    MemStore 每次 Flush 会创建新的 HFile,而过多的 HFile 会引起读的性能问题。对于这一问题,Hbase 采用 Compaction 机制来解决这个问题。在 Hbase 中 Compaction 分为两种:Minor Compaction 和 Major Compaction。

    Minor Compaction 是指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的数据。一次 Minor Compaction 的结果是更少并且更大的StoreFile。

    Major Compaction 是指将所有的StoreFile合并成一个StoreFile,在这个过程中,标记为Deleted的数据会被删除,而那些已经Expired的数据会被丢弃,那些已经超过最大版本的数据会被丢弃,一次 Major Compaction 的结果是一个 HStore 只有一个StoreFile存在。Major Compaction 可以手动或自动触发,然而由于他会引起性能问题,因而它一般会被安排在周末、凌晨等集群比较闲的时间。

    代码方式

    // minor compact
    hbaseTemplate.getAdmin().compact(TableName.valueOf("table_name"));
    // major compact
    hbaseTemplate.getAdmin().majorCompact(TableName.valueOf("table_name"));
    

    命令方式

    compact('table_name')
    major_compact('table_name')
    

    Hbase 表设计

    row-key 设计

    row-key 是不可分割的字节数,按字典排序由低到高存储在表中。在设计Hbase表时,row-key设计是最重要的事情,应该基于预期的访问模式来为row-key建模。row-key决定了访问Hbase表时可以得到的性能,原因有两个:

    1. HRegion基于row-key 为一个区间的行提供服务,并且负责区间每一行;
    2. HFile 在硬盘上存储有序的行。

    这两个因素是相互关联的。当 HRegion 将内存中数据 flush 为 HFile 时,这些行已经排过序,也会有序地写到硬盘上。row-key 的有序特性和底层存储格式可以保证Hbase 表在设计row-key之后的良好性能。

    关系型数据库可以在多列上建立索引,但是Hbase只能在row-key上建立索引(可以通过ES为Hbase的列建立索引)。而设计row-key有多种技巧,而且可以针对不同访问模式进行优化。

    1. 将row-key以字典顺序从大到小排序:原生Hbase只支持从小到大的排序,但是现在有个需求想展现影片热度排行榜,这就要求实现从大到小排列,针对这种情况可以采用 Rowkey=Integer.MAX_VALUE-Rowkey 的方式将 row-key进行转换,最大的变最小,最小的变最大,在应用层再转回来即可完成排序需求。

    2. row-key 尽量散列设计:最终要的是保证散列,这样就会保证所有的数据都不是在一个 Hregion 上,从而避免读写的时候负载会集中在个别 Hregion 上。Rowkey=业务数-随机数

    3. row-key的长度尽量短:如果 row-key 太长,第一 存储开销会增加,影响存储效率;第二 内存中row-key字段过长,会导致内存的利用率降低,进而降低索引命中率。row-key 是一个二进制码流,row-key 的长度建议在16个字节以内。原因如下:

    • 数据的持久化文件 HFile 中是按照 keyValue 存储的,如果row-key太长比如 100个字节,1000万列数据光row-key就要占用100*1000万=10以个字节,将近1G数据,这会极大影响HFile的存储效率。
    • MemStore 将缓存部分数据到内存,如果row-key字段过长,内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。
    1. row-key唯一

    2. row-key 建议使用string类型:虽然行键在Hbase中是以 byte[] 字节数组的形式存储的,但是建议在系统开发过程中将其数据类型设置为String类型,保证通用性。

    3. row-key建议设计的有意义:row-key 的主要作用是为了进行数据记录唯一性标示,但是唯一性并不是其全部,具有明确意义的行键对于应用开发、数据检索等都具有特殊意义。

    4. 具有定长性:行键具有有序性的基础便是定长,譬如20140512080500、20140512083000,这两个日期形式的字符串是递增的,不管后面的秒数是多少,我们都将其设置为14位数字形式,如果我们把后面0去除了,那么201405120805将大于20140512083,其有序性发生了变更。所以建议,行键一定要设计成定长的。最好是8字节的倍数

    列族的设计

    在设计 Hbase 表的时候,列族不宜过多,尽量的要少使用列族。经常要在一起查询的数据最好放在一个列族中,尽量减少跨列族的数据访问。

    相关文章

      网友评论

        本文标题:Hbase-2.4.2(一)概念

        本文链接:https://www.haomeiwen.com/subject/xlyxsltx.html