HBase第一天学习

2021/11/16 23:09:48

本文主要是介绍HBase第一天学习,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

HBase第一天学习     HBase的访问方式         进入退出:hbase shell    exit         shell实现DDl操作             创建一个表:create 'member','member_id','address','info'             获得表的描述:list(查看所有的表)   describe ‘member’(查看member表的详细信息) 'member_id',METHOD=>'delete'}">            删除一个列簇:alter、disable、enable。    alter 'member',{NAME=>'member_id',METHOD=>'delete'}             drop一个表:create 'temp_table','member_id','address','info'                        disable 'temp_table'               查看表是否存在:exists ‘member’             查看文件的存储路径:hdfs dfs -ls /yjx/hbase/data/default/t1         shell实现DMl操作:put(插入数据):put'member','guojing','info:age','24'             删除id为temp的值'info:age'字段:delete 'member','temp','info:age'             将整张表清空;truncate 'member'             可以使用count命令计算表的行数量:count 'member'         Shell实现DQL操作             获取一个id的所有数据:get 'member','linghuchong'             获取一个id,一个列族的所有数据:get 'member','linghuchong','info'             获取一个id,一个列族中一个列的所有数据:get 'member','linghuchong','info:age'             全表扫描:scan 'member'         Shell实现Region管理             移动region:move 'encodeRegionName', 'ServerName'             开启/关闭redion:balance_switch true|false             手动spilt:spilt 'regionName','spiltKey'             压缩整个区域:major_compact 'r1'             在region中它说单列簇:major_compact 'r1','c1'             在表中压缩单列族:major_compact 't1','c1'     HBase架构模型         Client:客户端             负责将请求发送到数据库,客户端连接的方式有很多:hbase shell、类JDBC             发送的请求主要包括:                 DDl:数据库定义语言(表的建立、删除、添加删除列簇,控制版本)                 DMl:数据库操作语言(增删改)                 DQL:数据库查询语言(查询--全表扫描--基于主键--基于过滤器)             client维护着一些cache来加快对hbase的访问,比如regione的位置信息         HBase有三个主要的组成部分:客户端库、主服务器和区域服务器         HMaster             HBase集群的主节点,HMaster也可以实现高可用(active-standby):通过zookeeper来维护祝福节点的切换             为Region server分配region并负责region server的负载均衡 zookeeper上面、表的数据-->HRegionServer上">            管理用户对table的结构DDL(创建、删除、修改)操作:表的元数据信息-->zookeeper上面、表的数据-->HRegionServer上             当HRegionServer下线的时候,HMaster会将当前HRegionServer上的Region转移到其他的HRegionServer         zookeeper             保证在任何时候,集群都只有一个master             存储所有Region的寻址入口,存储所有的元数据信息             实时监控Region server的状态,将Region Server的上线和下线信息实时通知给Master             存储HBase的schema,包括有哪些table,每个table有哪些column family         HRegionServer             Region server是属于HBase具体数据的管理者             Region server 维护Master分配给他的region,处理对这些region的io请求             会实时的和HMaster保持心跳,汇报当前节点的信息             当接受到Hmaster命令创建表的时候,分配一个Region对应一张表             Region Server负责切分在运行过程中变得过大的Region             当客户端发送的DMl和DQL操作时,HRegionServer负责和客户端建立连接             当意外关闭的时候,当前节点的Region会被其他HRegionServer管理         HRegion             HRegion是HBase中分布式存储和负载均衡的最小单元,最小单元就表示不同的HRegion可以分布在不同的HRegion server上             HBase自动把表水平划分成多个区域(region),每个区域会保存一个表里面某段连续的数据             每个表一开始只有一个region,一个region只属于一张表,随着数据不断插入表,region不断增大             Region达到阈值10G的时候会被平分(逻辑上平分,尽量保证数据的完整性):hbase.hregion.max.filesize、切分后的其中一个Region转移到其他的HRegionServer上管理             当table中的行不断增多,就会有越来越多的region,这样一张完整的表就被保存在多个RegionServer             为了防止前期数据的处理都集中在一个HRegionServer,我们可以根据自己的业务进行预分区         Store             HRegion是表获取和分布的基本元素,由一个或者多个Store组成,每个store保存一个columns family             每个Store又由一个memStore和0个或者多个StoreFile组成             HFile是HBase在HDFS中存储数据的格式,它包含多层的索引,这样在Hbase检索数据的时候就不用完全加载整个文件了。             索引的大小(key的大小,数据量的大小影响block的大小,在大数据集群的情况下,blcok的大小设置为每个RegionServer 1G也是很常见的)         StoreFile             Data Block段-保存表中数据,这部分可以被压榨             Meta Blocks段(可选的)-保护用户自定义的kv对,可以被压缩             File info 段-Hfile的元信息,不被压缩,用户也可以在这一部分添加自己的元信息             Data Block Index段-Data Block的索引,每条索引的key是被索引的block的第一条记录的key             Meta Block index段(可选的)-Meta blcok的索引             Trailer-这一段是定长的                 保存了每一段的偏移量,读取一个HFile时,会首先读取Trailer Trailer保存了每个段的起始位置(段的Magic Number用来做安全check) 然后,DataBlock Index会被读取到内存中,当检索某个key时,不需要扫描整个HFile,而只 需从内存中找到key所在的block 通过一次磁盘io将整个 block读取到内存中,再找到需要的key。DataBlock Index采用LRU机 制淘汰。         MemStore             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是HBase为了降低KeyValue结构性膨胀而提供的内部编码机制。         Hlog             一个HRegionServer只有一个Log文档             WAL(Write After Log)做任何操作之前先写日志             HLog文件就是一个普通的Hadoop Sequence File,SequeceFile的Key是HLogKey对象, HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp timestamp是” 写入时间”, sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。 SequeceFile的Value是HBase的KeyValue对象,即本次的操作。 日志直接存放到HDFS上             当memStore达到阈值的时候开始写出到文件之后,会在日志中对应的位置标识一个检查点             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的配置: <name>hbase.wal.provider</name> <value>multiwal</value> </property>">// 启用multiwal <property> <name>hbase.wal.provider</name> <value>multiwal</value> </property>     HBase读写流程         公共流程(三层索引)             HBase中单表的数据量通常可以达到TB级或PB级,但大多数情况下数据读取可以做到毫秒级。 HBase是如何做到的呢?要想实现表中数据的快速访问,通用的做法是数据保持有序并尽可能的将 数据保存在内存里。HBase也是这样实现的。             对于海量级的数据,首先要解决存储的问题。数据存储上,HBase将表切分成小一点的数据单位 region,托管到RegionServer上,和以前关系数据库分区表类似。但比关系数据库分区、分库易 用。这一点在数据访问上,HBase对用户是透明的。数据表切分成多个Region,用户在访问数据 时,如何找到该条数据对应的region呢?          HBase 0.96以前             有两个特殊的表,-Root-和.Meta. ,用来查找各种表的region位置在哪里。-Root-和.Meta.也像 HBase中其他表一样会切分成多个region。-Root-表比.Meta更特殊一些,永远不会切分超过一个 region。-ROOT-表的region位置信息存放在Zookeeper中,通过Zookeeper可以找到-ROOTregion托管的RegionServer。通过-ROOT-表就可以找到.META.表region位置。.META表中存放着 表切分region的信息。             当客户端访问一个表的时候,首先去询问Zookepper Zookepper会告诉客户端-root-Region所在的RegionServer             公共表.meta. 是一张普通表,但是由HBase自己维护 它的机构和meta一模一样,但是它只维护meta表的切分信息 理论上-root-表不会被切分(数据量)         HBase 0.96以后             -ROOT-表被移除,直接将.Meta表region位置信息存放在Zookeeper中。Meta表更名为 hbase:meta,部分内容如下             查询流程 zookeeper-------->hbase:meta--------->用户表region">Client--------->zookeeper-------->hbase:meta--------->用户表region         读取数据流程             01Client访问zookeeper,获取hbase:meta所在RegionServer的节点信息             02Client访问hbase:meta所在的RegionServer,获取hbase:meta记录的元数据后先加载到内存 中,然后再从内存中根据需要查询的RowKey查询出RowKey所在的Region的相关信息(Region所 在RegionServer)             03Client访问RowKey所在Region对应的RegionServer,发起数据读取请求             04RegionServer构建RegionScanner(需要查询的RowKey分布在多少个Region中就需要构建多少 个RegionScanner),用于对该Region的数据检索             05RegionScanner构建StoreScanner(Region中有多少个Store就需要构建多少个StoreScanner, Store的数量取决于Table的ColumnFamily的数量),用于对该列族的数据检索             06多个StoreScanner合并构建最小堆(已排序的完全二叉树)StoreHeap:PriorityQueue             07StoreScanner构建一个MemStoreScanner和一个或多个StoreFileScanner(数量取决于 StoreFile数量)             08过滤掉某些能够确定所要查询的RowKey一定不在StoreFile内的对应的StoreFileScanner或 MemStoreScanner             09经过筛选后留下的Scanner开始做读取数据的准备,将对应的StoreFile定位到满足的RowKey的 起始位置             10将所有的StoreFileScanner和MemStoreScanner合并构建最小堆 KeyValueHeap:PriorityQueue,排序的规则按照KeyValue从小到大排序             11从KeyValueHeap:PriorityQueue中经过一系列筛选后一行行的得到需要查询的KeyValue。         写入数据流程             首先客户端和RegionServer建立连接             然后将DML要做的操作写入到日志wal-log             然后将数据的修改更新到memstore中,然后本次操作结束 一个region由多个store组成,一个store对应一个CF(列族),store包括位于内存中的 memstore和位于磁盘的storefile,写操作先写入memstore.             当memstore数据写到阈值之后,创建一个新的memstore             旧的memstore写成一个独立的storefile,regionserver会启动flashcache进程写入storefile,每次 写入形成单独的一个storefile,存放到hdfs             当storefile文件的数量增长到一定阈值后,系统会进行合并(minor compaction、major compaction)             在合并过程中会进行版本合并和删除工作,形成更大的storefile             当一个region所有storefile的大小和数量超过一定阈值后,会把当前的region分割为两个,并由 hmaster分配到相应的regionserver服务器,实现负载均衡             Store负责管理当前列族的数据 1memstore+nstorefile             当我们进行数据DML的时候,以插入数据为例 我们会将数据先存储到memStore中,当memStore达到阈值(128M) 首先创建一个新的memstore 然后会将memStore中的数据写成一个storefile,storefile会存储到hdfs上(hfile)             随着时间的推移: HFile中会存放大量的失效数据(删除,修改) 会产生多个HFile 等达到阈值(时间、数量)会进行合并 多个HFile合并成一个大的HFile 合并会触发连锁反应,相邻的store也会进行合并             在Hbase中,表被分割成多个更小的块然后分散的存储在不同的服务器上,这些小块叫做 Regions,存放Regions的地方叫做RegionServer。Master进程负责处理不同的RegionServer之间 的Region的分发。在Hbase实现中HRegionServer和HRegion类代表RegionServer和Region。 HRegionServer除了包含一些HRegions之外,还处理两种类型的文件用于数据存储 HLog 预写日志文件,也叫做WAL(write-ahead log) HFile 是HDFS中真实存在的数据存储文件     数据刷写(MemStore Flush)         触发时机             Region 中所有 MemStore 占用的内存超过相关阈值 hbase.hregion.memstore.flush.size 参数控制,默认为128MB 如果我们的数据增加得很快, 达到了 hbase.hregion.memstore.flush.size * hbase.hregion.memstore.block.multiplier 的大小,hbase.hregion.memstore.block.multiplier 默认值为4, 也就是128*4=512MB的时候, 那么除了触发 MemStore 刷写之外,HBase 还会在刷写的时候同时阻塞所有写入该 Store 的 写请求!             整个 RegionServer 的 MemStore 占用内存总和大于相关阈值 HBase 为 RegionServer 所有的 MemStore 分配了一定的写缓存(),大小等于 hbase_heapsize(RegionServer 占用的堆内存大小)* hbase.regionserver.global.memstore.size(默认值是 0.4)。 如果整个 RegionServer 的 MemStore 占用内存总和大于阈值将会触发 MemStore 的刷写。 hbase.regionserver.global.memstore.size.lower.limit (默认值为 0.95)* MAX_SIZE 例如:HBase 堆内存总共是 32G ,MemStore 占用内存为:32 * 0.4 * 0.95 = 12.16G将触发 刷写 如果达到了 RegionServer 级别的 Flush,当前 RegionServer 的所有写操作将会被阻塞,这 个阻塞可能会持续到分钟级别             WAL数量大于相关阈值 数据到达 Region 的时候是先写入 WAL,然后再被写到 Memstore 。如 果 WAL 的数量越来越大,这就意味着 MemStore 中未持久化到磁盘的数据越来越多。 当 RS 挂掉的时候,恢复时间将会变得很长,所以有必要在 WAL 到达一定的数量时进行一次 刷写操作             定期自动刷写 hbase.regionserver.optionalcacheflushinterval 默认值 3600000(即 1 小时),HBase 定期 Flush 所有 MemStore 的时间间隔。 一般建议调大,比如 10 小时,因为很多场景下 1 小时 Flush 一次会产生很多小文件,一方 面导致 Flush 比较频繁,另一方面导致小文件很多,影响随机读性能             数据更新超过一定阈值 如果 HBase 的某个 Region 更新的很频繁,而且既没有达到自动刷写阀值,也没有达到内存 的使用限制,但是内存中的更新数量已经足够多, 比如超过 hbase.regionserver.flush.per.changes 参数配置,默认为30000000,那么也是会 触发刷写的。             手动触发刷写 Shell 中通过执行 flush 命令             特别注意: 以上所有条件触发的刷写操作最后都会检查对应的 HStore 包含的 StoreFiles 文件数是否超过 hbase.hstore.blockingStoreFiles 参数配置的个数,默认值是16。 如果满足这个条件,那么当前刷写会被推迟到hbase.hstore.blockingWaitTime 参数设置的时 间后再刷写。 在阻塞刷写的同时,HBase 还会请求 Compaction 或者Split 操作。         刷写策略             prepareFlush 阶段: 刷写的第一步是对 MemStore 做 snapshot, 为了防止刷写过程中更新的数据同时在 snapshot 和 MemStore 中而造成后续处理的困难, 所以在刷写期间需要持有 updateLock 。持有了 updateLock 之后,这将阻塞客户端的写操 作。 所以只在创建 snapshot 期间持有 updateLock,而且 snapshot 的创建非常快,所以此锁期间对客户的影响一般非常小。 对 MemStore 做 snapshot 是 internalPrepareFlushCache 里面进行的。             flushCache 阶段: 如果创建快照没问题, 那么返回的 result.result 将为 null。 这时候我们就可以进行下一步 internalFlushCacheAndCommit。 其实 internalFlushCacheAndCommit 里面包含两个步骤:flushCache 和 commit 阶段。 flushCache 阶段: 其实就是将 prepareFlush 阶段创建好的快照写到临时文件里面, 临时文件是存放在对应 Region 文件夹下面的 .tmp 目录里面。 commit 阶段: 将 flushCache 阶段生产的临时文件移到(rename)对应的列族目录下面, 并做一些清理工作,比如删除第一步生成的 snapshot。     数据合并         合并分类             HBase 根据合并规模将 Compaction 分为了两类:MinorCompaction 和 MajorCompaction             Minor Compaction 是指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会 处理已经Deleted或Expired的Cell 但是会处理超过TTL的数据 一次Minor Compaction的结果是让小的storefile变的更少并且产生更大的StoreFile。             Major Compaction 是指将所有的StoreFile合并成一个StoreFile 清理三类无意义数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。 一般情况下,Major Compaction时间会持续比较长,整个过程会消耗大量系统资源,对上层 业务有比较大的影响。因此线上业务都会将关闭自动触发Major Compaction功能,改为手动 在业务低峰期触发         合并时机             触发compaction的方式有三种:Memstore刷盘、后台线程周期性检查、手动触发             Memstore刷盘 memstore flush会产生HFile文件,文件越来越多就需要compact。 每次执行完Flush操作之后,都会对当前Store中的文件数进行判断,一旦文件数大于配置,就 会触发compaction。 compaction都是以Store为单位进行的,而在Flush触发条件下,整个Region的所有Store都 会执行compact             后台线程周期性检查 后台线程定期触发检查是否需要执行compaction,检查周期可配置。 hbase.server.thread.wakefrequency(默认10000毫秒) *hbase.server.compactchecker.interval.multiplier(默认1000) CompactionChecker大概是2hrs 46mins 40sec 执行一次 线程先检查文件数是否大于配置,一旦大于就会触发compaction。 如果不满足,它会接着检查是否满足major compaction条件, 如果当前store中hfile的最早更新时间早于某个值mcTime, 就会触发major compaction(默认7天触发一次,可配置手动触发)。             手动触发 一般来讲,手动触发compaction通常是为了执行major compaction,一般有这些情况需要手 动触发合并 是因为很多业务担心自动major compaction影响读写性能,因此会选择低峰期手动触 发; 也有可能是用户在执行完alter操作之后希望立刻生效,执行手动触发major compaction; 是HBase管理员发现硬盘容量不够的情况下手动触发major compaction删除大量过期数 据;          合并策略             承载了大量IO请求但是文件很小的HFile,compaction本身不会消耗太多IO,而且合并完成之后对读的 性能会有显著提升。 线程池选择 HBase CompacSplitThread类内部对于Split、Compaction等操作专门维护了各自所使用的 线程池 和Compaction相关的是如下的longCompactions和shortCompactions 前者用来处理大规模compaction,后者处理小规模compaction 默认值为2 * maxFlilesToCompact * hbase.hregion.memstore.flush.size 如果flush size 大小是128M,该参数默认值就是2 * 10 * 128M = 2.5G             合并策略选择 1.HBase 主要有两种 minor 策略: RatioBasedCompactionPolicy (0.96.x之前)和 ExploringCompactionPolicy(当前默认) 2.RatioBasedCompactionPolicy(基于比列的合并策略) 从老到新逐一扫描HFile文件,满足以下条件之一停止扫描 当前文件大小<比当前文件新的所有文件大小总和*ratio(高峰期1.2,非高峰期5) 当前所剩候选文件数<=阈值(默认为3) 3.ExploringCompactionPolicy策略(默认策略)  基于Ratio策略,不同之处在于Ratio策略找到一个合适文件集合就停止扫描,而Exploring策略 会记录所有合适的文件集合,然后寻找最优解,待合并文件数最多或者待合并文件数相同的情况下 文件较小的进行合并  4.FIFO Compaction策略 收集过期文件并删除,对应业务的列簇必须设置有TTL 5.Tier-Based Compaction策略(分层策略) 针对数据热点情况设计的策略,根据候选文件的新老程度将其划分为不同的等级,每个等级都有对 应的Ratio,表示该等级文件比选择为参与Compation的概率 6.Stripe Compation策略(条纹策略) 将整个Store中的文件按照key划分为多个range,此处称为stripe,一个Stripe内部就类似于 一个小Region,可以执行Minon Compation和major Compation             执行文件合并 分别读出待合并hfile文件的KV,并顺序写到位于./tmp目录下的临时文件中 将临时文件移动到对应region的数据目录 将compaction的输入文件路径和输出文件路径封装为KV写入WAL日志,并打上compaction 标记,最后强制执行sync 将对应region数据目录下的compaction输入文件全部删除     数据切分(Region Spilt)         通过切分,一个region变为两个近似相同大小的子region,再通过balance机制均衡到不同 region server上,使系统资源使用更加均衡。         切分原因             数据分布不均匀。 同一 region server 上数据文件越来越大,读请求也会越来越多。一旦所有的请求都落在同一 个 region server 上,尤其是很多热点数据,必然会导致很严重的性能问题。             compaction性能损耗严重。 compaction本质上是一个排序合并的操作,合并操作需要占用大量内存,因此文件越大,占 用内存越多 compaction有可能需要迁移远程数据到本地进行处理(balance之后的compaction就会存在 这样的场景),如果需要迁移的数据是大文件的话,带宽资源就会损耗严重。             资源耗费严重 HBase的数据写入量也是很惊人的,每天都可能有上亿条的数据写入 不做切分的话一个热点region的新增数据量就有可能几十G,用不了多长时间大量读请求就会 把单台region server的资源耗光。         触发时机             每次数据合并之后都会针对相应region生成一个requestSplit请求,requestSplit首先会执行 checkSplit,检测file size是否达到阈值,如果超过阈值,就进行切分。             检查阈值算法主要有两种:ConstantSizeRegionSplitPolicy( 0.94版本)和 IncreasingToUpperBoundRegionSplitPolicy(当前)             ConstantSizeRegionSplitPolicy : 系统会遍历region所有store的文件大小,如果有文件大小 > hbase.hregion.max.filesize(默 认10G),就会触发切分操作。             IncreasingToUpperBoundRegionSplitPolicy: 如果store大小大于一个变化的阀值就允许split。 默认只有1个region,那么逻辑这个region的store大小超过 1 * 1 * 1 * flushsize * 2 = 128M * 2 =256M 时,才会允许split 切分之后会有两个region,其中一个region中的某个store大小大于 2 * 2 * 2 * flushsize * 2 = 2048M 时,则允许split 后续超过hbase.hregion.max.filesize + hbase.hregion.max.filesize * 随机小数 * hbase.hregion.max.filesize.jitter才允许split 基本也就固定了,如果粗劣的计算可以把这个hbase.hregion.max.filesize的大小作为最后的 阀值,默认是10G         切分流程             寻找切分点 将一个region切分为两个近似大小的子region,首先要确定切分点。切分操作是基于region执 行的,每个region有多个store(对应多个column famliy)。系统首先会遍历所有store,找 到其中最大的一个,再在这个store中找出最大的HFile,定位这个文件中心位置对应的 rowkey,作为region的切分点。             开启切分事务 切分线程会初始化一个SplitTransaction对象,从字面上就可以看出来split流程是一个类似‘事 务’的过程,整个过程分为三个阶段:prepare - execute - rollback prepare阶段 在内存中初始化两个子region,具体是生成两个HRegionInfo对象,包含tableName、 regionName、startkey、endkey等。同时会生成一个transaction journal,这个对象 用来记录切分的进展 execute 阶段 region server 更改ZK节点 /region-in-transition 中该region的状态为SPLITING。 master检测到region状态改变。 region在存储目录下新建临时文件夹.split保存split后的daughter region信息。 parent region关闭数据写入并触发flush操作,将写入region的数据全部持久化到磁盘。 在.split文件夹下新建两个子文件夹,称之为daughter A、daughter B,并在文件夹中生 成引用文件,分别指向父region中对应文件。 将daughter A、daughter B拷贝到HBase根目录下,形成两个新的region。 parent region通知修改 hbase.meta 表后下线,不再提供服务。 开启daughter A、daughter B两个子region。 通知修改 hbase.meta 表,正式对外提供服务。 rollback阶段 如果execute阶段出现异常,则执行rollback操作。 为了实现回滚,整个切分过程被分为很多子阶段,回滚程序会根据当前进展到哪个子阶 段清理对应的垃圾数据。

这篇关于HBase第一天学习的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程