关于hbase:大数据学习之Hbase-shell的基本操作

HBase的命令行工具,最简略的接口,适宜HBase治理应用,能够应用shell命令来查问HBase中数据的详细情况。装置完HBase之后,启动hadoop集群(利用hdfs存储),启动zookeeper,应用start-hbase.sh命令开启hbase服务,最初在shell中执行hbase shell就能够进入命令行界面Habse shell的help对语法的介绍很全,hbase shell 的操作分为 10类,j本文只介绍前4类罕用的,别离是:gerneral,ddl,namespace,dml1. Gerneralstatus:查问以后服务器状态。Version:查看以后版本Whoami:查问以后hbase用户Table_help:表的援用,通过获取一张表的援用来对这张表进行增加删除数据等等操作,当初不举荐应用2. DDLCreate:创立一个表###创立一个表名为qianfeng,cf为列族create 'qianfeng','cf'list:列出HBase的所有表· disable:禁用一张表· ##禁用表‘qianfeng’· disable ‘qianfeng’· is_disabled:表是否被禁用· ##验证表‘qianfeng’是否被禁用· is_disabled ‘qianfeng’· enable: 启用一张表· ##启用表‘qianfeng’· enable ‘qianfeng’· is_enabled:表是否被启用· ##验证表‘qianfeng’是否被启用· is_enabled ‘qianfeng’· describe:查看表的形容· ##查看‘qianfeng’表的形容信息· describe ‘qianfeng’· alter:批改表的构造· ##给表‘qianfeng’退出一个列族‘cf1’· alter ‘qianfeng’,’cf1’· exists:验证表是否存在· ##验证表‘qianfeng’是否存在· exists ‘qianfeng’· drop:删除表,表需先禁用,而后能力删除· ##删除表‘qianfeng’· disable ‘qianfeng’· drop ‘qianfeng’· disable_all:禁用多个表drop_all:删除多个表,表需先禁用,而后能力删除3. Namespacecreate_namespace:创立命名空间,相当于关系型数据库里创立一个数据库##创立一个命名空间名为‘qf’,并增加属性create_namespace ‘qf’, {'PROPERTY_NAME'=>'PROPERTY_VALUE'}alter_namespace:批改,增加,删除命名空间的属性##设置命名空间qf的属性alter_namespace 'qf', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}##删除命名空间qf的属性alter_namespace 'qf', {METHOD => 'unset', NAME=>'PROPERTY_NAME'}describe_namespace:获取命名空间的形容##获取命名空间‘qf’的形容信息describe_namespace ‘qf’drop_namespace:删除命名空间##删除命名空间‘qf’drop_namespace ‘qf’list_namespace:查看所有命名空间list_namespace_tables:查看命名空间下的所有表##查看命名空间‘ns1’下的所有表list_namespace_tables ‘ns1’4.DML先在命名空间‘qianfeng’(如果没有这个命名空间要先创立此命名空间)下创立一张表test,列族为‘cf’作为测试用create ‘qianfeng:test’,’cf’put:增加cell(数据)# #向命名空间qianfeng下表test的rowkey为r1的列族下增加数据put 'qianfeng:test','r1','cf:uname','zhangsan'scan:扫描全表scan ‘qianfeng:test’get:失去某一列或cell的数据。##向命名空间qianfeng下表test的rowkey为r1的列族下增加数据put 'qianfeng:test','r1','cf:age','23'##获取列族cf下rowkey为r1的所有数据get ‘qianfeng:test’,’r1’ ...

April 3, 2023 · 1 min · jiezi

关于hbase:Hbase-基本理解

HBase的数据模型: HBase实质上其实就是Key-Value的数据库. HBase中是有表的概念的一个表中能够蕴含多个列族一个列族能够蕴含很多的列每一个列对应的单元格(值、timestamp) HBase介于nosql(非关系型数据库)和RDBMS(关系型数据库管理系统)之间,仅能通过主键(row key)和主键的range来检索数据,仅反对单行事务(可通过hive反对来实现多表join等简单操作)。次要用来存储非结构化和半结构化的涣散数据。 RowKey(行键):Rowkey相当于SQL中的主键。rowkey决定了row在表中的存储程序,在HBase中,row的排序形式为字典程序。HBase中的三种查问形式:1、基于Rowkey的单行查问2、基于Rowkey的范畴扫描3、全表扫描 Row key行键(Rowkey)能够是任意字符串(最大长度是 64KB,理论利用中长度个别为 10-100bytes),在Hbase外部,rowkey保留为字节数组。 Column(列):能够了解为其MySql中的列。根本的存储单位,一个或者多个列造成列族。 ColumnFamily(列族)列族是咱们在开始创立表的时候就须要定义的,它是表的一部分。 表中的有些属性也是在列族上定义的,比方过期工夫、数据块缓存以及是否压缩等。 Cell(单元格):{rowkey:column family:column:version}一个列上能够存储多个版本的值,多个版本的值存储在多个单元格外面,多个版本之间通过版本号(Version)来辨别 Time Stamp(工夫戳)工夫戳就是实现多版本的关键所在。通过不同的timestamp来标识雷同rowkey行对应的不同版本的数据。HBase 中通过 rowkey和 columns 确定的为一个存储单元(cell),每个cell都保留着同一份数据的多个版本,通过工夫戳来索引。 Hbase的一些操作(表,行键,列族,列)创立表HBase是没有schema的,就是在创立表的时候不须要指定表中有哪些列,只须要指定有多少个列蔟 create "表名","列蔟1", "列蔟2"删除表删除表之前咱们首先要禁用表,如果不禁用表这里会呈现无奈删除的状况 禁用表 disable “表名”删除表 drop “删除表”https://blog.csdn.net/FengTin...https://zhuanlan.zhihu.com/p/...

September 27, 2022 · 1 min · jiezi

关于hbase:HBase单机启动失败procedureServerCrashProcedure

过程:在首次配置hbase-site.xml内容有误的状况下启动了hbase。后续屡次启动后依然报错,内容如下。谬误起因:HBase split出现异常,WALs目录下有残留的splitting文件,将其删除后重新启动就行了解决办法:hdfs dfs -rm -r /hbase/WALs/* 2022-08-25 10:56:03,408 INFO [PEWorker-7] master.SplitLogManager: Started splitting 1 logs in [hdfs://localhost:8020/hbase/WALs/localhost,16020,1661394447685-splitting] for [localhost,16020,1661394447685]2022-08-25 10:56:03,930 INFO [main-EventThread] coordination.SplitLogManagerCoordination: Task /hbase/splitWAL/WALs%2Flocalhost%2C16020%2C1661394447685-splitting%2Flocalhost%252C16020%252C1661394447685.1661395053086 acquired by localhost,16020,16613960524892022-08-25 10:56:03,950 INFO [main-EventThread] coordination.SplitLogManagerCoordination: Task /hbase/splitWAL/WALs%2Flocalhost%2C16020%2C1661394447685-splitting%2Flocalhost%252C16020%252C1661394447685.1661395053086 entered state=ERR localhost,16020,16613960524892022-08-25 10:56:03,951 WARN [main-EventThread] coordination.SplitLogManagerCoordination: Error splitting /hbase/splitWAL/WALs%2Flocalhost%2C16020%2C1661394447685-splitting%2Flocalhost%252C16020%252C1661394447685.16613950530862022-08-25 10:56:03,951 WARN [PEWorker-7] master.SplitLogManager: error while splitting logs in [hdfs://localhost:8020/hbase/WALs/localhost,16020,1661394447685-splitting] installed = 1 but only 0 done2022-08-25 10:56:03,951 WARN [PEWorker-7] procedure.ServerCrashProcedure: Failed state=SERVER_CRASH_SPLIT_LOGS, retry pid=3, state=RUNNABLE:SERVER_CRASH_SPLIT_LOGS, locked=true; ServerCrashProcedure server=localhost,16020,1661394447685, splitWal=true, meta=true; cycles=104java.io.IOException: error or interrupted while splitting logs in [hdfs://localhost:8020/hbase/WALs/localhost,16020,1661394447685-splitting] Task = installed = 1 done = 0 error = 1 at org.apache.hadoop.hbase.master.SplitLogManager.splitLogDistributed(SplitLogManager.java:267) at org.apache.hadoop.hbase.master.MasterWalManager.splitLog(MasterWalManager.java:401) at org.apache.hadoop.hbase.master.MasterWalManager.splitLog(MasterWalManager.java:386) at org.apache.hadoop.hbase.master.MasterWalManager.splitLog(MasterWalManager.java:283) at org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure.splitLogs(ServerCrashProcedure.java:253) at org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure.executeFromState(ServerCrashProcedure.java:159) at org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure.executeFromState(ServerCrashProcedure.java:59) at org.apache.hadoop.hbase.procedure2.StateMachineProcedure.execute(StateMachineProcedure.java:184) at org.apache.hadoop.hbase.procedure2.Procedure.doExecute(Procedure.java:966) at org.apache.hadoop.hbase.procedure2.ProcedureExecutor.execProcedure(ProcedureExecutor.java:1723) at org.apache.hadoop.hbase.procedure2.ProcedureExecutor.executeProcedure(ProcedureExecutor.java:1462) at org.apache.hadoop.hbase.procedure2.ProcedureExecutor.access$1200(ProcedureExecutor.java:78) at org.apache.hadoop.hbase.procedure2.ProcedureExecutor$WorkerThread.run(ProcedureExecutor.java:2039)2022-08-25 10:56:03,956 INFO [PEWorker-8] master.SplitLogManager: Started splitting 1 logs in [hdfs://localhost:8020/hbase/WALs/localhost,16020,1661394447685-splitting] for [localhost,16020,1661394447685]2022-08-25 10:56:04,779 INFO [main-EventThread] coordination.SplitLogManagerCoordination: Task /hbase/splitWAL/WALs%2Flocalhost%2C16020%2C1661394447685-splitting%2Flocalhost%252C16020%252C1661394447685.1661395053086 acquired by localhost,16020,16613960524892022-08-25 10:56:04,800 INFO [main-EventThread] coordination.SplitLogManagerCoordination: Task /hbase/splitWAL/WALs%2Flocalhost%2C16020%2C1661394447685-splitting%2Flocalhost%252C16020%252C1661394447685.1661395053086 entered state=ERR localhost,16020,16613960524892022-08-25 10:56:04,800 WARN [main-EventThread] coordination.SplitLogManagerCoordination: Error splitting /hbase/splitWAL/WALs%2Flocalhost%2C16020%2C1661394447685-splitting%2Flocalhost%252C16020%252C1661394447685.16613950530862022-08-25 10:56:04,800 WARN [PEWorker-8] master.SplitLogManager: error while splitting logs in [hdfs://localhost:8020/hbase/WALs/localhost,16020,1661394447685-splitting] installed = 1 but only 0 done

August 25, 2022 · 1 min · jiezi

关于hbase:万字长文详解HBase读写性能优化

一、HBase 读优化1. HBase客户端优化和大多数零碎一样,客户端作为业务读写的入口,姿态应用不正确通常会导致本业务读提早较高实际上存在一些应用姿态的举荐用法,这里个别须要关注四个问题: 1) scan缓存是否设置正当?优化原理:在解释这个问题之前,首先须要解释什么是scan缓存,通常来讲一次scan会返回大量数据,因而客户端发动一次scan申请,理论并不会一次就将所有数据加载到本地,而是分成屡次RPC申请进行加载,这样设计一方面是因为大量数据申请可能会导致网络带宽重大耗费进而影响其余业务,另一方面也有可能因为数据量太大导致本地客户端产生OOM。在这样的设计体系下用户会首先加载一部分数据到本地,而后遍历解决,再加载下一部分数据到本地解决,如此往返,直至所有数据都加载实现。数据加载到本地就寄存在scan缓存中,默认100条数据大小。 本文参考 HBase 保姆级教程:HBase常识体系保姆级教程,五万字好文!通常状况下,默认的scan缓存设置就能够失常工作的。然而在一些大scan(一次scan可能须要查问几万甚至几十万行数据)来说,每次申请100条数据意味着一次scan须要几百甚至几千次RPC申请,这种交互的代价无疑是很大的。因而能够思考将scan缓存设置增大,比方设为500或者1000就可能更加适合。笔者之前做过一次试验,在一次scan扫描10w+条数据量的条件下,将scan缓存从100减少到1000,能够无效升高scan申请的总体提早,提早根本升高了25%左右。 优化倡议:大scan场景下将scan缓存从100增大到500或者1000,用以缩小RPC次数 2) get申请是否能够应用批量申请?优化原理:HBase别离提供了单条get以及批量get的API接口,应用批量get接口能够缩小客户端到RegionServer之间的RPC连接数,进步读取性能。另外须要留神的是,批量get申请要么胜利返回所有申请数据,要么抛出异样。 优化倡议:应用批量get进行读取申请 3) 申请是否能够显示指定列族或者列?优化原理:HBase是典型的列族数据库,意味着同一列族的数据存储在一起,不同列族的数据离开存储在不同的目录下。如果一个表有多个列族,只是依据Rowkey而不指定列族进行检索的话不同列族的数据须要独立进行检索,性能必然会比指定列族的查问差很多,很多状况下甚至会有2倍~3倍的性能损失。 优化倡议:能够指定列族或者列进行准确查找的尽量指定查找 4) 离线批量读取申请是否设置禁止缓存?优化原理:通常离线批量读取数据会进行一次性全表扫描,一方面数据量很大,另一方面申请只会执行一次。这种场景下如果应用scan默认设置,就会将数据从HDFS加载进去之后放到缓存。可想而知,大量数据进入缓存必将其余实时业务热点数据挤出,其余业务不得不从HDFS加载,进而会造成显著的读提早毛刺 优化倡议:离线批量读取申请设置禁用缓存,scan.setBlockCache(false) 2. HBase服务器端优化个别服务端端问题一旦导致业务读申请提早较大的话,通常是集群级别的,即整个集群的业务都会反映读提早较大。能够从4个方面动手: 1) 读申请是否平衡?优化原理:极其状况下如果所有的读申请都落在一台RegionServer的某几个Region上,这一方面不能施展整个集群的并发解决能力,另一方面势必造成此台RegionServer资源重大耗费(比方IO耗尽、handler耗尽等),落在该台RegionServer上的其余业务会因而受到很大的波及。可见,读申请不平衡不仅会造成自身业务性能很差,还会重大影响其余业务。当然,写申请不平衡也会造成相似的问题,可见负载不平衡是HBase的大忌。 察看确认:察看所有RegionServer的读申请QPS曲线,确认是否存在读申请不平衡景象 优化倡议:RowKey必须进行散列化解决(比方MD5散列),同时建表必须进行预分区解决 2) BlockCache是否设置正当?优化原理:BlockCache作为读缓存,对于读性能来说至关重要。默认状况下BlockCache和Memstore的配置绝对比拟平衡(各占40%),能够依据集群业务进行修改,比方读多写少业务能够将BlockCache占比调大。另一方面,BlockCache的策略抉择也很重要,不同策略对读性能来说影响并不是很大,然而对GC的影响却相当显著,尤其BucketCache的offheap模式下GC体现很优越。另外,HBase 2.0对offheap的革新(HBASE-11425)将会使HBase的读性能失去2~4倍的晋升,同时GC体现会更好! 察看确认:察看所有RegionServer的缓存未命中率、配置文件相干配置项一级GC日志,确认BlockCache是否能够优化 优化倡议:JVM内存配置量 < 20G,BlockCache策略抉择LRUBlockCache;否则抉择BucketCache策略的offheap模式;期待HBase 2.0的到来! 3) HFile文件是否太多?优化原理:HBase读取数据通常首先会到Memstore和BlockCache中检索(读取最近写入数据&热点数据),如果查找不到就会到文件中检索。HBase的类LSM构造会导致每个store蕴含少数HFile文件,文件越多,检索所需的IO次数必然越多,读取提早也就越高。文件数量通常取决于Compaction的执行策略,个别和两个配置参数无关: hbase.hstore.compactionThreshold hbase.hstore.compaction.max.size 前者示意一个store中的文件数超过多少就应该进行合并,后者示意参数合并的文件大小最大是多少,超过此大小的文件不能参加合并。这两个参数不能设置太’松’(前者不能设置太大,后者不能设置太小),导致Compaction合并文件的实际效果不显著,进而很多文件得不到合并。这样就会导致HFile文件数变多。 察看确认:察看RegionServer级别以及Region级别的storefile数,确认HFile文件是否过多 优化倡议:hbase.hstore.compactionThreshold设置不能太大,默认是3个;设置须要依据Region大小确定,通常能够简略的认为 hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compactionThreshold 4) Compaction是否耗费系统资源过多?优化原理:Compaction是将小文件合并为大文件,进步后续业务随机读性能,然而也会带来IO放大以及带宽耗费问题(数据近程读取以及三正本写入都会耗费零碎带宽)。失常配置状况下Minor Compaction并不会带来很大的系统资源耗费,除非因为配置不合理导致Minor Compaction太过频繁,或者Region设置太大状况下产生Major Compaction。 察看确认:察看零碎IO资源以及带宽资源应用状况,再察看Compaction队列长度,确认是否因为Compaction导致系统资源耗费过多 优化倡议: Minor Compaction设置:hbase.hstore.compactionThreshold设置不能太小,又不能设置太大,因而倡议设置为5~6;hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compactionThresholdMajor Compaction设置:大Region读提早敏感业务( 100G以上)通常不倡议开启主动Major Compaction,手动低峰期触发。小Region或者提早不敏感业务能够开启Major Compaction,但倡议限度流量;期待更多的优良Compaction策略,相似于stripe-compaction尽早提供稳固服务3. HBase列族设计优化HBase列族设计对读性能影响也至关重要,其特点是只影响单个业务,并不会对整个集群产生太大影响。列族设计次要从以下方面查看: 1) Bloomfilter是否设置?是否设置正当?优化原理:Bloomfilter次要用来过滤不存在待检索RowKey或者Row-Col的HFile文件,防止无用的IO操作。它会通知你在这个HFile文件中是否可能存在待检索的KV,如果不存在,就能够不必耗费IO关上文件进行seek。很显然,通过设置Bloomfilter能够晋升随机读写的性能。 Bloomfilter取值有两个,row以及rowcol,须要依据业务来确定具体应用哪种。如果业务大多数随机查问仅仅应用row作为查问条件,Bloomfilter肯定要设置为row,否则如果大多数随机查问应用row+cf作为查问条件,Bloomfilter须要设置为rowcol。如果不确定业务查问类型,设置为row。 优化倡议:任何业务都应该设置Bloomfilter,通常设置为row就能够,除非确认业务随机查问类型为row+cf,能够设置为rowcol 4. HDFS相干优化HDFS作为HBase最终数据存储系统,通常会应用三正本策略存储HBase数据文件以及日志文件。从HDFS的角度望下层看,HBase即是它的客户端,HBase通过调用它的客户端进行数据读写操作,因而HDFS的相干优化也会影响HBase的读写性能。这里次要关注如下三个方面: 1) Short-Circuit Local Read性能是否开启?优化原理:以后HDFS读取数据都须要通过DataNode,客户端会向DataNode发送读取数据的申请,DataNode承受到申请之后从硬盘中将文件读出来,再通过TPC发送给客户端。Short Circuit策略容许客户端绕过DataNode间接读取本地数据。(具体原理参考此处) ...

May 10, 2022 · 1 min · jiezi

关于hbase:HBase集群部署

1.搭建hbase须要依赖与zookeeper进行过程之间的通信,所以须要先部署zookeeper2.解压zookeeper,在/etc/profile.d/hadoop-etc.sh中增加环境变量,并将环境变量同步到其余两台服务器中。3.复制一个文件zoo_sample.cfg,并改名为zoo_.cfg;更改其中的配置信息,而后依据配置信息须要新建两个文件夹:一个长期文件目录(tmp),一个log目录4.将配置好的zookeeper文件拷贝到其余两台服务器中,并在每台服务器的tmp目录下新建一个myid文件,依据在配置文件zoo.cfg中指定1,2,3;顺次在三台机中指定。5.其中zookeeper集群:zkServer.sh start6.查看zookeeper集群的状态:一台leader、两台follower7.上传Hbase的安装包到soft文件夹下,解压到opt目录下,并改名为hbase8.在/etc/profile中增加环境变量,并将环境变量同步到其余两台服务器中,同时使环境变量立刻失效。9.批改hbase的配置文件:hbase-site.xml和regionservers10.留神批改配置文件:hbase-env.sh -- 解除正文,增加JAVA_HOME的门路11.将hbase整个文件夹同步到其余两台服务器中.1.解压# 解压/opt目录hbasetar -zxvf /soft/hbase-1.2.11-bin.tar.gz# 批改解压之后的文件名mv hbase-1.2.11/ hbase2.增加环境变量并同步到到其余两台服务器中vi /etc/profile# 追加以下内容export HBASE_HOME=/opt/hbaseexport PATH=$PATH:$HBASE_HOME/bin# 同步环境变量scp /etc/profile root@slave1:/etcscp /etc/profile root@slave2:/etc# 对立使环境变量失效(群发)source /etc/profile3.配置文件: hbase-site.xml<configuration> <property> <name>hbase.rootdir</name> <value>hdfs://master:9000/hbase</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>master,slave1,slave2</value> </property> <property> <name>hbase.tmp.dir</name> <value>/opt/hbase/tmp</value> </property></configuration>4.配置文件: regionserversslave1slave25.配置文件: hbase-env.shexport JAVA_HOME=/opt/jdK6.同步hbase到文件到其余两台服务器scp -r /opt/hbase/ root@slave1:/opt/scp -r /opt/hbase/ root@slave2:/opt/7.启动HBase# 1,首先确认曾经启动了Zookeeper,以及Hadoop集群# 2,而后启动HBasestart-hbase.sh

April 7, 2022 · 1 min · jiezi

关于hbase:HBase读链路分析

简介:HBase的存储引擎是基于LSM-Like树实现的,更新操作不会间接去更新数据,而是应用各种type字段(put,delete)来标记一个新的多版本数据,采纳定期compaction的模式来归档合并数据。这种数据结构将写操作变得非常简单且高效,然而却给读造成了很大的困扰。读取过程须要依据列族读取不同HFile中的数据;还须要依据版本进行过滤,同时对曾经标记删除的数据也要进行过滤;硬盘中的数据与MemStore中的数据重合时,还须要执行合并,最初在内存中拼接成一行残缺的数据再向上返回。 本文粗粒度地展现了HBase的读取链路,欢送一起探讨交换~ 注释之前在讲HBase的读门路时,咱们先来看几个简略的类图。 InternalScanner是一个Interface次要提供了两个办法,next(List<Cell> result)办法——获取下一行的数据。而next(List<Cell> result, ScannerContext scannerContext)提供性能雷同,只不过容许传入一个ScannerContext用以记录以后scan工作的上下文,判断是否能够提前结束、是否要去读下一列、是否要去读下一行等。并且产生在InternalScanner中的数据比拟等操作,都是基于byte[](而不必先转化为RowResults),更加靠近于数据在物理上的存储模式,能够取得更高的性能。 KeyValueScanner也是一个接口,换成CellScanner可能更容易了解。对,它次要提供在一个“可读取的对象上”,获取cell的能力。这里应用“可读取的对象”这个词,次要是因为它能够是一个物理概念上的HFile,但也能够是逻辑意义上有迭代读取能力的scanner。 最初一个要害的类就是KeyValueHeap,该类实现了KeyValueScanner与InternalScanner接口,具备了获取cell及获取行的能力。KeyValueHeap中还有一个要害的属性,为heap,它是一个PriorityQueue<KeyValueScanner>对象,comparator = CellComparatorImp(即依照key的格局:rowkeyqualifier:timestamp)。即KeyValueHeap容许传入多个KeyValueScanner,通过PriorityQueue的模式将这些scanner治理起来,向上提供获取cell及获取行数据的能力! 有了InternalScanner,KeyValueScanner和KeyValueHeap其实曾经能够做很多事件了。 咱们晓得,HBase的查问抽象地来看的话,是体现为上面这个流程的: 即从不同的HFile中进行数据读取,在内存中进行一个MergeSort,拼接成一行数据向上返回。 你们看KeyValueScanner、InternalScanner是不是就像其负责中HFile的读取Scanner,而KeyValueHeap负责的其实就是图中的MergeSort的工作。KeyValueHeap管制着上层KeyValueScanner、InternalScanner的数据读取,KeyValueScanner、InternalScanner是真正读取数据的Scanner。 好,大体的流程思路曾经讲清楚了。其实HBase的读取流程远比这简单,波及的对象也更多,但有了下面的根底置信能够了解得很容易,接下来咱们来认真看看HBase的读取流程。 注释咱们从RegionScanner登程,认真看看HBase的读取流程。 上图中的RegionScanner次要靠成员变量storeHeap,joinedHeap(KeyValueHeap)进行数据读取迭代。而StoreScanner也不是一个单纯的Scanner,而是表演了跟RegionScanner相似的角色,它也领有本人的heap,以此来进行数据的读取。跟【注释之前】说的一样,KeyValueHeap管制着上层KeyValueScanner、InternalScanner的数据读取,KeyValueScanner、InternalScanner是真正读取数据的Scanner。只不过RegionScanner中多嵌了一层StoreScanner(KeyValueHeap),变成了这样的调用链路:KeyValueHeap(RegionScanner)->KeyValueHeap(StoreScanner) ->KeyValueScanner,InternalScanner(StoreFileScanner及SegmentScanner)。 为什么HBase要这样封装?其实是为了形象不同的性能。 简略来说, 1)StoreScanner是为了联结StoreFileScanner与SegmentScanner向上提供整行的数据迭代读取性能。 2)而RegionScanner,一方面是对获取的数据做了过滤性能,另一方面是为了将全副数据分为两段获取模式(storeHeap和joinedHeap),用以优化性能。因为从storeHeap中获取的数据如果会被过滤,那么就没有必要再获取joinedHeap中的数据了。 具体内容咱们见下文。 HBase的读取工作开始之前须要构建初始的Scanner体系,波及RegionScanner与StoreScanner的对象初始化,咱们具体来看: 1)RegionScanner对象的初始化: 1.建设RegionScanner对象,筹备开始Scan工作波及的所有Scanner的生成。 2.依据scan工作波及的所有column family,在本region上别离会为其中的每个column family生成一个StoreScanner。如果开启了on-demand column family loading,那么会依据传入FilterList的isFamilyEssential办法进行判断,如果isFamilyEssential,那么会将该StoreScanner放入storeHeap中,否则放入joinedHeap中。 3.storeHeap和joinedHeap中寄存StoreScanner的模式为PriorityQueue,优先级为CellComparatorImp。 2)StoreScanner对象的初始化 接下来咱们介绍RegionScanner对象的初始化中,咱们一笔带过的StoreScanner的生成过程: 1.依据scan.isReversed()管制StoreScanner中的Scanner的优先级程序。 2.依据传入的scan信息,生成matcher内置对象,该对象在查问过程中会对StoreScanner读取的数据进行一个筛选。 3.依据scan信息startRow,stopRow在storeEngine中查问出波及的HStoreFile,对这些HStoreFile别离建设StoreFileScanner,组成scannerList,并且以StoreFileComparators.SEQ_ID为优先级(maxSequenceId升序,FileSize降序,BulkTime升序,PathName升序)。 4.对scannerList依据timestamp range, row key range, bloomFilter做一个过滤。 5.scannerList中残余的scanner依据startRow,stopRow将指针seek到正确的地位。 6.将scanners以PriorityQueue的模式组织,优先级同样为CellComparatorImp。 PS:StoreFileComparators.SEQ_ID —— Comparator.comparingLong(HStoreFile::getMaxSequenceId) .thenComparing(Comparator.comparingLong(new GetFileSize()).reversed()) .thenComparingLong(new GetBulkTime()).thenComparing(new GetPathName()) 组建好须要Scanner体系之后,后续就是读取流程了。 读取流程如下图所示: RegionScanner次要负责以下性能: 其蕴含storeHeap与joinedHeap都为KeyValueHeap的对象实例,heap底层是蕴含了多个StoreScanner组成的PriorityQueue,comparator = CellComparatorImp。向上提供符合条件的整行数据的迭代查问。 ...

February 8, 2022 · 1 min · jiezi

关于hbase:HBase的-rowkey-设计原则

hbase所谓的三维有序存储的三维是指:rowkey(行主键),column key(columnFamily+qualifier),timestamp(工夫戳)三局部组成的三维有序存储。 rowkey是行的主键,而且hbase只能用个rowkey,或者一个rowkey范畴即scan来查找数据。所以 rowkey的设计是至关重要的,关系到你应用层的查问效率。 rowkey是以字典程序排序的,存储的是字节码。 Rowkey设计准则 1.Rowkey的惟一准则 必须在设计上保障其唯一性。因为在HBase中数据存储是Key-Value模式,若HBase中同一表插入雷同Rowkey,则原先的数据会被笼罩掉(如果表的version设置为1的话),所以务必保障Rowkey的唯一性. 2.Rowkey的排序准则 HBase的Rowkey是依照ASCII有序设计的,咱们在设计Rowkey时要充分利用这点。比方视频网站上对影片《泰坦尼克号》的弹幕信息,这个弹幕是依照工夫倒排序展现视频里,这个时候咱们设计的Rowkey要和工夫程序相干。能够应用"Long.MAX_VALUE - 弹幕发表工夫"的 long 值作为 Rowkey 的前缀。 3.Rowkey的散列准则 咱们设计的Rowkey应平均的散布在各个HBase节点上。拿常见的工夫戳举例,如果Rowkey是按零碎工夫戳的形式递增,Rowkey的第一局部如果是工夫戳信息的话将造成所有新数据都在一个RegionServer上沉积的热点景象,也就是通常说的Region热点问题, 热点产生在大量的client间接拜访集中在个别RegionServer上(拜访可能是读,写或者其余操作),导致单个RegionServer机器本身负载过高,引起性能降落甚至Region不可用,常见的是产生jvm full gc或者显示region too busy异样情 况,当然这也会影响同一个RegionServer上的其余Region。 Region热点问题 1、Reverse反转 针对固定长度的Rowkey反转后存储,这样能够使Rowkey中常常扭转的局部放在最后面,能够无效的随机Rowkey。 反转Rowkey的例子通常以手机举例,能够将手机号反转后的字符串作为Rowkey,这样的就防止了以手机号那样比拟固定结尾(137x、15x等)导致热点问题,这样做的毛病是就义了Rowkey的有序性。 2、Salt加盐 Salt是将每一个Rowkey加一个前缀,前缀应用一些随机字符,使得数据扩散在多个不同的Region,达到Region负载平衡的指标。 比方在一个有4个Region(注:以 [ ,a)、[a,b)、[b,c)、[c, )为Region起至)的HBase表中,加Salt前的Rowkey:abc001、abc002、abc003 咱们别离加上a、b、c前缀,加Salt后Rowkey为:a-abc001、b-abc002、c-abc003 能够看到,加盐前的Rowkey默认会在第2个region中,加盐后的Rowkey数据会散布在3个region中,实践上解决后的吞吐量应是之前的3倍。因为前缀是随机的,读这些数据时须要消耗更多的工夫,所以Salt减少了写操作的吞吐量,不过毛病是同时减少了读操作的开销。 3、Hash散列或者Mod 用Hash散列来代替随机Salt前缀的益处是能让一个给定的行有雷同的前缀,这在扩散了Region负载的同时,使读操作也可能推断。确定性Hash(比方md5后取前4位做前缀)能让客户端重建残缺RowKey,能够应用get操作间接get想要的行。 4.Rowkey的长度准则 复制代码 Rowkey长度设计准则:Rowkey是一个二进制,Rowkey的长度被很多开发者倡议说设计在10~100个字节,倡议是越短越好。 起因有两点: 其一是HBase的长久化文件HFile是依照KeyValue存储的,如果Rowkey过长比方500个字节,1000万列数据光Rowkey就要占用500*1000万=50亿个字节,将近1G数据,这会极大影响HFile的存储效率; 其二是MemStore缓存局部数据到内存,如果Rowkey字段过长内存的无效利用率会升高,零碎无奈缓存更多的数据,这会升高检索效率; 须要指出的是不仅Rowkey的长度是越短越好,而且列族名、列名等尽量应用短名字,因为HBase属于列式数据库,这些名字都是会写入到HBase的长久化文件HFile中去,过长的Rowkey、列族、列名都会导致整体的存储量成倍增加。 关键词:大数据培训

January 21, 2022 · 1 min · jiezi

关于hbase:HBase-数据存储结构详细解读

在「HBase」中, 从逻辑上来讲数据大略就长这样: 单从图中的逻辑模型来看, HBase 和 MySQL 的区别就是: 将不同的列归属与同一个列族下反对多版本数据这看着感觉也没有那么太大的区别呀, 它解决了 MySQL 的那些问题呢? 每一个新事物的呈现, 都是为了解决本来存在的问题. 对写入敌对, 反对异步大批量并发写入可动静增加列按列存储数据, 不存在的列不会落盘, 节俭空间. 而 MySQL 中不存在的内容也要用 null 填充反对海量数据分布式存储(BigTable 最开始就是 Google 为了解决数据存储问题而提出来的)等等那么他是如何解决这些问题的呢? 他的数据是如何进行存储的呢? HBase 数据物理构造在介绍其物理构造之前, 要先简略提一下 LSM 树 LSM树和 MySQL 所应用的B+树一样, 也是一种磁盘数据的索引构造. B+树是一种对读取敌对的存储构造, 然而当大量写入的时候, 比方日志信息, 因为波及到随机写入, 就显得顾此失彼了. 而「LSM树」就是针对这种大量写入的场景而提出的. 他的中文名字叫: 日志构造合并树. 文件存储的是对数据的批改操作, 数据会 append 但不会去批改原有的数据. 是程序写入操作. 然而, 如果不管不顾的将所有的操作都程序写入了, 大数据培训那读取数据的时候没有任何依据, 须要扫描所有操作能力读到. 「LSM 树」的做法是, 先在内存中保护一份小的有序的数据(内存不存在随机读写的问题), 当这份数据超过肯定大小的时候, 将其整个放入磁盘中. 这样, 磁盘中就存在很多个有序的文件了, 然而会有大量的小文件, 读取数据时要顺次查找, 导致读取性能升高. 这时就须要对多个小文件进行多路归并合成一个文件来优化读取的性能. 至此, 根本就是「LSM 树」的全副思维了. 在内存中保护一个有序的数据将内存中的数据push 到磁盘中将磁盘中的多个有序文件进行归并, 合成一个较大的有序文件HBase存储在「HBase」中, 数据的存储就应用了 「LSM 树」进行存储. 其中每一条数据都是一条操作记录. 那么在「HBase」实现中的局部内容如下. ...

January 5, 2022 · 1 min · jiezi

关于hbase:实战大数据HBase-性能调优指南

1 HBase 表结构设计调优1.1 Row Key 设计HBase 中 row key 用来检索表中的记录,反对以下三种形式: 通过单个 row key 拜访:即依照某个 row key 键值进行 get 操作; 通过 row key 的 range 进行 scan:即通过设置 startRowKey 和 endRowKey,在这个范畴内进行扫描; 全表扫描:即间接扫描整张表中所有行记录。 在 HBase 中,row key 能够是任意字符串,最大长度 64KB,理论利用中个别为 10~100bytes,存为 byte[]字节数组,个别设计成定长的。 row key 是依照字典序存储,因而,设计 row key 时,要充分利用这个排序特点,将常常一起读取的数据存储到一块,将最近可能会被拜访的数据放在一块。 举个例子:如果最近写入 HBase 表中的数据是最可能被拜访的,能够思考将工夫戳作为 row key 的一部分,因为是字典序排序,所以能够应用 Long.MAX_VALUE - timestamp 作为 row key,这样能保障新写入的数据在读取时能够被疾速命中。 Rowkey 规定: rowkey 是一个二进制码流,长度越小越好,个别不超过 16 个字节,次要出于以下思考: 数据的长久化文件 HFile 中是依照 KeyValue 存储的,即你写入的数据可能是一个 rowkey 对应多个列族,多个列,然而理论的存储是每个列都会对应 rowkey 写一遍,即这一条数据有多少个列,就会存储多少遍 rowkey,这会极大影响 HFile 的存储效率; ...

December 29, 2021 · 5 min · jiezi

关于hbase:Hbase-和-Redis-的持久化等级

Hbase 的长久化等级援用自《Hbase原理和实际》第六章 6.1 Hbase 的写入流程HBase 能够通过设置HLog的长久化等级决定是否开启 HLog 机制以及 HLog 的落盘形式。HLog的长久化等级分为如下五个等级。• SKIP_WAL:只写缓存,不写HLog日志。因为只写内存,因而这种形式能够极大地晋升写入性能,然而数据有失落的危险。在理论利用过程中并不倡议设置此等级,除非确认不要求数据的可靠性。• ASYNC_WAL:异步将数据写入HLog日志中。• SYNC_WAL:同步将数据写入日志文件中,须要留神的是,数据只是被写入文件系统中,并没有真正落盘。HDFS Flush策略详见HADOOP-6313。• FSYNC_WAL:同步将数据写入日志文件并强制落盘。这是最严格的日志写入等级,能够保证数据不会失落,然而性能绝对比拟差。• USER_DEFAULT:如果用户没有指定长久化等级,默认HBase应用SYNC_WAL等级长久化数据。 Mysql 的长久化等级redo log 的长久化1、长久化策略通过参数 innodb_flush_log_at_trx_commit 管制。 设置为 0 的时候,示意每次事务提交时都只是把 redo log 留在 redo log buffer 中 ; MySQL 解体就会失落。设置为 1 的时候,示意每次事务提交时都将 redo log 间接长久化到磁盘(将 redo log buffer 中的操作全副进行长久化,可能会蕴含其余事务还未提交的记录);断电也不会失落。设置为 2 的时候,示意每次事务提交时都只是把 redo log 写到 page cache。MySQL 解体不会失落,断电会失落。 2、InnoDB 后盾还有一个线程会每隔一秒钟将 redo log buffer 中记录的操作执行 write 写到 page cache,而后再 fsync 到磁盘上。 未提交的事务操作也可能会长久化,未提交事务操作的长久化触发场景如下: 1、redo log buffer 被占用的空间达到 innodb_log_buffer_size(redo log buffer 大小参数)的一半时,后盾会被动写盘,无论是否是已实现的事务操作都会执行。 ...

December 12, 2021 · 1 min · jiezi

关于hbase:HBase知识点总结

一、HBase根底HBase 是一种建设在 Hadoop 文件系统之上的分布式、可扩大、反对海量数据存储的 NoSQL 数据库。HBase 是 BigTable 的开源 Java 版本。是建设在 HDFS 之上,提供高可靠性、高性能、列存储、可伸缩、实时读写 NoSql 的数据库系统。 它介于 NoSql 和 RDBMS 之间,仅能通过主键(rowKey)和主键的 range 来检索数据,仅反对单行事务(可通过 Hive 反对来实现多表 join 等简单操作)。次要用来存储结构化和半结构化的涣散数据。HBase 查问数据性能很简略,不反对 join 等简单操作,不反对简单的事务(行级的事务)。 HBase 不限度存储的数据的品种,容许动静的、灵便的数据模型,不必 SQL 语言,也不强调数据之间的关系。HBase被设计成在一个服务器集群上运行,能够相应地横向扩大。利用 HBase 技术可在便宜 PC Server 上搭建起大规模结构化存储集群。 HBase 自身是一个数据模型,相似于谷歌的大表设计(BIgtable),能够提供疾速随机拜访海量结构化数据。它利用了 Hadoop 的文件系统(HDFS)提供的容错能力,提供对数据的随机实时读/写访问,是Hadoop文件系统的一部分。 人们能够间接或通过 HBase 存储 HDFS 数据,也能够应用 HBase 在 HDFS 读取生产/随机拜访数据。 HBase 利用 Hadoop 的 MapReduce 来解决海量数据。协同服务方面 Google Bigtable 利用 Chubby 来反对 ,HBase 的 Zookeeper 与之对应。 HBase 中的表个别有这样的特点: 大:一个表能够有上十亿行,上百万列。面向列:面向列(族)的存储和权限管制,列(族)独立检索。稠密:对于为空(null)的列,并不占用存储空间,因而,表能够设计的十分稠密。二、 HDFS 、Hive 、HBase 三者比照1、HDFS 与 HBase 比照 ...

November 21, 2021 · 7 min · jiezi

关于hbase:关于-Cassandra-和-Hbase-的思考

Facebook当初想用cassandra实现其音讯零碎,但起初发现不适合,起因不是cassandra不靠谱,而是Cassandra的最终一致性模型不适宜Message System,HBase具备更简略的一致性模型。Cassandra强调AP ,Hbase强调CP。目前Facebook的inbox search零碎在应用,8亿用户,200T数据;其挪动利用开发平台也应用cassandra。 作者:Ecomshot链接:https://www.zhihu.com/questio...起源:知乎著作权归作者所有。商业转载请分割作者取得受权,非商业转载请注明出处。

November 14, 2021 · 1 min · jiezi

关于hbase:hbase-启动它

启动 hbase 和 thrift 的脚本 sudo bash ~/opt/hbase/bin/start-hbase.shnetstat -tunlp | grep 600sudo bash ~/opt/hbase/bin/hbase-daemon.sh start thriftnetstat -tunlp | grep 90输入 vagrant@vagrant:/vagrant$ sudo bash myhbase_go.sh master running as process 2143. Stop it first.tcp6 0 0 127.0.1.1:16000 :::* LISTEN 2143/java thrift running as process 2293. Stop it first.tcp6 0 0 :::9090 :::* LISTEN 2293/java tcp6 0 0 :::9095 :::* LISTEN 2293/java 查看端口号的命令 netstat -tunlp | grep 端口号参考文章:Hadoop, HBase, Hive, ZooKeeper默认端口阐明

October 9, 2021 · 1 min · jiezi

关于hbase:大数据开发技术之如何将数据导入到HBase

在理论生产环境中,将计算和存储进行拆散,是咱们进步集群吞吐量、确保集群规模程度可扩大的次要办法之一,并且通过集群的扩容、性能的优化,确保在数据大幅增长时,存储不能称为零碎的瓶颈。大数据培训 具体到咱们理论的我的项目需要中,有一个典型的场景,通常会将Hive中的局部数据,比方热数据,存入到HBase中,进行冷热拆散解决。 咱们采纳Spark读取Hive表数据存入HBase中,这里次要有两种形式: 通过HBase的put API进行数据的批量写入 通过生成HFile文件,而后通过BulkLoad形式将数据存入HBase HBase的原生put形式,通过HBase集群的region server向HBase插入数据,然而当数据量十分大时,region会进行split、compact等解决,并且这些解决十分占用计算资源和IO开销,影响性能和集群的稳定性。 HBase的数据最终是以HFile的模式存储到HDFS上的,如果咱们能间接将数据生成为HFile文件,而后将HFile文件保留到HBase对应的表中,能够防止上述的很多问题,效率会绝对更高。 本篇文章次要介绍如何应用Spark生成HFile文件,而后通过BulkLoad形式将数据导入到HBase中,并附批量put数据到HBase以及间接存入数据到HBase中的理论利用示例。 1. 生成HFile,BulkLoad导入 1.1 数据样例 {"id":"1","name":"jack","age":"18"}{"id":"2","name":"mike","age":"19"}{"id":"3","name":"kilos","age":"20"}{"id":"4","name":"tom","age":"21"}... 1.2 示例代码 /** @Author bigdatalearnshare */object App { def main(args: Array[String]): Unit = { System.setProperty("HADOOP_USER_NAME", "root")val sparkSession = SparkSession .builder() .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") .master("local[*]") .getOrCreate()val rowKeyField = "id"val df = sparkSession.read.format("json").load("/people.json")val fields = df.columns.filterNot(_ == "id").sortedval data = df.rdd.map { row => val rowKey = Bytes.toBytes(row.getAs(rowKeyField).toString) val kvs = fields.map { field => new KeyValue(rowKey, Bytes.toBytes("hfile-fy"), Bytes.toBytes(field), Bytes.toBytes(row.getAs(field).toString)) } (new ImmutableBytesWritable(rowKey), kvs)}.flatMapValues(x => x).sortByKey()val hbaseConf = HBaseConfiguration.create(sparkSession.sessionState.newHadoopConf())hbaseConf.set("hbase.zookeeper.quorum", "linux-1:2181,linux-2:2181,linux-3:2181")hbaseConf.set(TableOutputFormat.OUTPUT_TABLE, "hfile")val connection = ConnectionFactory.createConnection(hbaseConf)val tableName = TableName.valueOf("hfile")//没有HBase表则创立creteHTable(tableName, connection)val table = connection.getTable(tableName)try { val regionLocator = connection.getRegionLocator(tableName) val job = Job.getInstance(hbaseConf) job.setMapOutputKeyClass(classOf[ImmutableBytesWritable]) job.setMapOutputValueClass(classOf[KeyValue]) HFileOutputFormat2.configureIncrementalLoad(job, table, regionLocator) val savePath = "hdfs://linux-1:9000/hfile_save" delHdfsPath(savePath, sparkSession) job.getConfiguration.set("mapred.output.dir", savePath) data.saveAsNewAPIHadoopDataset(job.getConfiguration) val bulkLoader = new LoadIncrementalHFiles(hbaseConf) bulkLoader.doBulkLoad(new Path(savePath), connection.getAdmin, table, regionLocator)} finally { //WARN LoadIncrementalHFiles: Skipping non-directory hdfs://linux-1:9000/hfile_save/_SUCCESS 不影响,间接把文件移到HBASE对应HDFS地址了 table.close() connection.close()}sparkSession.stop()} ...

October 8, 2021 · 2 min · jiezi

关于hbase:带你了解-HBase-数据模型和-HBase-架构

摘要:HBase 是一个面向列的 NoSQL 数据库。本文分享自华为云社区《HBase 架构:HBase 数据模型 & HBase 读/写机制》,作者: Donglian Lin 。 HBase 架构:HBase 数据模型家喻户晓,HBase 是一个面向列的 NoSQL 数据库。尽管它看起来相似于蕴含行和列的关系数据库,但它不是关系数据库。关系数据库是面向行的,而 HBase 是面向列的。那么,让咱们首先理解面向列和面向行的数据库之间的区别: 面向行与面向列的数据库: • 面向行的数据库以行的顺序存储表记录。而面向列的数据库 将表记录存储在一系列列中,即列中的条目存储在磁盘上的间断地位。 为了更好地了解它,让咱们举个例子并思考下表。 如果此表存储在面向行的数据库中。它将存储如下所示的记录: 1 ,保罗沃克,美国, 231 ,加拉多, 2, Vin Diesel ,巴西, 520 , Mustang 如上所示,在面向行的数据库中,数据是基于行或元组存储的。 尽管面向列的数据库将此数据存储为: 1 , 2 , Paul Walker , Vin Diesel , 美国,巴西, 231 , 520 , Gallardo , Mustang 在面向列的数据库中,所有列值都存储在一起,就像第一列值将存储在一起,而后第二列值将一起存储,其余列中的数据以相似形式存储。 • 当数据量十分大时,比方 PB 级或 EB 级,咱们应用面向列的办法,因为单列的数据存储在一起,能够更快地拜访。• 尽管面向行的办法绝对无效地解决较少数量的行和列,但面向行的数据库存储数据是一种结构化格局。• 当咱们须要解决和剖析大量半结构化或非结构化数据时,咱们应用面向列的办法。例如解决在线剖析解决的应用程序,如数据挖掘、数据仓库、包含剖析在内的应用程序等。• 而在线事务处理(例如解决结构化数据并须要事务属性(ACID 属性)的银行和金融畛域)应用面向行的办法。 HBase 表具备以下组件,如下图所示: ...

September 24, 2021 · 3 min · jiezi

关于hbase:Apache-Kylin-400-正式发布

Apache Kylin 社区于日前发表:Apache Kylin 4.0.0 正式公布!欢送大家下载应用。 Apache Kylin 是行业当先的开源分布式的剖析型数据仓库,提供 Hadoop/Spark 之上的 SQL 查问接口及多维分析 (OLAP) 能力,反对对超大规模数据进行亚秒级查问,已被 eBay、腾讯、美团、滴滴、汽车之家、贝壳找房、OLX 团体等寰球超过 1500 家企业采纳。 1. Release NotesApache Kylin 4.0.0 是 Kylin 3(HBase Storage)版本后的一次重大版本更新,Kylin 4 应用 Parquet 这种真正的列式存储来代替 HBase 存储,从而晋升文件扫描性能;同时,Kylin 4 从新实现了基于 Spark 的构建引擎和查问引擎,使得计算和存储的拆散变为可能,更加适应云原生的技术趋势。 Kylin 4.0.0 是继 4.0.0-alpha、4.0.0-beta 之后 Kylin 4 (Parquet Storage)的第一个正式版本,这次公布绝对上次公布退出了构建性能优化、查问性能优化、Spark 3 反对、元数据降级工具等若干重要个性。此次公布共增加了 32 个新性能和性能加强,修复了 10 个问题和缺点等,详情请拜访:https://kylin.apache.org/docs...  在去 Hadoop 迈向云原生的过程中,Apache Kylin 也做了踊跃的尝试,通过应用对象存储代替 HDFS,应用 Spark Standalone 代替 Yarn,来逐步升高 Kylin 的学习老本和保护难度,从而打造成为一个简化和对立的,领有高性能和低 TCO 的 OLAP 平台。你能够通过以下文档来理解应用过程:https://kylin.apache.org/docs...  ...

September 4, 2021 · 3 min · jiezi

关于hbase:Apache-HBase-MTTR-优化实践减少恢复时长

摘要:HBase是Hadoop Database的简称,是建设在Hadoop文件系统之上的分布式面向列的数据库,它具备高牢靠、高性能、面向列和可伸缩的个性,提供疾速随机拜访海量数据能力。本文分享自华为云社区《Apache HBase MTTR 优化实际》,作者: pippo。 HBase介绍HBase是Hadoop Database的简称,是建设在Hadoop文件系统之上的分布式面向列的数据库,它具备高牢靠、高性能、面向列和可伸缩的个性,提供疾速随机拜访海量数据能力。 HBase采纳Master/Slave架构,由HMaster节点、RegionServer节点、ZooKeeper集群组成,底层数据存储在HDFS上。 整体架构如图所示: HMaster次要负责: 在HA模式下,蕴含主用Master和备用Master。主用Master:负责HBase中RegionServer的治理,包含表的增删改查;RegionServer的负载平衡,Region散布调整;Region决裂以及决裂后的Region调配;RegionServer生效后的Region迁徙等。备用Master:当主用Master故障时,备用Master将取代主用Master对外提供服务。故障复原后,原主用Master降为备用。RegionServer次要负责: 寄存和治理本地HRegion。RegionServer负责提供表数据读写等服务,是HBase的数据处理和计算单元,间接与Client交互。RegionServer个别与HDFS集群的DataNode部署在一起,实现数据的存储性能。读写HDFS,治理Table中的数据。ZooKeeper集群次要负责: 寄存整个 HBase集群的元数据以及集群的状态信息。实现HMaster主从节点的Failover。HDFS集群次要负责: HDFS为HBase提供高牢靠的文件存储服务,HBase的数据全副存储在HDFS中。构造阐明: Store 一个Region由一个或多个Store组成,每个Store对应图中的一个Column Family。MemStore 一个Store蕴含一个MemStore,MemStore缓存客户端向Region插入的数据,当RegionServer中的MemStore大小达到配置的容量下限时,RegionServer会将MemStore中的数据“flush”到HDFS中。StoreFile MemStore的数据flush到HDFS后成为StoreFile,随着数据的插入,一个Store会产生多个StoreFile,当StoreFile的个数达到配置的阈值时,RegionServer会将多个StoreFile合并为一个大的StoreFile。HFile HFile定义了StoreFile在文件系统中的存储格局,它是以后HBase零碎中StoreFile的具体实现。HLog(WAL) HLog日志保障了当RegionServer故障的状况下用户写入的数据不失落,RegionServer的多个Region共享一个雷同的HLog。HBase提供两种API来写入数据。 Put:数据间接发送给RegionServer。BulkLoad:间接将HFile加载到表存储门路。HBase为了保证数据可靠性,应用WAL(Write Ahead Log)来保证数据可靠性。它是HDFS上的一个文件,记录HBase中数据的所有更改。所有的写操作都会先保障将数据写入这个文件后,才会真正更新MemStore,最初写入HFile中。如果写WAL文件失败,则操作会失败。在失常状况下,不须要读取WAL文件,因为数据会从MemStore中长久化为HFile文件。然而如果RegionServer在长久化MemStore之前解体或者不可用,零碎依然能够从WAL文件中读取数据,回放所有操作,从而保证数据不失落。 写入流程如图所示: 默认状况下RegionServer上治理的所有HRegion共享同一个WAL文件。WAL文件中每个记录都包含相干Region的信息。当关上Region时,须要回放WAL文件中属于该Region的记录信息。因而,WAL文件中的记录信息必须按Region进行分组,以便能够回放特定Region的记录。按Region分组WAL的过程称为WAL Split。 WAL Split由HMaster在集群启动时实现或者在RegionServer敞开时由ServershutdownHandler实现。在给定的Region再次可用之前,须要复原和回放所有的WAL文件。因而在数据恢复之前,对应的Region无奈对外服务。 HBase启动时,Region调配简要调配流程如下: HMaster启动时初始化AssignmentManager。AssignmentManager通过hbase:meta表查看以后Region调配信息。如果Region调配仍然无效(Region所在RegionServer仍然在线),则保留调配信息。如果Region调配有效,调用LoadBalancer来进行重调配。调配实现后更新hbase:meta表。本文次要关注集群重新启动和复原相干内容,着重形容相干优化,缩小HBase复原时长。 RegionServer故障复原流程当HMaster检测到故障时,会触发SCP(Server Crash Procedure)流程。SCP流程包含以下次要步骤: HMaster创立WAL Split工作,用于对属于解体RegionServer上Region进行记录分组。将原属于解体RegionServer上Region进行重调配,调配给失常RegionServer。失常RegionServer执行Region上线操作,对须要复原数据进行回放。故障复原常见问题HMaster期待Namespace表超时终止当集群进行重启时,HMaster进行初始化会找到所有的异样RegionServer(Dead RegionServer)并开始SCP流程,并持续初始化Namespace表。 如果SCP列表中存在大量的RegionServer,那么Namespace表的调配将可能被提早并超过配置的超时工夫(默认5分钟),而这种状况在大集群场景下是最常见的。为长期解决该问题,经常将默认值改大,然而必不能保障肯定会胜利。 另外一种形式是在HMaster上启用表来防止此问题(hbase.balancer.tablesOnMaster=hbase:namespace),HMaster会优先将这些表进行调配。然而如果配置了其它表也能够调配到HMaster或者因为HMaster性能问题,这将无奈做到100%解决此问题。此外在HBase 2.X版本中也不举荐应用HMaster来启用表。解决这个问题的最佳办法是反对优先表和优先节点,当HMaster触发SCP流程时,优先将这些表调配到优先节点上,确保调配的优先级,从而齐全打消此问题。 批量调配时RPC超时HBase专门线性可扩展性而设计。如果集群中的数据随着表减少而增多,集群能够很容易扩大增加RegionServer来治理表和数据。例如:如果一个集群从10个RegionServer扩大到20个RegionServer,它在存储和解决能力方面将会减少。 随着RegionServer上Region数量的减少,批量调配RPC调用将会呈现超时(默认60秒)。这将导致从新进行调配并最终对调配上线工夫产生重大影响。 在10个RegionServer节点和20个RegionServer节点的测试中,RPC调用别离破费了约60秒和116秒。对于更大的集群来说,批量调配无奈一次胜利。次要起因在于对ZooKeeper进行大量的读写操作和RPC调用,用来创立OFFLINE ZNode节点,创立正在复原的Region ZNode节点信息等。 复原可扩展性测试在10到100个节点的集群测试中,咱们察看到复原工夫随着集群规模的增大而线性减少。这意味着集群越大,复原所需的工夫就越多。特地是当要复原WAL文件时,复原工夫将会十分大。在100个节点的集群中,通过Put申请写入数据的状况下,复原须要进行WAL Split操作,发现须要100分钟能力从集群解体中完全恢复。而在雷同规模的集群中,如果不写入任何数据大概须要15分钟。这意味着85%以上的工夫用于WAL Split操作和回放用于复原。 上面咱们将分析测试过程中发现的瓶颈在哪里? 复原耗时剖析HDFS负载在10个节点的HBase集群上,通过JMX来获取HDFS的RPC申请监控信息,发现在启动阶段有1200万读取RPC调用。 其中GetBlockLocationNumOps:380万、GetListingNumOps:13万、GetFileInfoNumOps:840万。 当集群规模达到100个时,RPC调用和文件操作将会十分大,从而对HDFS负载造成很大压力,成为瓶颈。可能因为以下起因导致HDFS写入失败、WAL Split和Region上线迟缓超时重试。 微小的预留磁盘空间。并发拜访达到DataNode的xceiver的限度。HMaster负载HMaster应用基于ZooKeeper的分配机制时,在Region上线过程中HMaster会创立一个OFFLINE ZNode节点,RegionServer会将该ZNode更新为OPENING和OPENED状态。对于每个状态变动,HMaster都会进行监听并解决。 对于100个节点的HBase集群,大略将会有6,000,000个ZNode创立和更新操作和4,000,000个监听事件要进行解决。 ZooKeeper的监听事件告诉解决是程序的,旨在保障事件的程序。这种设计在Region锁获取阶段将会导致提早。在10个节点的集群中发现等待时间为64秒,而20节点的集群中等待时间为111秒。 GeneralBulkAssigner 在批量发送OPEN RPC申请到RegionServer之前会获取相干Region的锁,再收到RegionServer的OPEN RPC申请响应时才会开释该锁。如果RegionServer再解决批量OPEN RPC申请时须要工夫,那么在收到确认响应之前GeneralBulkAssigner将不会开释锁,其实局部Region曾经上线,也不会独自解决这些Region。 HMaster依照程序创立OFFLINE ZNode节点。察看发现在执行批量调配Region到RegionServer之前将会有35秒的提早来创立ZNode。 采纳不依赖ZooKeeper的分配机制将会缩小ZooKeeper的操作,能够有50%左右的优化。HMaster仍然会协调和解决Region的调配。 晋升WAL Split性能长久化FlushedSequenceId来减速集群重启WAL Split性能(HBASE-20727)ServerManager有每个Region的flushedSequenceId信息,这些信息被保留在一个Map构造中。咱们能够利用这些信息来过滤不须要进行回放的记录。然而这个Map构造并没有被长久化,当集群重启或者HMaster重启后,每个Region的flushedSequenceId信息将会失落。 ...

August 18, 2021 · 1 min · jiezi

关于hbase:赵强老师HBase的体系架构

一、什么是HBase?HBase是一个基于HDFS之上的分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“BigTable大表”,即:把所有的数据存入一张表中。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了相似于Bigtable的能力。HBase是Apache的Hadoop我的项目的子项目。HBase不同于个别的关系数据库,它是一个适宜于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式。 二、HBase的体系架构 HBase是由三种类型的服务器以主从模式形成的。这三种服务器别离是:HBase HMaster,Region server,ZooKeeper。 HBase HMaster负责Region的调配及数据库的创立和删除等操作。具体来说,HMaster的职责包含:HMaster负责region的调配。调控Region server的工作在集群启动的时候调配region,依据复原服务或者负载平衡的须要重新分配region。监控集群中的Region server的工作状态。治理数据库。提供创立,删除或者更新表格的接口。Region server负责数据的读写服务。用户通过沟通Region server来实现对数据的拜访。具体来说,RegionServer上存在若干个Region。HBase中的表是依据row key的值程度宰割成所谓的region的。一个region蕴含表中所有row key位于region的起始键值和完结键值之间的行。每一个region的默认大小为1GB。集群中负责管理Region的结点叫做Region server。Region server负责数据的读写。每一个Region server大概能够治理1000个region。 ZooKeeper负责保护集群的状态(某台服务器是否在线,服务器之间数据的同步操作及master的选举等)。HBase中ZooKeeper的职责蕴含:保护HBase服务器是否存活监控HBase服务器是否可拜访的状态提供服务器故障/宕机的告诉同时还应用一致性算法来保障服务器之间的同步。同时也负责Master选举的工作。须要留神的是要保障良好的一致性及顺利的Master选举,集群中的服务器数目必须是奇数,例如三台或五台。三、HBase的表构造 每一行有一个RowKey用于惟一地标识和定位行,各行数据按RowKey的字典序排列。其中ImployeeBasicInfoCLF和DetailInfoCLF是两个列族,列族下又有多个具体列。(员工根本信息列族:姓名、年龄。详细信息列族:薪水、角色)。 HBase数据模型 命名空间:命名空间是对表的逻辑分组,不同的命名空间相似于关系型数据库中的不同的Database数据库。利用命名空间,在多租户场景下可做到更好的资源和数据隔离。表:对应于关系型数据库中的一张张表,HBase以“表”为单位组织数据,表由多行组成。行:由一个RowKey和多个列族组成,一个行有一个RowKey,用来惟一标示。列族:每一行由若干列族组成,每个列族下可蕴含多个列,如上ImployeeBasicInfoCLF和DetailInfoCLF即是两个列族。列族是列共性的一些体现。留神:物理上,同一列族的数据存储在一起的。列限定符:列由列族和列限定符惟一指定,像如上的name、age即是ImployeeBasicInfoCLF列族的列限定符。单元格:单元格由RowKey、列族、列限定符惟一定位,单元格之中寄存一个值(Value)和一个版本号。工夫戳:单元格内不同版本的值按工夫倒序排列,最新的数据排在最后面

August 2, 2021 · 1 min · jiezi

关于hbase:Hbase写数据存数据读数据的详细过程

HBase架构 Region-Store-ColumnFmily的关系逻辑分层:<font color=red>HRegion由一个或者多个Store组成</font>Table (HBase table) Region (Regions for the table) Store (Store per ColumnFamily for each Region for the table) MemStore (MemStore for each Store for each Region for the table) StoreFile (StoreFiles for each Store for each Region for the table) Block (Blocks within a StoreFile within a Store for each Region for the table)物理分层: <font color=red>每个store保留一个columns family</font> 一、写操作1、Client 写入 -> 存入 MemStore ,始终到MemStore满 -> Flush 成一个 StoreFile ...

July 30, 2021 · 2 min · jiezi

关于hbase:feeds流系统设计方案

前言feeds流在互联网零碎中利用的十分宽泛,能够说是咱们每天都要用到的,比方微信朋友圈、知乎、抖音微博等,动静以瀑布流的模式出现,凡是带点社交性能,都会有feeds模块,这些feeds来源于用户的好友或者关注用户,形成咱们的虚构社交广场. 难点用户量小,qps低的时候,怎么设计都能够,然而当用户上百万、千万级,如何保障以下几点: 存储怎么选,用户关系和feeds又怎么存?如何提供可能稳固扛住上百万级qps流量的服务?如何保障时延稳固在不影响用户体验的范畴内?读扩散和写扩散某个用户公布了一条feed,如果扩散到好友的社交圈中,比方在朋友圈中,A发了一条朋友圈,如何让B看到,常见的扩散形式包含两种.这里以朋友圈为例,用户A有一百个微信好友; 读扩散:记录A与100个好友之间的好友关系,每次刷新朋友圈时,先去找到这一百个好友,而后拉取这一百个好友的动静,依照工夫排序展现在朋友圈中;写扩散:为A保护一个收件箱,A的好友每次公布动静时,都往这个收件箱中发送一条记录,A每次刷新朋友圈时,只须要从收件箱中拉取记录即可;特色:tobecontinue

July 24, 2021 · 1 min · jiezi

关于hbase:hbase运维故障案例分析

在理论运维HBase集群时,各位小伙伴总会遇到RegionServer异样宕机、业务写入提早增大甚至无奈写入等相似问题。本章联合笔者的教训、列举实在生产线环境常见的几个问题,并介绍这些地问题的根本排查思路。同时,重点对HBase零碎中的日志进行梳理介绍,最初对如何通过监控、日志等工具进行问题排查进行总结,造成问题排查套路,不便读者进行实际。 regionserver宕机案例一: 长时间GC导致Regionserver宕机长时间FullGC是RegionServer宕机最常见的起因.剖析这类问题,能够遵循如下排错过程: 景象:收到Regionserver过程退出的报警。 1. 宕机起因定位步骤1: 通常在监控上看不出,须要到事发的RegionServer日志间接搜寻2类关键字---a long garbage collecting pause 或ABORTING region server。对于长时间Full GC的场景,搜寻第一个关键字会检索到:      2019-06-14T17:22:02.054 WARN [JvmPauseMonitor] util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 20542ms     GC pool 'ParNew' had collection(s): count=1 time=0ms     GC pool 'ConcurrentMarkSweep' had collection(s): count=2 time=20898ms     2019-06-14T WARN [regionserver60020.periodicFlusher] util.Sleeper: We slept 20936ms instead of 100ms, this is likely due to a long garbage collecting pause and it's usually bad, see http://hbase.apache.org/book.html#trouble.rs.runtime.zkexpired步骤2: 通常CMS GC策略会在2种场景下产生重大的Full GC ,1. Concurrent Mode Failure 2. Promotion Failure。 ...

July 22, 2021 · 2 min · jiezi

关于hbase:HBase-Meta表结构组成

一、HBase Meta表hbase:metab表寄存着整个集群的所有Region信息,客户端数据的读写须要定位到具体须要操作的Region,说白了就是一张字典表。meta表只会有一个Region,这是为了确保meta表屡次操作的原子性。二、Meta表构造与内容scan 'hbase:meta'ROW COLUMN+CELLhbase:namespace column=table:state, timestamp=1625022648593, value=\x08\x00hbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06. column=info:regioninfo, timestamp=1625037742467, value={ENCODED => 882bc9caea6a5cee511a1525d7801f06, NAME => 'hbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06.', STARTKEY => '', ENDKEY => ''}hbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06. column=info:seqnumDuringOpen, timestamp=1625037742467, value=\x00\x00\x00\x00\x00\x00\x00\x0Ahbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06. column=info:server, timestamp=1625037742467, value=10.2.31.104:16020hbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06. column=info:serverstartcode, timestamp=1625037742467, value=1625037620770hbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06. column=info:sn, timestamp=1625037742238, value=10.2.31.104,16020,1625037620770hbase:namespace,,1625022647862.882bc9caea6a5cee511a1525d7801f06. column=info:state, timestamp=1625037742467, value=OPEN search_table column=table:state, timestamp=1625037955888, value=\x08\x00search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c. column=info:regioninfo, timestamp=1625037955882, value={ENCODED => f507364ab62a42cfe702c6b3dea8757c, NAME => 'search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c.', STARTKEY => '', ENDKEY => ''}search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c. column=info:seqnumDuringOpen, timestamp=1625037955882, value=\x00\x00\x00\x00\x00\x00\x00\x02search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c. column=info:server, timestamp=1625037955882, value=10.2.31.104:16020search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c. column=info:serverstartcode, timestamp=1625037955882, value=1625037620770search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c. column=info:sn, timestamp=1625037955648, value=10.2.31.104,16020,1625037620770search_table,,1625037955174.f507364ab62a42cfe702c6b3dea8757c. column=info:state, timestamp=1625037955882, value=OPEN三、Meta表组成阐明3.1 Rowkey组成meta表中的一个Rowkey就代表了一个region。Rowkey次要由以下几局部组成:3.1.1.TableName(业务表名)3.1.2.StartRow(业务表Region区间的起始rowkey)3.1.3.Timestamp(Region创立的工夫戳)3.1.4.EncodedName(下面3个字段的MD5 Hex值)4个字段拼接而成 ...

June 30, 2021 · 1 min · jiezi

关于hbase:HBase2110源码导入Idea本地调试

一、环境筹备环境筹备1. Jdk 112. maven 3.6.33. Idea 2020.14. Git 2.24.35. Mac OS二.克隆源码到本地目录git clone https://github.com/apache/hbase三.应用Idea导入我的项目并配置jdk 3.1 切换须要编译的分支,此处我抉择的是2.1.103.2 导入到idea后的jdk版本须要做调整,让每一个模块都加载jdk11 3.3 批改根目录下的pom.xml,批改jdk版本、批改maven插件版本、跳过license 检测<properties> <compileSource>11</compileSource> <maven.compiler.version>3.8.1</maven.compiler.version></properties><plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.version}</version> <configuration> <source>${compileSource}</source> <target>${compileSource}</target> <showWarnings>true</showWarnings> <showDeprecation>false</showDeprecation> <useIncrementalCompilation>false</useIncrementalCompilation> <!-- <compilerArgument>-Xlint:-options</compilerArgument> --> <compilerArgs> <arg>--add-exports=java.base/jdk.internal.access=ALL-UNNAMED</arg> <arg>--add-exports=java.base/jdk.internal=ALL-UNNAMED</arg> <arg>--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED</arg> <arg>--add-exports=java.base/sun.security.pkcs=ALL-UNNAMED</arg> <arg>--add-exports=java.base/sun.nio.ch=ALL-UNNAMED</arg> </compilerArgs> </configuration> </plugin><!-- 跳过license查看 --><execution> <id>check-aggregate-license</id> <!-- must check after LICENSE is built at 'generate-resources' --> <phase>process-resources</phase> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <evaluateBeanshell> <condition> File license = new File("${license.aggregate.path}"); // Beanshell does not support try-with-resources, // so we must close this scanner manually Scanner scanner = new Scanner(license); while (scanner.hasNextLine()) { if (scanner.nextLine().startsWith("ERROR:")) { scanner.close(); return false; } } scanner.close(); return true; </condition> <message> License errors detected, for more detail find ERROR in ${license.aggregate.path} </message> </evaluateBeanshell> </rules> <!--<skip>${skip.license.check}</skip>--> <skip>true</skip> </configuration></execution>批改后: ...

June 30, 2021 · 2 min · jiezi

关于hbase:hbase-入门

一、参考elasticsearch 学习系列目录——更新ing hbase quick start 二、hbase装置2.1 下载下载hbase tar xzvf hbase-2.4.4-bin.tar.gz2.2 运行HMaster 2.3 运行hbase shell(1)报错 可能起因是java版本太高,重新安装配置JAVA_HOMEbrew install openjdk@8export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/ (2)运行hbase shell

June 16, 2021 · 1 min · jiezi

关于hbase:华为云PB级数据库GaussDBfor-Redis揭秘第九期与HBase的对比

摘要: 高斯Redis,兼具开源Redis和HBase各自长处,提供老本更低、性能更好、灵活性更强的数据库服务!本文分享自华为云社区《华为云PB级数据库GaussDB(for Redis)揭秘第九期:与HBase的比照》,原文作者:高斯Redis官网博客。 0. 引言HBase是一个分布式的、面向列的开源数据库,基于Hadoop生态圈,在NoSQL蓬勃发展的明天被国内外泛滥公司抉择,利用于古代互联网零碎的不同业务。本文简要形容了HBase的根本架构和应用场景,重点剖析了HBase要害个性在此场景下的体现,以及HBase在应用上尚存的痛点;同时介绍了华为自研的强统一、长久化 NoSQL数据库GaussDB(for Redis)(下文简称高斯Redis)在以上场景中的体现,以及对于HBase痛点问题的改善。 1. HBase零碎简述HBase的物理构造次要包含ZooKeeper、 HMaster、 RegionServer、HDFS 等组件。 ZooKeeper 用以实现 HMaster 的高可用、 RegionServer 的监控、元数据的入口以及集群配置的保护等工作。HMaster的作用是保护整个集群的Region信息,解决元数据变更及负载平衡工作。RegionServer是间接解决用户读写申请的节点,理论解决所调配Region的读写、决裂等工作,并应用WAL实现容错机制。HDFS提供最终的底层数据存储服务,提供元数据和表数据的底层分布式存储服务,同时利用数据多正本,保障的高牢靠和高可用性。 在逻辑构造中,RowKey是表的主键,并依照字典序进行排列,HRegion 达到肯定大小后也会依照 RowKey 范畴进行裂变。ColumnFamily在纵向上对表进行切分,将多个Column分成一组进行治理,在HBase中,ColumnFamily是表的schema而Column不是。Cell则是保留的具体value,在HBase中,所有的数据都是以字节码的形式进行存储。 2.HBase大显神通2.1标签数据的存储标签数据是稠密矩阵的代表,形容了实体的各类属性,次要利用于智能举荐、商务智能或营销引擎等畛域。 三个不同的用户在同一公司旗下的不同APP中留下了大量的行为数据,这些数据中蕴含了间接填写的用户材料、应用APP的具体行为以及领域专家对某些景象的标记,通过后盾的标签算法能够失去这样的数据: 咱们能发现,对用户行为采集存在局限性,因而所能失去的标签品种各不相同,表中大量的数据项只能被置空,也就是所谓的稠密矩阵。而且随着用户更深度的应用APP,能够预见到,对用户感兴趣畛域/不感兴趣畛域会逐步被挖掘,那么表的列也会随之减少。 这样的特点对于MySQL是灾难性的,这是因为在MySQL建表时就必须定义表构造,属性的动静增删是微小的工作量,同时大量NULL值的存储会导致存储老本变得难以承受。然而应用HBase存储时,未指定value的列不会占用任何的存储空间,因此能够将无限的资源高效利用,且HBase表在创立时只需指定ColumnFamily,而对于Column的增删极为容易,有利于应答将来属性的扩张。 2.2 车联网数据的收集车联网零碎是利用车载设施收集车辆运行时产生的各项数据,通过网络实时上传,在平台进行动态分析和利用。 咱们能够发现,车联网零碎所面对的数据特点是大量车辆终端高并发的不间断写入TB级甚至PB级的数据,而且对于实时剖析来说,为了保障剖析后果的时效性,又要求查问的低时延响应。 HBase采纳LSM存储模型,能够从容应对高并发写入的场景,同时也能保障读时延在可承受的范畴内。同时HBase具备良好的程度扩大能力。通过增减RegionServer来实现对存储容量动静调整,满足对应用老本的要求。 2.3 交易记录的保留在挪动领取畛域,保障历史交易记录等敏感信息的安全性是一个重要的话题。当数据中心遭逢自然灾害、内部攻打时,必须保障这些信息不丢,而且从业务角度要保障RTO尽可能短、RPO尽可能为0。 HBase基于底层的HDFS作为存储系统,HDFS实现了三正本策略,依照肯定的规定将正本放在不同的节点或机架中,自身具备较高的容灾能力。在工程实际中,也产生了Region replica、主备集群、互备双活等策略来尽可能进行灾备并保障高可用。 3.HBase并不全能从上文三个例子能够看出,HBase基于其自身的设计,在稠密矩阵的存储、抗高并发大流量写入、高可用和高牢靠场景下体现得相当优良,但这并不意味着HBase能够没有任何弱点的适应所有场景。 3.1HBase的阿克琉斯之踵1. 朱丽叶暂停 Java零碎绕不开Full GC的探讨。HBase在Full GC造成STW时,ZooKeeper将收不到来自RegionServer的心跳,进而将此节点断定为宕机,由其余节点接管数据,当Full GC完结后,RegionServer为避免脑裂而被动他杀,称之为朱丽叶暂停。这类问题个别须要资深的java程序员依据业务场景进行粗疏的GC策略调优能力尽可能防止。 2. 数据类型少 HBase反对存储的类型是字节数组,在应用中须要将字符串、简单对象、甚至图像等数据转化为字节数组进行存储。然而这样的存储只能示意涣散的数据关系,对于汇合、队列、Map等数据结构或数据关系,则须要开发人员编码实现转换逻辑能力进行存储,灵活性较差。 3. 性能之瓶颈 HBase是依照RowKey的字典序宰割为Region进行存储的,不佳的RowKey设计方案会造成负载不均,申请大量打到某一个Region造成热点,那么所在RegionServer的IO有可能被打爆。 RegionServer掉线后,须要由ZooKeeper发现节点宕机,将其负责的数据挪动到其余节点接管,并对meta表中的Region信息进行批改。在此过程中,RegionServer上的数据将变得不可用,对于这部分数据的申请会被阻塞。 3.2 Redis的伊卡洛斯之翼3.2.1 开源Redis的良好体现开源Redis的个性在肯定水平上解决了HBase的痛点问题,因其具备以下长处: 1. 更丰盛的数据类型 Redis 5.0协定中蕴含了String、List、Set、ZSet、Hash、Bit Array、HyperLogLog、Geospatial Index、Streams九种数据类型,以及建设在这些数据类型上的相干操作。与HBase的繁多数据类型相比,Redis给了开发人员更多的抉择空间来表白数据和数据间的互相关系。 2. 纯内存的丝滑感触 开源Redis的实质是一个key-value类型的内存数据库,整个数据库都加载在内存中进行操作。这也就意味着Redis的响应速度和解决能力远超过须要进行磁盘IO的HBase,目前大量的测试后果都表明,开源Redis的性能能够达到每秒10万次读写。 3.2.2 开源Redis的显著弱点纯内存的操作也使得开源Redis有无奈防止的弱点,次要体现在以下两方面: 1. 大数据量下的噩梦 当数据量继续增大时,无限的内存成为应用限度。此时必须应用更大容量的内存能力实现数据的全量加载,而内存价格远高于磁盘价格,会导致应用老本的激增。同时常见的服务器内存多是GB级,也重大限度了开源Redis在高量级数据库畛域的竞争力。 2. 断电后该何去何从 纯内存操作的另一弊病是宕机后数据会全副失落。现有的解决方案是应用AOF或RDB的形式将数据长久化,过程重启后能够在内存中将数据恢复。但这两种形式并不齐备,AOF是执行命令的汇合,因而复原速度绝对较慢;RDB是定期dump内存数据,因而存在数据失落的危险。除此之外,在最坏场景下须要预留一半内存,升高了内存的使用率。 4.高斯Redis:成年人不做选择题HBase和开源Redis各有千秋,这时一句相熟的话在脑海中浮现:小孩子才做选择题,成年人当然是全都要,高斯Redis的兼具二者长处,更好的满足了对数据库服务的需要。 ...

May 11, 2021 · 1 min · jiezi

关于hbase:HBase行级事务锁

写写并发管制: 只须要在写入(或更新)之前先获取行锁,如果获取不到,阐明曾经有其余线程拿了该锁,就须要一直重试期待或者自旋期待,直至其余线程开释该锁。拿到锁之后开始写入数据,写入实现之后开释行锁即可。这种行锁机制是实现写写并发管制最罕用的伎俩,前面能够看到MySQL也是应用行锁来实现写写并发的。批量写入多行的写写并发: HBase反对批量写入(或批量更新),即一个线程同时更新同一个Region中的多行记录。那如何保障以后事务中的批量写入与其余事务中的批量写入的并发管制呢?思路还是一样的,应用行锁。但这里须要留神的是必须应用两阶段锁协定,即:(1) 获取所有待写入(更新)行记录的行锁(2) 开始执行写入(更新)操作(3) 写入实现之后再对立开释所有行记录的行锁不能更新一行锁定(开释)一行,多个事务之间容易造成死锁。两阶段锁协定就是为了防止死锁,MySQL事务写写并发管制同样应用两阶段锁协定。Rowkey info:company info:rolegreg cloudera engineer Rowkey info:company info:rolegreg restaurant waiter 两个并发写入申请同时进来,别离对一行数据进行写入。若没有并发管制,会呈现穿插状况。 Rowkey info:company info:rolegreg restaurant engineer 读写并发管制:事务A实现。Rowkey info:company info:rolegreg cloudera engineer 开始执行事务BRowkey info:company greg restaurant 此时来了读申请,info:role还未更新实现。 info:role waiter 读取到的数据为:Rowkey info:company info:rolegreg restaurant engineer 呈现数据不统一的状况。 多版本并发管制(MVCC机制-Mutil Version Concurrent Control): 两个写事务别离调配了序列号1和序列号2,读申请进来的时候事务1曾经实现,事务2还未实现,因而调配事务1对应的序列号1给读申请。此时序列号1对本次读可见,序列号2对本次读不可见。 +---+---+---+---+---+---+---+---+---+----+----+----+----+ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | +---+---+---+---+---+---+---+---+---+----+----+----+----+ 所有事务都会生成一个region级别的自增序列。 ...

November 9, 2020 · 1 min · jiezi

关于hbase:HBase宕机恢复

1.HBase常见故障导致RegionServer故障的起因: 1、FullGc引起长时间进展 2、HBase对Jvm堆内存治理不善,未正当应用堆外内存 3、Jvm启动参数配置不合理 4、业务写入或吞吐量太大 5、写入读取字段太大 HDFS异样: 读取写入数据都是间接操作hdfs的,若hdfs产生异样,会导致region server间接宕机 机器宕机: 1、物理节点间接宕机 2、虚构云主机不稳固,包含网络环境等 HBase Bug2.HBase故障复原Master复原: 1、Master次要负责实现集群的负载平衡和读写调度,没有直接参与用户的申请,所以整体负载并不高 2、热备形式实现Master高可用,zookeeper上进行注册 3、active master会接管整个零碎的元数据管理工作,zk以及meta表中的元数据,相应用户的治理指令,创立、删除、批改,merge region等regionServer复原: 1、RegionServer宕机,HBase会检测到 2、Master将宕机RegionServer上所有region重新分配到集群中其它失常的RegionServer上 3、依据HLog进行失落数据恢复,复原之后对外提供服务大略流程: 1、master通过zk实现对RegionServer的宕机检测。RegionServer会周期性的向zk发送心跳,超过肯定工夫,zk会认为RegionServer离线,发送音讯给master 2、切分为长久化的日志,所有region的数据都混合存储在同一个hlog文件里,为了使这些数据可能依照region进行组织回放,须要将hlog日志进行切分再合并, 同一个region的数据合并在一起,不便后续依照region进行数据恢复。 3、master重新分配宕机regionserver上的所有region,regionserver宕机后,所有region处于不可用状态,所有路由到这些region上的申请都会返回异样。 异常情况比拟短暂,master会将这些region调配到其它regionserver上。 4、回放HLog日志补救数据 5、复原实现,对外提供读写服务具体流程: 1、master检测regionserver宕机 regionserver启动后会在zk的 /rs节点上注册一个长期子节点,超时后长期节点会主动隐没,并告诉watch在该长期节点上的其它客户端。 master会watch在/rs节点上,子节点一旦离线会告诉master。 长时间的FullGc也会使得心跳进行。zookeeper.session.timeout,默认180s。对提早要求高,参数设短。迅速检测到异样,离线集群设置长。 2、切分未长久化数据的HLog 对HLog中的region进行分组,每个region的数据合并放在一起,不便后续依照region进行回放,这个分组过程称为HLog切分。 2.1、LogSplitting策略: 某台regionserver宕机,/hbase/WALs/bj-hadoop01,123456,789456 为HLog存储在hdfs上的门路。 日志切分就是将这个目录下所有HLog文件的所有kv依照region进行分组。 2.1.1、将/hbase/WALs/bj-hadoop01,123456,789456 重命名为 /hbase/WALs/bj-hadoop01,123456,789456-splitting 因为某些场景region server并没有真正宕机,region server与zk网络异样,与外网之间的网络失常,用户并不知道 region server宕机,写入更细操作还会持续发送到该region server上。该region server还能持续工作,接管用户 申请,不重命名日志文件夹,回放生master曾经在应用hlog进行故障复原了,但region server还在一直的写入hlog,数据不统一。 重命名后用户的写申请会异样终止,不会呈现数据不统一的状况。 客户端失落数据 2.1.2、启动读线程一次读取每个HLog中的数据,写入不同的buffer中,每个buffer对应一个region 2.1.3、切分实现后写成文件。 该办法效率差,切分过程只有master参加,集群宕机,须要复原大量数据,可能有几百G,master单机切分可能须要几小时。 切分过程中一旦出现异常会导致整个集群故障复原不能失常实现。 2.2、Distributed Log Splitting: master和所有region server的计算能力进行日志切分,master是协调者,region server是理论工作者。 2.2.1、不同region server抢不同的hlog,抢到后发给hlogsplitter线程进行解决,对日志执行具体切分。将数据进行region归类。 2.2.2、将buffer中的数据写入文件,对数据进行回放。 Distributed Log Splitting 放慢故障复原过程,能够将故障复原工夫降到分钟级别。但会产生很多小文件。 小文件数: M * N, M:待切分的总Hlog数量 N:一个宕机region server上的region个数 一台region server上200个region,90个hlog。宕机后复原过程会创立18000个小文件。若多个region server宕机,小文件会更多。 2.3、Distributed Log Replay: 在2.2的根底上不进行文件的写入,而是读取出数据后间接进行回放,大大减少小文件的读写IO耗费。3.故障耗费工夫优化HBase故障复原流程: ...

October 21, 2020 · 1 min · jiezi

关于hbase:PhoenixHbase二级索引

应用的软件版本,留神软件版本很重要,很重要apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz hadoop-2.9.2.tar.gz hbase-2.0.5-bin.tar.gz Hbase中通过非rowkey查问数据查问速度会很慢为什么须要二级索引在Hbase中要想准确查问一条数据所以必须应用rowkey,如果不通过rowkey查问数据,就必须逐行逐列的比拟(即全表扫描),效率很低. 理论业务中须要通过多个维度疾速查问数据. 例如查问用户的时候可能须要通过用户名,姓名,邮箱,手机号查问,然而把这种多维度的查问字段都放到rowkey中,显然是不可能的(灵活性不高,roekey的长度也是有限度的),因而二级索引的利用场景就应运而生,Phoenix曾经提供了对HBase的二级索引反对反对。二级索引分类Global indexing 全局索引,实用于读多写少的场景应用Global indexing在写数据的时候开销很大,因为所有对数据表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),都会引起索引表的更新,而索引表是散布在不同的数据节点上的,跨节点的数据传输带来了较大的性能耗费。在读数据的时候Phoenix会抉择索引表来升高查问耗费的工夫。在默认状况下如果想查问的字段不是索引字段的话索引表不会被应用,也就是说不会带来查问速度的晋升。Local indexing 本地索引,实用于写多的场景与Global indexing一样,Phoenix会主动断定在进行查问的时候是否应用索引。应用Local indexing时,索引数据和数据表的数据寄存在雷同的服务器中,这样防止了在写操作的时候往不同服务器的索引表中写索引带来的额定开销。应用Local indexing的时候即便查问的字段不是索引字段索引表也会被应用,这会带来查问速度的晋升,这点跟Global indexing不同。对于Local Indexing,一个数据表的所有索引数据都存储在一个繁多的独立的可共享的表中。immutable indexing 不可变索引,实用于数据只减少不更新,而且按工夫程序先后循序存储.不可变索引的存储形式是write one,append only。当在Phoenix应用create table语句时指定IMMUTABLE_ROWS = true示意该表上创立的索引将被设置为不可变索引。Phoenix默认状况下如果在create table时不指定IMMUTABLE_ROW = true时,示意该表为mutable。不可变索引分为Global immutable index和Local immutable index两种。mutable indexing 可变索引,实用于数据有增删的的场景Phoenix默认状况下创立的索引是可变索引,除非指定 IMMUTABLE_ROW=true开启Hbase对二级索引的反对vim vim hbase-2.3.1/conf/hbase-site.xml <property> <name>hbase.regionserver.wal.codec</name> <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value></property>user表创立索引>create table user1( id varchar(10) primary key, f.name varchar(100), f.pass varchar(100), f.grp varchar(10), f.type varchar(5), f.types varchar(2), f.code varchar(10), f.uname varchar(20), f.email varchar(20), f.factory varchar(10), f.depart varchar(10), f.region varchar(10))column_encoded_bytes=0;> create index user_name on user(name);//查问索引> !indexes useruser表删除索引> drop index user_name on user;实战create index user_name on user; //默认可变索引//创立索引> create index user_name on user;//*这样查问是不会走索引的> select * from user where name='rumenz';> explain select * from user where name='rumenz'; //FULL SCAN OVER USER SERVER FILTER BY F.NAME =//查问字段和索引字段保持一致就能够用到索引> select name from user where name='rumenz';> explain select name from user where name='rumenz';//CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER USER_NAME SERVER FILTER BY FIRST KEY ONLY create local index user_name on user1(name); //创立本地索引//*这样查问就会走索引> select * from user where name='rumenz';> explain select * from user where name='rumenz'; //应用到了索引//ROUND ROBIN RANGE SCAN OVER USER1converted index //相当于一个联结索引> create index user_name1 on user1(name) include(pass);//只有当name,pass在查问字段呈现时,才会用到索引:比方//select name from user1 where name=''或者 pass='';//select pass from user1 where name=''或者 pass='';//select name,pass from user1 where name=''或者 pass='';在select和column_name之间加上/*+ Index(<表名> <index名>)*/,通过这种形式强制应用索引。> select /*+ index(user1,USER_NAME) */ pass from user1 where name='xxx';//1.如果pass是索引那么从索引表查问.//2.如果pass不是索引,那么会进行全表扫描会很慢.重建索引> alter index USER_NAME on user1 rebuild;索引性能调优1. index.builder.threads.max 创立索引时,应用的最大线程数。 默认值: 10。2. index.builder.threads.keepalivetime 创立索引的创立线程池中线程的存活工夫,单位:秒。 默认值: 603. index.writer.threads.max 写索引表数据的写线程池的最大线程数。 更新索引表能够用的最大线程数,也就是同时能够更新多少张索引表,数量最好和索引表的数量统一。 默认值: 104. index.writer.threads.keepalivetime 索引写线程池中,线程的存活工夫,单位:秒。默认值:60 5. hbase.htable.threads.max 每一张索引表可用于写的线程数。 默认值: 2,147,483,6476. hbase.htable.threads.keepalivetime 索引表线程池中线程的存活工夫,单位:秒。 默认值: 607. index.tablefactory.cache.size 容许缓存的索引表的数量。 减少此值,能够在写索引表时不必每次都去反复的创立htable,这个值越大,内存耗费越多。 默认值: 108. org.apache.phoenix.regionserver.index.handler.count 解决全局索引写申请时,能够应用的线程数。 默认值: 30 ...

September 22, 2020 · 2 min · jiezi

关于hbase:HbasePhoenix使用总结

1.Hbase中表名和列族名是大小写敏感的 如果应用小写的表名那么必须加上双引号。表名和列族名是大写则不须要双引号2.Phoenix查问客户端超时Error: Operation timed out. (state=TIM01,code=6000)java.sql.SQLTimeoutException: Operation timed out.解决方案:批改apache-phoenix-5.0.0-HBase-2.0-bin/bin/hbase-site.xml,减少以下配置 <property> <name>phoenix.query.timeoutMs</name> <value>3600000</value> </property><property> <name>hbase.rpc.timeout</name> <value>3600000</value></property>3.Phoenix二级索引表与源数据表放弃同步的前提 数据源表的增删改查必须通过Phoenix命令行或者客户端能力保障二级索引表与源表同步。Phoenix提供的Bulk Loading同样也能保障二级索引表与源数据表放弃同步。4.Phoenix Bulk Loading的应用 应用Loading via PSQL来导入大批量数据,要留神Loading via PSQL的文件必须是.csv后缀,不然程序无奈辨认到数据文件。5.Phoenix表的治理保护 通过Phoenix创立的表,必须指定primary key(对应Hbase的rowkey),列最好指定列族名称,列类型最好指定为varchar如果应用了Phoenix操作Hbase,删除表的话肯定要应用Phoenix的api操作,如果间接用Hbase的api操作会导致Phoenix能够看见表然而操作表会报错. 通过Phoenix的api删除表同时也会删除可能存在的二级索引。

September 20, 2020 · 1 min · jiezi

关于hbase:HbasePhoenixMybatisSpringboot整合查询数据

Phoenix Query Server提供了一种与Phoenix和HBase交互的代替办法。很快,这将容许从JVM以外的环境进行拜访。在4.x和5.0版本中,查问服务器及其JDBC客户端是规范Phoenix发行版的一部分。它们不须要其余依赖项。在5.0版本之后,查问服务器已被捆绑到phoenix-queryserver存储库中,并且其版本号已重置为1.0。在撰写本文时,没有独立查问服务器的发行版本。因为咱们装置的是apache-phoenix-5.0.0-HBase-2.0,所以外面内置了queryserver1.启动queryserver,默认监听8765 > apache-phoenix-5.0.0-HBase-2.0-bin/bin/queryserver.py2.自定义配置 vim hbase-site.xml 属性形容默认phoenix.queryserver.http.port指定服务器将侦听的端口。默认值为8765。8765phoenix.queryserver.metafactory.class要实例化的Avatica Meta.Factory类。org.apache.phoenix.queryserver.server.PhoenixMetaFactoryImplphoenix.queryserver.serialization传输/序列化格局,PROTOBUF或JSON。PROTOBUF//将默认的8765端口改成8888<property> <name>phoenix\.queryserver\.http\.port</name> <value>8888</value></property>3.pom.xml中引入Phoenix客户端 //轻量级客户端<dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-queryserver-client</artifactId> <version>5.0.0-HBase-2.0</version></dependency>4.残缺的pom.xml <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rumenz</groupId> <artifactId>phoenix</artifactId> <version>0.0.1-SNAPSHOT</version> <name>phoenix</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.3.0.RELEASE</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-queryserver-client</artifactId> <version>5.0.0-HBase-2.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.21</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.3.0.RELEASE</version> <configuration> <mainClass>com.rumenz.phoenix.PhoenixApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build></project>5.数据源配置 ...

September 19, 2020 · 2 min · jiezi

关于hbase:HBaseCompaction

HBase Compaction1.Compaction作用合并小文件,缩小文件数,稳固随机读提早进步数据的本地化率革除有效数据,缩小数据存储量HFile越多,查问须要的IO操作也会变多,读提早越来越大。Compaction稳固HFile文件个数,缩小IO操作。本地化率越高,hdfs上拜访数据时提早就越小,本地化率低,拜访数据就须要通过网络拜访,提早必然增大,Compaction后会将大文件在以后DataNode上保留一个正本,进步本地化率。Major Compaction能够将以后region的本地化率进步到100% Compaction的副作用 带宽压力和短时间的IO压力,小文件读取须要IO,传输须要带宽。读取后写新的文件须要有3个正本2.Compaction组成从一个Region上的一个Store中选取局部HFile文件进行合并,从这些待合并的文件中一次读取出KeyValue,再由小到大排序后写入一个新的文件,由这个新的文件对外提供服务Minor Compaction 选取局部小的、相邻的HFile合并成一个HFile,造成一个更大的HFile(TTL过期数据也会被清理)Major Compaction 将一个Store中所有HFile合并成一个HFile,会清理被删除的数据、TTL过期数据、版本号超过设定版本号的数据Major Compaction持续时间较长,耗费大量系统资源,影响大生产举荐敞开主动触发的Major Compaction,在业务低峰期手动触发3.Compaction根本流程先实现flush操作(后续补充)、周期性的Compaction查看操作都会触发Compaction抉择适合的HFile合并筛选适合的线程池执行HFile文件合并Compaction由独立的线程解决,该线程会从对应的store中抉择适合的HFile进行合并,选文件有许多条件。现实状况是选取那些IO负载中、文件小的文件集4.Compaction触发机会MemStore Flush MemStore Flush产生HFile文件,数据一直写入,就会有更多的HFile文件产生,每次flush完后都会对以后store中的hfile数量进行判断一旦总文件数大于 hbase.hstore.compactionThreshold,就会触发compaction compaction都是以store为单位,flush触发条件下,整个region的store都会执行compact操作 一个region可能在短时间内执行屡次compaction(这是十分不好的景象) 后盾线程定期检查 默认7天左右一次major compaction,敞开需将参数 hbase.hregion.majorcompection=0手动触发 防止major compaction影响业务的读写性能或是硬盘容量不够。低峰期手动执行major compaction(咱们的业务就是采纳的这种形式)5.HFile汇合选取策略排除正在Compaction的文件以及比这些文件更新的文件排除某些过大的文件,大文件会产生大量IO通过1 2 留下来的文件就是Compaction的候选文件判断是否满足major compaction的条件,只有满足一下任意一条就会执行major compaction,对全副文件进行合并 用户强制执行major compaction长时间没有进行major compaction且候选文件数小于10长时间 = 上次执行major compaction的工夫早于以后工夫-hbase.hregion.majorcompection Store中含有reference文件,reference是region决裂产生的临时文件,在compaction过程中必须清理若满以上任意一条件,文件抉择就完结了,间接合并。若不满足,则为minor compaction。 minor compaction的文件选取策略: RatioBasedCompactionPolicy(从老到新选取文件)ExploringCompactionPolicy(选取到适合的文件后就进行选取,缩小IO操作)6.筛选适合的线程池CompactSplitThread类负责接管compaction申请和split申请。 不同线程池如下: largeCompations 解决大compaction smallCompations 解决下小compaction splits 解决所有split申请将申请独立解决,进步零碎解决性能。依据阈值来决定是否为大或小compaction 7.HFile文件合并执行选出了待合并的HFile和适合的解决线程,执行合并流程读取待合并HFile的keyValue,进行归并排序,写到./tmp目录下的临时文件中将临时文件挪动到对应的store目录中将Compaction的输出文件门路和输入文件封装为kv写入hlog日志中,打上compaction标记,强制执行sync将对应Store数据目录下的Compaction输出文件全副删除至此实现了一次Compaction操作

September 18, 2020 · 1 min · jiezi

关于hbase:HBase内置过滤器java-api的总结

1、RowFilter:筛选出匹配的所有的行(应用过) //rowkey 等于 test|id9Filter filter=new RowFilter(CompareOperator.EQUAL,new BinaryComparator(Bytes.toBytes("test|id9")));2、PrefixFilter:筛选出具备特定前缀的行健的数据 //rowkey 以test结尾Filter filter=new PrefixFilter(Bytes.toBytes("test"));3、KeyOnlyFilter:只返回每行的行健 //只返回每行的行键,但值全是空Filter filter=new KeyOnlyFilter();4、RandomRowFilter:依照肯定的几率来返回随机的后果集 //返回随机的数据Filter filter=new RandomRowFilter(0.5f);5、InclusiveStopFilter:扫描的时候,咱们能够设置一个开始行键和一个终止行键,默认状况下,这个行键的返回是前闭后开区间,即蕴含起始行,但不蕴含终止行,如果咱们想要同时蕴含起始行和终止行 //遇到rowkey等于test|id4进行查问Filter filter=new InclusiveStopFilter(Bytes.toBytes("test|id4"));6、FirsterKeyOnlyFilter:返回的后果集中只蕴含第一列的数据它在找到每行的第一列之后会进行扫描 //筛选出第一个每个第一个单元格Filter filter=new FirstKeyOnlyFilter();7、ColumnsPrefixFilter:依照列名的前缀来筛选单元格,如果咱们想要对返回的列的前缀加以限度的话,能够应用这个过滤器 //列名以ss结尾Filter filter=new ColumnPrefixFilter(Bytes.toBytes("ss"));8、ValueFilter:依照具体的值来筛选单元格 //值中蕴含one的记录Filter filter=new ValueFilter(CompareOperator.EQUAL,new SubstringComparator("one"));9、ColumnsCountGetFilter:这个过滤器来返回每行最多返回多少列,并在遇到一行的列数超过咱们所设置的限度值的时候,完结扫描操作 Filter ccf=new ColumnCountGetFilter(2);//OK如果忽然发现一行中的列数超过设定的最大值时,整个扫描操作会进行10、SingleColumnValueFilter:用一列的值决定这一行的数据是否被过滤 SingleColumnValueFilter scvf=new SingleColumnValueFilter(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),CompareFilter.CompareOp.NOT_EQUAL,new SubstringComparator("BOGUS"));scvf.setFilterIfMissing(false);scvf.setLatestVersionOnly(true);//OK11、SingColumnValueExcludeFilter:这个与10种的过滤器惟一的区别就是,作为筛选条件的列的不会蕴含在返回的后果中。 12、SkipFilter:这是一种附加过滤器,其与ValueFilter联合应用,如果发现一行中的某一列不符合条件,那么整行就会被过滤掉 Filter skf=new SkipFilter(vf);//OK发现某一行中的一列须要过滤时,整个行就会被过滤掉13、WhileMatchFilter:如果你想要在遇到某种条件数据之前的数据时,就能够应用这个过滤器;当遇到不合乎设定条件的数据的时候,整个扫描也就完结了 Filter wmf=new WhileMatchFilter(rf);//OK相似于Pythonitertools中的takewhile14、FilterList:用于综合应用多个过滤器(应用过) List<Filter>filters=new ArrayList<Filter>();filters.add(rf);filters.add(vf);FilterList fl=?new FilterList(FilterList.Operator.MUST_PASS_ALL,filters);//OK综合应用多个过滤器,AND和OR两种关系通过Filter获取后果集案例 FilterList filterList=new FilterList();Filter filter=new RowFilter(CompareOperator.EQUAL,new BinaryComparator(Bytes.toBytes("test|id9")));filterList.addFilter(filter);ResultScanner www = HBaseUtil.getScanner("www",filterList);for (Result re:www){ for(Cell kv:re.rawCells()){ System.out.println("====="+kv.toString()); System.out.println("列族:"+Bytes.toString(kv.getFamilyArray(),kv.getFamilyOffset(),kv.getFamilyLength())); System.out.println("RowKey:"+Bytes.toString(kv.getRowArray(),kv.getRowOffset(),kv.getRowLength())); System.out.println("列名:"+Bytes.toString(kv.getQualifierArray(),kv.getQualifierOffset(),kv.getQualifierLength())); System.out.println("值:"+Bytes.toString(kv.getValueArray(),kv.getValueOffset(),kv.getValueLength())); System.out.println("================================================================================="); }} ...

September 17, 2020 · 1 min · jiezi

关于hbase:Hbase备份与恢复快照技术

什么是快照快照就是一份元信息的合集,容许管理员复原到表的先前状态。快照不是表的复制而是一个文件名称列表,因此不会复制数据。快照的作用HBase中存在的备份或克隆表的办法就是应用复制/导出表或者在敞开表之后拷贝HDFS中的所有HFile。复制或导出是通过一系列工具调用MapReduce来扫描并复制表,这样会对RegionServer有间接的影响。敞开表会进行所有的读写操作,理论环境中往往无奈承受。相比之下HBase快照容许管理员不拷贝数据,而间接克隆一张表,这对域服务器产生的影响最小。将快照导出至其余集群不会间接影响到任何服务器;导出只是带有一些额定逻辑的群间数据同步。齐全快照复原是指复原到之前的“表构造”以及过后的数据,快照之后产生的数据不会复原。快照劣势导出快照与复制/导出表除了更好地放弃一致性外,次要的不同在于导出快照是在HDFS的层面操作的。 这意味着HMaster和域服务器与操作无关。因而不须要为不必要的数据创立缓存空间,也不会有扫描过程。因为大量对象创立引起的GC暂停,对于HBase 来说次要性能影响就是DataNode额定的网络和磁盘负载。应用快照备份数据 1.配置文件配置能够应用快照性能 <property> <name>hbase.snapshot.enabled</name> <value>true</value></property>2.新建一个快照 > snapshot 'www','www001'3.查看所有的快照 > list_snapshots4.应用快照克隆一个表 > clone_snapshot 'www001','wwww'5.复原数据到快照 > disable 'www'> restore_snapshot 'www001'6.删除快照 > delete_snapshot 'www001'7.应用ExportSnapshot将以后快照导出至其余集群,导出工具不会影响到域服务器的负载,只是在HDFS层面,所以须要指定HDFS门路(其它集群的hbase根目录) hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshotName -copy-to hdfs://server1:8082/hbase

September 16, 2020 · 1 min · jiezi

关于hbase:基于dockercompose-搭建本地hbase测试环境

之前在本地测试环境, 搭了一整套hadoop, 能力失常运行hbase, 运行中常常闪退, 于是找寻docker搭建计划.站在伟人肩膀上github有基于docker-compose搭建hbase的我的项目, 非常残缺, 依照阐明间接up, 便能在镜像中进行hbase shell等相干操作, 然而从内部连贯hbase(指通过zk)有一些问题, 之后通过几行配置批改, 实现了该指标. github地址 修脚此我的项目中有两个docker-compose文件, 一个standlone, 一个distribution. 都是local的. 原本我打算用standlone, 惋惜regionserver的端口在一万多个端口中随机... 于是抉择应用distribution.hosts文件批改内部连贯zk, 能够通过关上2181端口实现, 可是zk里存的是docker中的hostname, 你的程序并不在容器中, 会呈现unknown hosts的状况, 于是须要增加以下到hosts文件中(对应到docker-compose文件中的hostname) 0.0.0.0 hbase-master0.0.0.0 hbase-regiondocker-compose-distributed-local.yml 文件批改这个文件, 有些小坑, 很多重要端口没开, 导致连贯超时(程序假死). 通过很多debug后, 确认了端口, 并且补齐. hbase-master: image: bde2020/hbase-master:1.0.0-hbase1.2.6 container_name: hbase-master hostname: hbase-master env_file: - ./hbase-distributed-local.env environment: SERVICE_PRECONDITION: "namenode:50070 datanode:50075 zoo:2181" ports: - 16010:16010 - 16000:16000 # 新增加 hbase-region: image: bde2020/hbase-regionserver:1.0.0-hbase1.2.6 container_name: hbase-regionserver hostname: hbase-regionserver env_file: - ./hbase-distributed-local.env environment: HBASE_CONF_hbase_regionserver_hostname: hbase-region SERVICE_PRECONDITION: "namenode:50070 datanode:50075 zoo:2181 hbase-master:16010" ports: - 16030:16030 - 16020:16020 # 新增加rundocker-compose -f docker-compose-distributed-local.yml up ...

September 15, 2020 · 1 min · jiezi

关于hbase:Hbase架构入门

Hbase结构图Hbase自身蕴含三局部,Zookeeper,HMaster,HRegionServer Zookeeper:1.保障任何时候只有一个沉闷的Master2.存储所有的Region的地址,晓得哪个Region存储在哪台机器上3.时刻监控RegionServer的状态,将RegionServer的高低线信息,RegionServer不间接向HMaster汇报,加重HMaster的压力,通过Zookeeoer发送信息4.存储Hbase的元数据结构(Schema),晓得集群中有哪些Table,每个Table有哪些Column Family HMaster:1.为所有的RegionServer调配Region2.负责RegionServer的负载平衡3.发现生效的RegionServer,重新分配下面的Region4.HDFS的垃圾文件5.解决Schema申请(表的创立,删除,批改,列族的减少等) HRegionServer:负责数据的读写操作,客户端间接和RegionServer交互RegionServer介绍一个RegionServer会有多个Region,每个Region有多个Store每个Store有多个StoreFile(HFile)每个Store有一个Memstore 客户端通过发申请到RegionServer端,写入的时候会先写入WAL日志中,其次会将数据写入memstore内存,当数据达到肯定大小后会flush成一个个的StoreFile(HFile)文件,当文件达到肯定数量后,通过compaction的操作合并成更大文件,这样数据读取会更快。 1)HRegion: (1)、简介:Table在行的方向上分隔为多个Region,Region是HBase中分布式存储和负载平衡的最小单元,即不同的Region能够分在不同的RegionServer下面,但同一个Region是不会拆分到多个Server下面的。随着数据的增多,某个列族的达到一个阈值就会分成两个新的Region。构造:<表名,startRowkey,创立工夫>,由目录表(-ROOT-,.META.)记录该Region的endRowkey(2)、Store: (1)简介:每一个Region由一个或则多个Store组成,至多是一个Store,HBase会把拜访的数据寄存在Store中,即每一个列族建一个Store,如果有多个ColumnFamily,就多多个Store,一个Store由一个MemStore和0或则多个StoreFile组成。HBase通过Store的大小判断是否须要切分Region。 (2)MemStore:它是放在内存中的,保留批改的数据,即key/values。当MemStore的大小达到肯定的阈值的时候(默认128M),MemStore会被Flush到文件,即生成一个快照StoreFile,Flush过程由一个线程实现。 (3)StoreFile:StoreFile底层是HFile,HFile是Hadoop的二进制格式文件, (2)HLog:WAL文件,用来劫难复原应用,HLog记录数据的所有变更,一旦RegionServer宕机,就从HLog中进行复原,HLog文件就是一个一般的Hadoop Sequence File,Sequence File记录了写入数据的归属信息,除了Table和Region名字外,还同时包含了Sequence Number和TimeStamp,Sequence File的value是HBase的key/value对象,即对应的HFile中的key/value。 Hbase 中的 Compaction其实Compaction操作属于资源密集型操作特地是IO密集型,这点前面也会提及到,Compaction实质上其实就是就义了局部IO,以换取绝对稳固的读取性能。compaction的核心作用是:通过合并大量小文件为一个大文件来缩小hfile的总数量,进而保障读提早的稳固。HBase Compaction分为两种:Minor Compaction 与 Major Compaction,通常咱们简称为小合并、大合并

September 15, 2020 · 1 min · jiezi

关于hbase:Hbase常用数据库操作类

pom.xml中援用hbase-client <dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>2.2.5</version></dependency>HBaseConn.java获取hbase链接 package com.rumenz;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.hbase.HBaseConfiguration;import org.apache.hadoop.hbase.TableName;import org.apache.hadoop.hbase.client.Connection;import org.apache.hadoop.hbase.client.ConnectionFactory;import org.apache.hadoop.hbase.client.Table;import java.io.IOException;public class HBaseConn { private static final HBaseConn INSTANCE=new HBaseConn(); private static Configuration configuration; private static Connection connection; private HBaseConn(){ try{ if(configuration==null){ configuration=HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", "192.168.82.177:2181"); } }catch (Exception e){ e.printStackTrace(); } } private Connection getConnection(){ if(connection==null||connection.isClosed()){ try{ connection=ConnectionFactory.createConnection(configuration); }catch(Exception e){ e.printStackTrace(); } } return connection; } public static Connection getHbaseConn(){ return INSTANCE.getConnection(); } public static Table getTable(String table) throws IOException { return INSTANCE.getConnection().getTable(TableName.valueOf(table)); } public static void closeConn(){ if(connection!=null){ try{ connection.close(); }catch(Exception e){ e.printStackTrace(); } } }}HBaseUtil.java数据库增删改查操作 ...

September 14, 2020 · 3 min · jiezi

关于hbase:Hbase高级功能过滤Filter

1.创立一个Rumenz表 // 创立了两个列族user和depart> ./bin/hbase shell> create 'Rumenz','user','depart'2.插入数据 > put 'Rumenz','user|id1','user:name','张三'> put 'Rumenz','user|id1','depart:name','开发部'> put 'Rumenz','user|id2','user:name','王五'> put 'Rumenz','user|id2','depart:name','市场部'> put 'Rumenz','user|tsc','user:name','入门'> put 'Rumenz','user1|id1','user:name','小站'3.找出值为张三的记录 > scan 'Rumenz',FILTER=>"ValueFilter(=,'binary:张三')"4.找出值中蕴含部字的记录 > scan 'Rumenz',FILTER=>"ValueFilter(=,'substring:部')"5.找出列名以dep结尾的记录 > scan 'Rumenz',FILTER=>"ColumnPrefixFilter('dep')"6.找出列名以ts结尾并且值为入门的值 > scan 'Rumenz',FILTER=>"ColumnPrefixFilter('ts') AND ValueFilter(=,'binary:入门')"7.找出rowkey以user1结尾 > scan 'Rumenz',FILTER=>"PrefixFilter('user1')"8.一个rowkey可能有会多个版本,通过FirstKeyOnlyFilter能够获取最新版本的数据.获取最新数据中值中蕴含部的数据 > scan 'Rumenz',FILTER=>"FirstKeyOnlyFilter() and ValueFilter(=,'substring:部')"9.一个rowkey可能有会多个版本,通过FirstKeyOnlyFilter能够获取最新版本的数据.获取最新数据中值中蕴含部的数据并且只返回key不须要value > scan 'Rumenz',FILTER=>"FirstKeyOnlyFilter() and ValueFilter(=,'substring:部') AND KeyOnlyFilter()"10.从user|id2行开始,查问rowkey以user结尾的数据 > sacn 'Rumenz',{STARTROW=>'user|id2',FILTER=>"PrefixFilter('user')"}11.查找rowkey中蕴含id的数据 > scan 'Rumenz', {FILTER => RowFilter.new(CompareFilter::CompareOp.valueOf('EQUAL'), SubstringComparator.new('id'))}12.查找user:name列值为王五的数据并只显示user:name列 //显示多个列应用COLUMNS => ['user:name','xxxx']>scan 'Rumenz', {COLUMNS => 'user:name', FILTER => SingleColumnValueFilter.new(Bytes.toBytes('user'), Bytes.toBytes('name'), CompareFilter::CompareOp.valueOf('EQUAL'), Bytes.toBytes('王五'))} ...

September 12, 2020 · 1 min · jiezi

关于hbase:内含面试一文搞懂HBase的基本原理

本文会对HBase的基本原理进行分析,通过本文你能够理解到: CAP实践NoSQL呈现的起因HBase的特点及应用场景HBase的数据模型和基本原理客户端API的根本应用易混同知识点面试总结舒适提醒:本文内容较长,如果感觉有用,倡议珍藏。另外记得分享、点赞、在看,素质三连哦! 从BigTable说起HBase是在谷歌BigTable的根底之上进行开源实现的,是一个高牢靠、高性能、面向列、可伸缩的分布式数据库,能够用来存储非结构化和半结构化的稠密数据。HBase反对超大规模数据存储,能够通过程度扩大的形式解决超过10亿行数据和百万列元素组成的数据表。 BigTable是一个分布式存储系统,利用谷歌提出的MapReduce分布式并行计算模型来解决海量数据,应用谷歌分布式文件系统GFS作为底层的数据存储,并采纳Chubby提供协同服务治理,具备宽泛的应用型、可扩展性、高可用性及高性能性等特点。对于BigTable与HBase的比照,见下表: 依赖BigTbaleHBase数据存储GFSHDFS数据处理MapReduceHadoop的MapReduce协同服务ChubbyZookeeperCAP实践2000年,Berkerly大学有位Eric Brewer传授提出了一个CAP实践,在2002年,麻省理工学院的Seth Gilbert(赛斯·吉尔伯特)和Nancy Lynch(南希·林奇)发表了布鲁尔猜测的证实,证实了CAP实践的正确性。所谓CAP实践,是指对于一个分布式计算零碎来说,不可能同时满足以下三点: 一致性(Consistency)等同于所有节点拜访同一份最新的数据正本。即任何一个读操作总是可能读到之前实现的写操作的后果,也就是说,在分布式环境中,不同节点拜访的数据是统一的。 可用性(Availability)每次申请都能获取到非错的响应——然而不保障获取的数据为最新数据。即疾速获取数据,能够在确定的工夫内返回操作后果。 分区容错性(Partition tolerance)以实际效果而言,分区相当于对通信的时限要求。零碎如果不能在时限内达成数据一致性,就意味着产生了分区的状况,必须就以后操作在C和A之间做出抉择。即指当呈现网络分区时(零碎中的一部分节点无奈与其余的节点进行通信),拆散的零碎也可能失常运行,即可靠性。 如上图所示:一个分布式的零碎不可能同时满足一致性、可用性和分区容错性,最多同时满足两个。当解决CAP的问题时,能够有一下几个抉择: 满足CA,不满足P。将所有与事务相干的内容都放在同一个机器上,这样会影响零碎的可扩展性。传统的关系型数据库。如MySQL、SQL Server 、PostgresSQL等都采纳了此种设计准则。满足AP,不满足C。不满足一致性(C),即容许零碎返回不统一的数据。其实,对于WEB2.0的网站而言,更加关注的是服务是否可用,而不是一致性。比方你发了一篇博客或者写一篇微博,你的一部分敌人立马看到了这篇文章或者微博,另一部分敌人却要等一段时间之后能力刷出这篇文章或者微博。尽管有延时,然而对于一个娱乐性质的Web 2.0网站而言,这几分钟的延时并不重要,不会影响用户体验。相同,当公布一篇文章或微博时,不可能立刻公布(不满足可用性),用户对此必定不爽。所以呢,对于WEB2.0的网站而言,可用性和分区容错性的优先级要高于数据一致性,当然,并没有齐全放弃一致性,而是最终的一致性(有延时)。如Dynamo、Cassandra、CouchDB等NoSQL数据库采纳了此准则。满足CP,不满足A。强调一致性性(C)和分区容错性(P),放弃可用性性(A)。当呈现网络分区时,受影响的服务须要期待数据统一,在期待期间无奈对外提供服务。如Neo4J、HBase 、MongoDB、Redis等采纳了此种设计准则。为什么呈现NoSQL所谓NoSQL,即Not Only SQL的缩写,意思是不只是SQL。下面提到的CAP实践正是NoSQL的设计准则。那么,为什么会衰亡NoSQL数据库呢?因为WEB2.0以及大数据时代的到来,关系型数据库越来越不能满足需要。大数据、物联网、挪动互联网和云计算的倒退,使得非结构化的数据比例高达90%以上,关系型数据库因为模型不灵便以及扩大程度较差,在面对大数据时,暴露出了越来越多的缺点。由此NoSQL数据库应运而生,更好地满足了大数据时代及WEB2.0的需要。 面对WEB2.0以及大数据的挑战,关系型数据库在以下几个方面体现欠佳: 对于海量数据的解决性能较差WEB2.0时代,尤其是挪动互联网的倒退,UGC(用户生成内容,User Generated Content)以及PGC(公众生成内容,Public Generated Content)占据了咱们的日常。现如今,自媒体倒退遍地开花,简直每个人都成了内容的创造者,比方博文、评论、意见、新闻音讯、视频等等,不一而足。可见,这些数据产生的速度之快,数据量之大。比方微博、公众号、抑或是淘宝,在一分钟内产生的数据可能就会十分的惊人,面对这些千万级、亿级的数据记录,关系型数据库的查问效率显然是不能承受的。 无奈满足高并发需要WEB1.0时代,大部分是动态网页(即提供什么就看什么),从而在大规模用户拜访时,能够实现较好的响应能力。然而,在WEB2.0时代,强调的是用户的交互性(用户发明内容),所有信息都须要事实动静生成,会造成高并发的数据库拜访,可能每秒上万次的读写申请,对于很多关系型数据库而言,这显示是难以承受的。 无奈满足扩展性和高可用性的需要在当今娱乐至死的时代,热点问题(吸引人眼球,满足好奇心理)会引来一窝蜂的流量,比方微博曝出某明星出轨,热搜榜会迅速引来少量用户围观(俗称吃瓜大众),从而产生大量的互动交换(蹭热点),这些都会造成数据库的读写负荷急剧减少,从而须要数据库可能在短时间内迅速晋升性能以应答突发需要(毕竟宕机会十分影响户体验)。然而关系型数据库通常难以程度扩大,不可能像网页服务器和应用服务器那样简略地通过减少更多的硬件和服务节点来扩大性能和负载能力。 综上,NoSQL数据库应运而生,是IT倒退的必然。 HBase的特点及应用场景特点强一致性读写HBase 不是 最终一致性(eventually consistent) 数据存储. 这让它很适宜高速计数聚合类工作 主动分片(Automatic sharding)HBase 表通过region散布在集群中。数据增长时,region会主动宰割并从新散布 RegionServer 主动故障转移Hadoop/HDFS 集成HBase 反对本机外HDFS 作为它的分布式文件系统 MapReduce集成HBase 通过MapReduce反对大并发解决, HBase 能够同时做源(Source)和汇(Sink) Java 客户端 APIHBase 反对易于应用的 Java API 进行编程拜访 Thrift/REST API反对Thrift 和 REST 的形式拜访HBase Block Cache 和 布隆过滤器(Bloom Filter)HBase反对 Block Cache 和 布隆过滤器进行查问优化,晋升查问性能 ...

August 12, 2020 · 2 min · jiezi

关于hbase:内含面试一文搞懂HBase的基本原理

本文会对HBase的基本原理进行分析,通过本文你能够理解到: CAP实践NoSQL呈现的起因HBase的特点及应用场景HBase的数据模型和基本原理客户端API的根本应用易混同知识点面试总结舒适提醒:本文内容较长,如果感觉有用,倡议珍藏。另外记得分享、点赞、在看,素质三连哦! 从BigTable说起HBase是在谷歌BigTable的根底之上进行开源实现的,是一个高牢靠、高性能、面向列、可伸缩的分布式数据库,能够用来存储非结构化和半结构化的稠密数据。HBase反对超大规模数据存储,能够通过程度扩大的形式解决超过10亿行数据和百万列元素组成的数据表。 BigTable是一个分布式存储系统,利用谷歌提出的MapReduce分布式并行计算模型来解决海量数据,应用谷歌分布式文件系统GFS作为底层的数据存储,并采纳Chubby提供协同服务治理,具备宽泛的应用型、可扩展性、高可用性及高性能性等特点。对于BigTable与HBase的比照,见下表: 依赖BigTbaleHBase数据存储GFSHDFS数据处理MapReduceHadoop的MapReduce协同服务ChubbyZookeeperCAP实践2000年,Berkerly大学有位Eric Brewer传授提出了一个CAP实践,在2002年,麻省理工学院的Seth Gilbert(赛斯·吉尔伯特)和Nancy Lynch(南希·林奇)发表了布鲁尔猜测的证实,证实了CAP实践的正确性。所谓CAP实践,是指对于一个分布式计算零碎来说,不可能同时满足以下三点: 一致性(Consistency)等同于所有节点拜访同一份最新的数据正本。即任何一个读操作总是可能读到之前实现的写操作的后果,也就是说,在分布式环境中,不同节点拜访的数据是统一的。 可用性(Availability)每次申请都能获取到非错的响应——然而不保障获取的数据为最新数据。即疾速获取数据,能够在确定的工夫内返回操作后果。 分区容错性(Partition tolerance)以实际效果而言,分区相当于对通信的时限要求。零碎如果不能在时限内达成数据一致性,就意味着产生了分区的状况,必须就以后操作在C和A之间做出抉择。即指当呈现网络分区时(零碎中的一部分节点无奈与其余的节点进行通信),拆散的零碎也可能失常运行,即可靠性。 如上图所示:一个分布式的零碎不可能同时满足一致性、可用性和分区容错性,最多同时满足两个。当解决CAP的问题时,能够有一下几个抉择: 满足CA,不满足P。将所有与事务相干的内容都放在同一个机器上,这样会影响零碎的可扩展性。传统的关系型数据库。如MySQL、SQL Server 、PostgresSQL等都采纳了此种设计准则。满足AP,不满足C。不满足一致性(C),即容许零碎返回不统一的数据。其实,对于WEB2.0的网站而言,更加关注的是服务是否可用,而不是一致性。比方你发了一篇博客或者写一篇微博,你的一部分敌人立马看到了这篇文章或者微博,另一部分敌人却要等一段时间之后能力刷出这篇文章或者微博。尽管有延时,然而对于一个娱乐性质的Web 2.0网站而言,这几分钟的延时并不重要,不会影响用户体验。相同,当公布一篇文章或微博时,不可能立刻公布(不满足可用性),用户对此必定不爽。所以呢,对于WEB2.0的网站而言,可用性和分区容错性的优先级要高于数据一致性,当然,并没有齐全放弃一致性,而是最终的一致性(有延时)。如Dynamo、Cassandra、CouchDB等NoSQL数据库采纳了此准则。满足CP,不满足A。强调一致性性(C)和分区容错性(P),放弃可用性性(A)。当呈现网络分区时,受影响的服务须要期待数据统一,在期待期间无奈对外提供服务。如Neo4J、HBase 、MongoDB、Redis等采纳了此种设计准则。为什么呈现NoSQL所谓NoSQL,即Not Only SQL的缩写,意思是不只是SQL。下面提到的CAP实践正是NoSQL的设计准则。那么,为什么会衰亡NoSQL数据库呢?因为WEB2.0以及大数据时代的到来,关系型数据库越来越不能满足需要。大数据、物联网、挪动互联网和云计算的倒退,使得非结构化的数据比例高达90%以上,关系型数据库因为模型不灵便以及扩大程度较差,在面对大数据时,暴露出了越来越多的缺点。由此NoSQL数据库应运而生,更好地满足了大数据时代及WEB2.0的需要。 面对WEB2.0以及大数据的挑战,关系型数据库在以下几个方面体现欠佳: 对于海量数据的解决性能较差WEB2.0时代,尤其是挪动互联网的倒退,UGC(用户生成内容,User Generated Content)以及PGC(公众生成内容,Public Generated Content)占据了咱们的日常。现如今,自媒体倒退遍地开花,简直每个人都成了内容的创造者,比方博文、评论、意见、新闻音讯、视频等等,不一而足。可见,这些数据产生的速度之快,数据量之大。比方微博、公众号、抑或是淘宝,在一分钟内产生的数据可能就会十分的惊人,面对这些千万级、亿级的数据记录,关系型数据库的查问效率显然是不能承受的。 无奈满足高并发需要WEB1.0时代,大部分是动态网页(即提供什么就看什么),从而在大规模用户拜访时,能够实现较好的响应能力。然而,在WEB2.0时代,强调的是用户的交互性(用户发明内容),所有信息都须要事实动静生成,会造成高并发的数据库拜访,可能每秒上万次的读写申请,对于很多关系型数据库而言,这显示是难以承受的。 无奈满足扩展性和高可用性的需要在当今娱乐至死的时代,热点问题(吸引人眼球,满足好奇心理)会引来一窝蜂的流量,比方微博曝出某明星出轨,热搜榜会迅速引来少量用户围观(俗称吃瓜大众),从而产生大量的互动交换(蹭热点),这些都会造成数据库的读写负荷急剧减少,从而须要数据库可能在短时间内迅速晋升性能以应答突发需要(毕竟宕机会十分影响户体验)。然而关系型数据库通常难以程度扩大,不可能像网页服务器和应用服务器那样简略地通过减少更多的硬件和服务节点来扩大性能和负载能力。 综上,NoSQL数据库应运而生,是IT倒退的必然。 HBase的特点及应用场景特点强一致性读写HBase 不是 最终一致性(eventually consistent) 数据存储. 这让它很适宜高速计数聚合类工作 主动分片(Automatic sharding)HBase 表通过region散布在集群中。数据增长时,region会主动宰割并从新散布 RegionServer 主动故障转移Hadoop/HDFS 集成HBase 反对本机外HDFS 作为它的分布式文件系统 MapReduce集成HBase 通过MapReduce反对大并发解决, HBase 能够同时做源(Source)和汇(Sink) Java 客户端 APIHBase 反对易于应用的 Java API 进行编程拜访 Thrift/REST API反对Thrift 和 REST 的形式拜访HBase Block Cache 和 布隆过滤器(Bloom Filter)HBase反对 Block Cache 和 布隆过滤器进行查问优化,晋升查问性能 ...

August 12, 2020 · 2 min · jiezi

关于hbase:内存总是不够HBaseGeoMesa配置优化了解一下

详情:生产环境HBase集群内存常常处于高位(90%),而且GC之后也是内存仍然处于高位,经剖析内存全副由集群的regionserver过程所持有,,常常重启之后,大略3-4天就会放弃在高位。由上述症状,能够判断集群内存有泄露的嫌疑。 剖析1、先相熟一下HBase的内存模型HBase零碎中有两块大的内存治理模块,一块是MemStore ,一块是BlockCache,前置是用于集群写入所属内存,而后者用于缓存热数据,提供查问速度。这两者均能够通过配置文件进行配置。以后集群均配置了0.4和0.4的比例。而思考到HBase集群是多写少读的情景,为此而引入了MSLAB机制来优化HBase的MemStore 累赘。内存的使用率会出现很柔美的锯齿图形。 2、剖析内存使用率和业务关系起初认为是读写业务量曾经超过了集群负载能力,但集群业务也不大,写和读的TPS,带宽吞吐量均未达到集群限定的能力,而且CPU利用率大多半都被GC占用,但内存就是持高不下,即便业务了停了一天,内存还是不怎么降落,很显著和业务量无关。 那么和compaction无关?经察看确实能够看compact时特地耗费工夫。此时感觉看到了心愿,调整各个参数,把compact操作晋升了10+倍之后,内存还是持高不下 。剩下最根治的方法就是剖析内存,看一下内存数据都是什么?有无内存泄露问题。 3、剖析dunp文件节点dump下regionserver的内存,剖析发现内存中有50个RpcServer.FifoRWQ.default.read.handler线程,每个线程持有了1.2%左右的总内存,那么所有的线程持有的内存占有量大于为50*1.2%=60%。随着查问次数增多,线程继续的内存还会继续减少,如下图。 剖析每一个线程持有的内存数据,全部都是业务信息。 那么持续剖析,此业务信息所属对象:org.locationtech.geomesa.filter.factory.FastFilterFactory。而比照同规模的集群,确实是此异样集群开启了GeoMesa个性。找到问题所在,那就看源码剖析是惟一前途。 解决方案经剖析GeoMesa源码,缓存数据为GeoMesa的filterCache,全部都是查问的条件及其优化后查问条件。如下代码: override def getOrElseUpdate(key: K, op: => V): V = { val cached = caches.get.getIfPresent(key) if (cached != null) { cached } else { val value = op//value=optimize(sft, ECQL.toFilter(ecql))caches.get.put(key, value) value } }导致集群随着查问次数增多,内存始终继续不下。 是否去掉此处缓存策略呢?为什么缓存此查问信息呢,目标就是为了缩小同样的查问再次被优化的步骤。那么咱们查问添条件key有没有重复使用,此处有个严格规定,就是key中不仅保障应用雷同的GeoMesa函数还有应用雷同的参数,基于这个准则,业务上查问条件是没有反复的。 咱们配置了可选参数useFilterCache,默认是开启的,没必要缓存此查问条件,应予以删除。 论断在配置文件中增加了useFilterCache参数,默认是开启的,依据业务须要抉择开始和敞开filterCache特效。 经剖析咱们业务场景没必要缓存此查问条件,,应予以敞开。优化后的集群内存使用率状况就复原了失常状态。 点击关注,第一工夫理解华为云陈腐技术~

August 10, 2020 · 1 min · jiezi

关于hbase:HBase应用架构

HBase利用架构 下载地址: https://pan.baidu.com/s/10I2G7y39oeRB20vUUb11XQ 扫码上面二维码关注公众号回复100002 获取分享码 本书目录构造如下: 序 1 前言 3 第一局部 HBase概述 第1章什么是HBase  11 面向列与面向行 13 实现和应用示例 13 第2章 HBase原理 15 表格局列族 15 表的外部操作 22 依赖 27 HBase 角色 27 第3章 HBase生态系统 32 监控工具 32 SQL 40 框架 42 第4章 HBase规模预估和调优概述 45 硬件 46 存储 46 网络 47 操作系统调优 48 Hadoop调优 49 HBase调优 50 负载不均调优 52 第5章环境设置 54 零碎要求 55 HBase单机装置 58 虚拟机中的HBase 61 本地与VM 62 故障排除 63 ...

August 6, 2020 · 1 min · jiezi

关于hbase:HBase-Region分裂的三种策略

1、ConstantSizeRegionSplitPolicy一个Region中最大Store的大小超过阈值之后就会触发决裂。该策略最简略,但弊病相当大。阈值设置大,对大表敌对,小表可能不会触发决裂,极其状况下可能只有一个region。阈值设置小,对小表敌对,但一个大表可能在集群中产生大量的region。对于集群治理不是坏事。 2、IncreasiongToUpperBoundRegionSplitPolicy一个Region中最大Store的大小超过阈值之后就会触发决裂。阈值不是固定的值,而是在肯定状况下一直调整的,调整后的阈值大小和Region所属表在以后region server上的region个数有关系。调整后的阈值 = regions regions flushsize * 2阈值不会有限增大,maxRegionFileSize来做限度。可能自适应大小表,集群规模大的状况下,对大表很优良,对小表会产生大量小region 3、SteppingSplitPolicy决裂阈值大小和待决裂Region所属表在以后Region Server上的region个数有关系。如果region个数为1,决裂之为flushsize * 2。否则为 maxRegionFileSize大表小表都不会产生大量的region Region决裂筹备1、初始化两个子Region对象2、更改zk的状态为splitting、更改master内存中父region的状态信息3、在父目录下新建.split文件夹4、敞开父region,flush操作,数据落盘。短时间落在父region上的申请都会抛异样5、在.split文件夹下生成两个子文件夹daughterA、daughterB,并在两个文件夹内生成reference文件,别离指向父region中对应的文件 reference是援用文件,文件中的内容并不是用户数据。由两局部形成,决裂点、boolean变量,true示意reference援用的是父文件的上局部,false示意下半局部6、决裂成两个region后,将daughterA、daughterB拷贝到HBase根目录7、下线父region,批改meta表, 依据reference文件查找数据1、依据文件名定位到具体文件(父region名+hfile名)2、依据reference文件内容的两个变量确定要扫描的局部数据 父region数据迁徙到子regionMajor Compaction 父region被删除的工夫master启动线程定期遍历查看所有处于splitting状态的父region1、读取出meta表中所有split为true的region,加载出他们的子region2、查看子region是否还存在援用文件,若不存在,父region对应的文件就能删除

July 30, 2020 · 1 min · jiezi

关于hbase:HBase-Region分裂的三种策略

1、ConstantSizeRegionSplitPolicy一个Region中最大Store的大小超过阈值之后就会触发决裂。该策略最简略,但弊病相当大。阈值设置大,对大表敌对,小表可能不会触发决裂,极其状况下可能只有一个region。阈值设置小,对小表敌对,但一个大表可能在集群中产生大量的region。对于集群治理不是坏事。 2、IncreasiongToUpperBoundRegionSplitPolicy一个Region中最大Store的大小超过阈值之后就会触发决裂。阈值不是固定的值,而是在肯定状况下一直调整的,调整后的阈值大小和Region所属表在以后region server上的region个数有关系。调整后的阈值 = regions regions flushsize * 2阈值不会有限增大,maxRegionFileSize来做限度。可能自适应大小表,集群规模大的状况下,对大表很优良,对小表会产生大量小region 3、SteppingSplitPolicy决裂阈值大小和待决裂Region所属表在以后Region Server上的region个数有关系。如果region个数为1,决裂之为flushsize * 2。否则为 maxRegionFileSize大表小表都不会产生大量的region Region决裂筹备1、初始化两个子Region对象2、更改zk的状态为splitting、更改master内存中父region的状态信息3、在父目录下新建.split文件夹4、敞开父region,flush操作,数据落盘。短时间落在父region上的申请都会抛异样5、在.split文件夹下生成两个子文件夹daughterA、daughterB,并在两个文件夹内生成reference文件,别离指向父region中对应的文件 reference是援用文件,文件中的内容并不是用户数据。由两局部形成,决裂点、boolean变量,true示意reference援用的是父文件的上局部,false示意下半局部6、决裂成两个region后,将daughterA、daughterB拷贝到HBase根目录7、下线父region,批改meta表, 依据reference文件查找数据1、依据文件名定位到具体文件(父region名+hfile名)2、依据reference文件内容的两个变量确定要扫描的局部数据 父region数据迁徙到子regionMajor Compaction 父region被删除的工夫master启动线程定期遍历查看所有处于splitting状态的父region1、读取出meta表中所有split为true的region,加载出他们的子region2、查看子region是否还存在援用文件,若不存在,父region对应的文件就能删除

July 30, 2020 · 1 min · jiezi

关于hbase:HBase原理HBase读取流程

和写流程相比,HBase读数据的流程更加简单。次要基于两个方面的起因:一是因为HBase一次范畴查问可能会波及多个Region、多块缓存甚至多个数据存储文件;二是因为HBase中更新操作以及删除操作的实现都很简略,更新操作并没有更新原有数据,而是应用工夫戳属性实现了多版本;删除操作也并没有真正删除原有数据,只是插入了一条标记为"deleted"标签的数据,而真正的数据删除产生在零碎异步执行Major Compact的时候。很显然,这种实现思路大大简化了数据更新、删除流程,然而对于数据读取来说却意味着套上了层层桎梏:读取过程须要依据版本进行过滤,对曾经标记删除的数据也要进行过滤。 本节系统地将HBase读取流程的各个环节串起来进行解读。读流程从头到尾能够分为如下4个步骤:Client-Server读取交互逻辑,Server端Scan框架体系,过滤淘汰不合乎查问条件的HFile,从HFile中读取待查找Key。其中Client-Server交互逻辑次要介绍HBase客户端在整个scan申请的过程中是如何与服务器端进行交互的,了解这点对于应用HBase Scan API进行数据读取十分重要。理解Server端Scan框架体系,从宏观上介绍HBase RegionServer如何逐渐解决一次scan申请。接下来的大节会对scan流程中的外围步骤进行更加深刻的剖析。 Client-Server读取交互逻辑 Client-Server通用交互逻辑在之前介绍写入流程的时候曾经做过解读:Client首先会从ZooKeeper中获取元数据hbase:meta表所在的RegionServer,而后依据待读写rowkey发送申请到元数据所在RegionServer,获取数据所在的指标RegionServer和Region(并将这部分元数据信息缓存到本地),最初将申请进行封装发送到指标RegionServer进行解决。 在通用交互逻辑的根底上,数据读取过程中Client与Server的交互有很多须要关注的点。从API的角度看,HBase数据读取能够分为get和scan两类,get申请通常依据给定rowkey查找一行记录,scan申请通常依据给定的startkey和stopkey查找多行满足条件的记录。但从技术实现的角度来看,get申请也是一种scan申请(最简略的scan申请,scan的条数为1)。从这个角度讲,所有读取操作都能够认为是一次scan操作。 HBase Client端与Server端的scan操作并没有设计为一次RPC申请,这是因为一次大规模的scan操作很有可能就是一次全表扫描,扫描后果十分之大,通过一次RPC将大量扫描后果返回客户端会带来至多两个十分重大的结果: •大量数据传输会导致集群网络带宽等系统资源短时间被大量占用,重大影响集群中其余业务。 •客户端很可能因为内存无奈缓存这些数据而导致客户端OOM。 实际上HBase会依据设置条件将一次大的scan操作拆分为多个RPC申请,每个RPC申请称为一次next申请,每次只返回规定数量的后果。上面是一段scan的客户端示例代码: public static void scan(){ HTable table=... ; Scan scan=new Scan(); scan.withStartRow(startRow) //设置检索起始row .withStopRow(stopRow) //设置检索完结row .setFamilyMap (Map<byte[],Set<byte[]>familyMap>) //设置检索的列簇和对应列簇下的列汇合 .setTimeRange(minStamp,maxStamp) //设置检索TimeRange .setMaxVersions(maxVersions) //设置检索的最大版本号 .setFilter(filter) //设置检索过滤器 scan.setMaxResultSize(10000); scan.setCacheing(500); scan.setBatch(100); ResultScanner rs=table.getScanner(scan); for (Result r : rs){ for (KeyValue kv : r.raw()){ ...... } }} 其中,for (Result r : rs)语句理论等价于Result r=rs.next()。每执行一次next()操作,客户端先会从本地缓存中查看是否有数据,如果有就间接返回给用户,如果没有就发动一次RPC申请到服务器端获取,获取胜利之后缓存到本地。 单次RPC申请的数据条数由参数caching设定,默认为Integer.MAX_VALUE。每次RPC申请获取的数据都会缓存到客户端,该值如果设置过大,可能会因为一次获取到的数据量太大导致服务器端/客户端内存OOM;而如果设置太小会导致一次大scan进行太屡次RPC,网络老本高。 对于很多非凡业务有可能一张表中设置了大量(几万甚至几十万)的列,这样一行数据的数据量就会十分大,为了避免返回一行数据但数据量很大的状况,客户端能够通过setBatch办法设置一次RPC申请的数据列数量。 另外,客户端还能够通过setMaxResultSize办法设置每次RPC申请返回的数据量大小(不是数据条数),默认是2G。 Server端Scan框架体系从宏观视角来看,一次scan可能会同时扫描一张表的多个Region,对于这种扫描,客户端会依据hbase:meta元数据将扫描的起始区间[startKey, stopKey)进行切分,切分成多个相互独立的查问子区间,每个子区间对应一个Region。比方以后表有3个Region,Region的起始区间别离为:["a", "c"),["c", "e"),["e","g"),客户端设置scan的扫描区间为["b", "f")。因为扫描区间显著逾越了多个Region,须要进行切分,依照Region区间切分后的子区间为["b", "c"),["c","e"),["e", "f ")。 ...

July 29, 2020 · 1 min · jiezi

关于hbase:HBase原理BulkLoad

在理论生产环境中,有这样一种场景:用户数据位于HDFS中,业务须要定期将这部分海量数据导入HBase零碎,以执行随机查问更新操作。这种场景如果调用写入API进行解决,极有可能会给RegionServer带来较大的写入压力: •引起RegionServer频繁flush,进而一直compact、split,影响集群稳定性。 •引起RegionServer频繁GC,影响集群稳定性。 •耗费大量CPU资源、带宽资源、内存资源以及IO资源,与其余业务产生资源竞争。 •在某些场景下,比方均匀KV大小比拟大的场景,会耗尽RegionServer的解决线程,导致集群阻塞。 鉴于存在上述问题,HBase提供了另一种将数据写入HBase集群的办法——BulkLoad。BulkLoad首先应用MapReduce将待写入集群数据转换为HFile文件,再间接将这些HFile文件加载到在线集群中。显然,BulkLoad计划没有将写申请发送给RegionServer解决,能够无效防止上述一系列问题。 BulkLoad外围流程 从HBase的视角来看,BulkLoad次要由两个阶段组成: 1)HFile生成阶段。这个阶段会运行一个MapReduce工作,MapReduce的mapper须要本人实现,将HDFS文件中的数据读出来组装成一个复合KV,其中Key是rowkey,Value能够是KeyValue对象、Put对象甚至Delete对象;MapReduce的reducer由HBase负责,通过办法HFileOutputFormat2.configureIncrementalLoad()进行配置,这个办法次要负责以下事项。 •依据表信息配置一个全局有序的partitioner。 •将partitioner文件上传到HDFS集群并写入DistributedCache。 •设置reduce task的个数为指标表Region的个数。 •设置输入key/value类满足HFileOutputFormat所规定的格局要求。 •依据类型设置reducer执行相应的排序(KeyValueSortReducer或者PutSortReducer)。 这个阶段会为每个Region生成一个对应的HFile文件。 2)HFile导入阶段。HFile准备就绪之后,就能够应用工具completebulkload将HFile加载到在线HBase集群。completebulkload工具次要负责以下工作。 •顺次查看第一步生成的所有HFile文件,将每个文件映射到对应的Region。 •将HFile文件挪动到对应Region所在的HDFS文件目录下。 •告知Region对应的RegionServer,加载HFile文件对外提供服务。 如果在BulkLoad的两头过程中Region产生了决裂,completebulkload工具会主动将对应的HFile文件依照新生成的Region边界切分成多个HFile文件,保障每个HFile都能与指标表以后的Region绝对应。但这个过程须要读取HFile内容,因此并不高效。须要尽量减少HFile生成阶段和HFile导入阶段的提早,最好可能在HFile生成之后立即执行HFile导入。 基于BulkLoad两阶段的工作原理,BulkLoad的外围流程如图所示。 BulkLoad根底案例 在hbase上创立一张表:create 'test_log','ext' 执行BulkLoad代码: import org.apache.hadoop.hbase.client.ConnectionFactoryimport org.apache.hadoop.hbase.{HBaseConfiguration, KeyValue, TableName}import org.apache.hadoop.hbase.io.ImmutableBytesWritableimport org.apache.hadoop.hbase.mapreduce.{HFileOutputFormat2, LoadIncrementalHFiles}import org.apache.hadoop.hbase.util.Bytesimport org.apache.spark.SparkConfimport org.apache.spark.sql.SparkSessionobject BulkLoad1 { def main(args: Array[String]): Unit = { val sparkConf = new SparkConf().setAppName("HbaseBulkLoad") val spark = SparkSession.builder .config(sparkConf) .getOrCreate() val sc = spark.sparkContext val datas = List( ("abc", ("ext", "type", "login")), ("ccc", ("ext", "type", "logout")) ) val dataRdd = sc.parallelize(datas) val output = dataRdd.map { x => { val rowKey = Bytes.toBytes(x._1) val immutableRowKey = new ImmutableBytesWritable(rowKey) val colFam = x._2._1 val colName = x._2._2 val colValue = x._2._3 val kv = new KeyValue( rowKey, Bytes.toBytes(colFam), Bytes.toBytes(colName), Bytes.toBytes(colValue.toString) ) (immutableRowKey, kv) } } val hConf = HBaseConfiguration.create() hConf.addResource("hbase_site.xml") val hTableName = "test_log" hConf.set("hbase.mapreduce.hfileoutputformat.table.name",hTableName) val tableName = TableName.valueOf(hTableName) val conn = ConnectionFactory.createConnection(hConf) val table = conn.getTable(tableName) val regionLocator = conn.getRegionLocator(tableName) val hFileOutput = "/tmp/h_file" output.saveAsNewAPIHadoopFile(hFileOutput, classOf[ImmutableBytesWritable], classOf[KeyValue], classOf[HFileOutputFormat2], hConf) val bulkLoader = new LoadIncrementalHFiles(hConf) bulkLoader.doBulkLoad(new Path(hFileOutput),conn.getAdmin,table,regionLocator) }}提交spark执行: ...

July 29, 2020 · 1 min · jiezi

关于hbase:HBase原理HBase写入流程

HBase采纳LSM树架构,天生实用于写多读少的利用场景。在实在生产线环境中,也正是因为HBase集群杰出的写入能力,能力反对当下很多数据激增的业务。须要阐明的是,HBase服务端并没有提供update、delete接口,HBase中对数据的更新、删除操作在服务器端也认为是写入操作,不同的是,更新操作会写入一个最新版本数据,删除操作会写入一条标记为deleted的KV数据。所以HBase中更新、删除操作的流程与写入流程完全一致。当然,HBase数据写入的整个流程随着版本的迭代在一直优化,但总体流程变动不大。 写入流程的三个阶段 从整体架构的视角来看,写入流程能够概括为三个阶段。 1)客户端解决阶段:客户端将用户的写入申请进行预处理,并依据集群元数据定位写入数据所在的RegionServer,将申请发送给对应的RegionServer。 2)Region写入阶段:RegionServer接管到写入申请之后将数据解析进去,首先写入WAL,再写入对应Region列簇的MemStore。 3)MemStore Flush阶段:当Region中MemStore容量超过肯定阈值,零碎会异步执行f lush操作,将内存中的数据写入文件,造成HFile。 用户写入申请在实现Region MemStore的写入之后就会返回胜利。MemStoreFlush是一个异步执行的过程。 1. 客户端解决阶段HBase客户端解决写入申请的外围流程基本上能够概括为三步。 步骤1:用户提交put申请后,HBase客户端会将写入的数据增加到本地缓冲区中,合乎肯定条件就会通过AsyncProcess异步批量提交。HBase默认设置autoflush=true,示意put申请间接会提交给服务器进行解决;用户能够设置autoflush=false,这样,put申请会首先放到本地缓冲区,等到本地缓冲区大小超过肯定阈值(默认为2M,能够通过配置文件配置)之后才会提交。很显然,后者应用批量提交申请,能够极大地晋升写入吞吐量,然而因为没有爱护机制,如果客户端解体,会导致局部曾经提交的数据失落。 步骤2:在提交之前,HBase会在元数据表hbase:meta中依据rowkey找到它们归属的RegionServer,这个定位的过程是通过HConnection的locateRegion办法实现的。如果是批量申请,还会把这些rowkey依照HRegionLocation分组,不同分组的申请意味着发送到不同的RegionServer,因而每个分组对应一次RPC申请。 Client与ZooKeeper、RegionServer的交互过程如图所示。 •客户端依据写入的表以及rowkey在元数据缓存中查找,如果可能查找出该rowkey所在的RegionServer以及Region,就能够间接发送写入申请(携带Region信息)到指标RegionServer。 •如果客户端缓存中没有查到对应的rowkey信息,须要首先到ZooKeeper上/hbase-root/meta-region-server节点查找HBase元数据表所在的RegionServer。向hbase:meta所在的RegionServer发送查问申请,在元数据表中查找rowkey所在的RegionServer以及Region信息。客户端接管到返回后果之后会将后果缓存到本地,以备下次应用。 •客户端依据rowkey相干元数据信息将写入申请发送给指标RegionServer,Region Server接管到申请之后会解析出具体的Region信息,查到对应的Region对象,并将数据写入指标Region的MemStore中。 步骤3:HBase会为每个HRegionLocation结构一个近程RPC申请MultiServerCallable,并通过rpcCallerFactory. newCaller()执行调用。将申请通过Protobuf序列化后发送给对应的RegionServer。 2. Region写入阶段 服务器端RegionServer接管到客户端的写入申请后,首先会反序列化为put对象,而后执行各种查看操作,比方查看Region是否是只读、MemStore大小是否超过blockingMemstoreSize等。查看实现之后,执行一系列外围操作 Region写入流程 1)Acquire locks :HBase中应用行锁保障对同一行数据的更新都是互斥操作,用以保障更新的原子性,要么更新胜利,要么更新失败。 2)Update LATEST_TIMESTAMP timestamps :更新所有待写入(更新)KeyValue的工夫戳为以后零碎工夫。 3)Build WAL edit :HBase应用WAL机制保证数据可靠性,即首先写日志再写缓存,即便产生宕机,也能够通过复原HLog还原出原始数据。该步骤就是在内存中构建WALEdit对象,为了保障Region级别事务的写入原子性,一次写入操作中所有KeyValue会构建成一条WALEdit记录。 4)Append WALEdit To WAL :将步骤3中结构在内存中的WALEdit记录程序写入HLog中,此时不须要执行sync操作。以后版本的HBase应用了disruptor实现了高效的生产者消费者队列,来实现WAL的追加写入操作。 5)Write back to MemStore:写入WAL之后再将数据写入MemStore。 6)Release row locks:开释行锁。 7)Sync wal :HLog真正sync到HDFS,在开释行锁之后执行sync操作是为了尽量减少持锁工夫,晋升写性能。如果sync失败,执行回滚操作将MemStore中曾经写入的数据移除。 8)完结写事务:此时该线程的更新操作才会对其余读申请可见,更新才理论失效。 3. MemStore Flush阶段 随着数据的一直写入,MemStore中存储的数据会越来越多,零碎为了将应用的内存放弃在一个正当的程度,会将MemStore中的数据写入文件造成HFile。f lush阶段是HBase的十分外围的阶段,实践上须要重点关注三个问题: •MemStore Flush的触发机会。即在哪些状况下HBase会触发f lush操作。 •MemStore Flush的整体流程。 •HFile的构建流程。HFile构建是MemStore Flush整体流程中最重要的一个局部,这部分内容会波及HFile文件格式的构建、布隆过滤器的构建、HFile索引的构建以及相干元数据的构建等。 Region写入流程数据写入Region的流程能够形象为两步:追加写入HLog,随机写入MemStore。 1. 追加写入HLog ...

July 29, 2020 · 2 min · jiezi

关于hbase:HBase原理RegionServer核心组件之BlockCache

家喻户晓,晋升数据库读取性能的一个外围办法是,尽可能将热点数据存储到内存中,以防止低廉的IO开销。古代零碎架构中,诸如Redis这类缓存组件曾经是体系中的外围组件,通常将其部署在数据库的下层,拦挡零碎的大部分申请,保障数据库的“平安”,晋升整个零碎的读取效率。 同样为了晋升读取性能,HBase也实现了一种读缓存构造——BlockCache。客户端读取某个Block,首先会查看该Block是否存在于Block Cache,如果存在就间接加载进去,如果不存在则去HFile文件中加载,加载进去之后放到Block Cache中,后续同一申请或者邻近数据查找申请能够间接从内存中获取,以防止低廉的IO操作。 从字面意思能够看进去,BlockCache次要用来缓存Block。须要关注的是,Block是HBase中最小的数据读取单元,即数据从HFile中读取都是以Block为最小单元执行的。 BlockCache是RegionServer级别的,一个RegionServer只有一个BlockCache,在RegionServer启动时实现BlockCache的初始化工作。到目前为止,HBase先后实现了3种BlockCache计划,LRUBlockCache是最早的实现计划,也是默认的实现计划;HBase 0.92版本实现了第二种计划SlabCache,参见HBASE-4027;HBase 0.96之后官网提供了另一种可选计划BucketCache,参见HBASE-7404。 这3种计划的不同之处次要在于内存管理模式,其中LRUBlockCache是将所有数据都放入JVM Heap中,交给JVM进行治理。而后两种计划采纳的机制容许将局部数据存储在堆外。这种演变实质上是因为LRUBlockCache计划中JVM垃圾回收机制常常导致程序长时间暂停,而采纳堆外内存对数据进行治理能够无效缓解零碎长时间GC。 LRUBlockCacheLRUBlockCache是HBase目前默认的BlockCache机制,实现绝对比较简单。它应用一个ConcurrentHashMap治理BlockKey到Block的映射关系,缓存Block只须要将BlockKey和对应的Block放入该HashMap中,查问缓存就依据BlockKey从HashMap中获取即可。同时,该计划采纳严格的LRU淘汰算法,当Block Cache总量达到肯定阈值之后就会启动淘汰机制,最近起码应用的Block会被置换进去。在具体的实现细节方面,须要关注以下三点。 1.缓存分层策略 HBase采纳了缓存分层设计,将整个BlockCache分为三个局部:single-access、multi-access和in-memory,别离占到整个BlockCache大小的25%、50%、25%。 在一次随机读中,一个Block从HDFS中加载进去之后首先放入single-access区,后续如果有屡次申请拜访到这个Block,就会将这个Block移到multi-access区。而in-memory区示意数据能够常驻内存,个别用来寄存拜访频繁、量小的数据,比方元数据,用户能够在建表的时候设置列簇属性IN_MEMORY=true,设置之后该列簇的Block在从磁盘中加载进去之后会间接放入in-memory区。 须要留神的是,设置IN_MEMORY=true并不意味着数据在写入时就会被放到in-memory区,而是和其余BlockCache区一样,只有从磁盘中加载出Block之后才会放入该区。另外,进入in-memory区的Block并不意味着会始终存在于该区,仍会基于LRU淘汰算法在空间有余的状况下淘汰最近最不沉闷的一些Block。 因为HBase零碎元数据(hbase:meta,hbase:namespace等表)都寄存在in-memory区,因而对于很多业务表来说,设置数据属性IN_MEMORY=true时须要十分审慎,肯定要确保此列簇数据量很小且拜访频繁,否则可能会将hbase:meta等元数据挤出内存,重大影响所有业务性能。 2. LRU淘汰算法实现在每次cache block时,零碎将BlockKey和Block放入HashMap后都会查看BlockCache总量是否达到阈值,如果达到阈值,就会唤醒淘汰线程对Map中的Block进行淘汰。零碎设置3个MinMaxPriorityQueue,别离对应上述3个分层,每个队列中的元素依照最近起码被应用的规定排列,零碎会优先取出最近起码应用的Block,将其对应的内存开释。可见,3个分层中的Block会别离执行LRU淘汰算法进行淘汰。 3. LRUBlockCache计划优缺点LRUBlockCache计划应用JVM提供的HashMap治理缓存,简略无效。但随着数据从single-access区降职到multi-access区或长时间停留在single-access区,对应的内存对象会从young区降职到old区,降职到old区的Block被淘汰后会变为内存垃圾,最终由CMS回收(Conccurent Mark Sweep,一种标记革除算法),显然这种算法会带来大量的内存碎片,碎片空间始终累计就会产生臭名远扬的FullGC。尤其在大内存条件下,一次Full GC很可能会继续较长时间,甚至达到分钟级别。Full GC会将整个过程暂停,称为stop-the-world暂停(STW),因而长时间Full GC必然会极大影响业务的失常读写申请。正因为该计划有这样的弊病,之后相继呈现了SlabCache计划和BucketCache计划。 SlabCache为了解决LRUBlockCache计划中因JVM垃圾回收导致的服务中断问题,SlabCache计划提出应用Java NIO DirectByteBuffer技术实现堆外内存存储,不再由JVM治理数据内存。默认状况下,零碎在初始化的时候会调配两个缓存区,别离占整个BlockCache大小的80%和20%,每个缓存区别离存储固定大小的Block,其中前者次要存储小于等于64K的Block,后者存储小于等于128K的Block,如果一个Block太大就会导致两个区都无奈缓存。和LRUBlockCache雷同,SlabCache也应用Least-Recently-Used算法淘汰过期的Block。和LRUBlockCache不同的是,SlabCache淘汰Block时只须要将对应的BufferByte标记为闲暇,后续cache对其上的内存间接进行笼罩即可。 线上集群环境中,不同表不同列簇设置的BlockSize都可能不同,很显然,默认只能存储小于等于128KB Block的SlabCache计划不能满足局部用户场景。比方,用户设置BlockSize=256K,简略应用SlabCache计划就不能达到缓存这部分Block的目标。因而HBase在理论实现中将SlabCache和LRUBlockCache搭配应用,称为DoubleBlockCache。在一次随机读中,一个Block从HDFS中加载进去之后会在两个Cache中别离存储一份。缓存读时首先在LRUBlockCache中查找,如果CacheMiss再在SlabCache中查找,此时如果命中,则将该Block放入LRUBlockCache中。 通过理论测试,DoubleBlockCache计划有很多弊病。比方,SlabCache中固定大小内存设置会导致理论内存使用率比拟低,而且应用LRUBlockCache缓存Block仍然会因为JVM GC产生大量内存碎片。因而在HBase 0.98版本之后,曾经不倡议应用该计划。 BucketCacheSlabCache计划在理论利用中并没有很大水平改善原有LRUBlockCache计划的GC弊病,还额定引入了诸如堆外内存使用率低的缺点。然而它的设计并不是一无是处,至多在应用堆外内存这方面给予了后续开发者很多启发。站在SlabCache的肩膀上,社区工程师设计开发了另一种十分高效的缓存计划——BucketCache。 BucketCache通过不同配置形式能够工作在三种模式下:heap,offheap和f ile。heap模式示意这些Bucket是从JVM Heap中申请的;offheap模式应用DirectByteBuffer技术实现堆外内存存储管理;f ile模式应用相似SSD的存储介质来缓存Data Block。无论工作在哪种模式下,BucketCache都会申请许多带有固定大小标签的Bucket,和SlabCache一样,一种Bucket存储一种指定BlockSize的Data Block,但和SlabCache不同的是,BucketCache会在初始化的时候申请14种不同大小的Bucket,而且如果某一种Bucket空间有余,零碎会从其余Bucket空间借用内存应用,因而不会呈现内存使用率低的状况。 理论实现中,HBase将BucketCache和LRUBlockCache搭配应用,称为CombinedBlock-Cache。和DoubleBlockCache不同,零碎在LRUBlockCache中次要存储Index Block和Bloom Block,而将Data Block存储在BucketCache中。因而一次随机读须要先在LRUBlockCache中查到对应的Index Block,而后再到BucketCache查找对应Data Block。BucketCache通过更加正当的设计修改了SlabCache的弊病,极大升高了JVM GC对业务申请的理论影响,但其也存在一些问题。比方,应用堆外内存会存在拷贝内存的问题,在肯定水平上会影响读写性能。当然,在之后的2.0版本中这个问题失去了解决,参见HBASE-11425。 相比LRUBlockCache,BucketCache实现绝对比较复杂。它没有应用JVM内存治理算法来治理缓存,而是本人对内存进行治理,因而大大降低了因为呈现大量内存碎片导致Full GC产生的危险。鉴于生产线上CombinedBlockCache计划应用的普遍性,下文次要介绍BucketCache的具体实现形式(包含BucketCache的内存组织模式、缓存写入读取流程等)以及配置应用形式。 1. BucketCache的内存组织模式 下图所示为BucketCache的内存组织模式,图中上半局部是逻辑组织构造,下半局部是对应的物理组织构造。HBase启动之后会在内存中申请大量的Bucket,每个Bucket的大小默认为2MB。每个Bucket会有一个baseoffset变量和一个size标签,其中baseoffset变量示意这个Bucket在理论物理空间中的起始地址,因而Block的物理地址就能够通过baseoffset和该Block在Bucket的偏移量惟一确定;size标签示意这个Bucket能够寄存的Block大小,比方图中左侧Bucket的size标签为65KB,示意能够寄存64KB的Block,右侧Bucket的size标签为129KB,示意能够寄存128KB的Block。 HBase中应用BucketAllocator类实现对Bucket的组织治理。 1)HBase会依据每个Bucket的size标签对Bucket进行分类,雷同size标签的Bucket由同一个BucketSizeInfo治理,如上图所示,左侧寄存64KB Block的Bucket由65KB BucketSizeInfo治理,右侧寄存128KB Block的Bucket由129KBBucketSizeInfo治理。可见,BucketSize大小总会比Block自身大1KB,这是因为Block自身并不是严格固定大小的,总会大那么一点,比方64K的Block总是会比64K大一些。 2)HBase在启动的时候就决定了size标签的分类,默认标签有(4+1)K,(8+1)K,(16+1)K...(48+1)K,(56+1)K,(64+1)K,(96+1)K...(512+1)K。而且零碎会首先从小到大遍历一次所有size标签,为每种size标签调配一个Bucket,最初所有残余的Bucket都调配最大的size标签,默认调配 (512+1)K,如下图所示。 3)Bucket的size标签能够动静调整,比方64K的Block数目比拟多,65K的Bucket用完了当前,其余size标签的齐全闲暇的Bucket能够转换成为65K的Bucket,然而会至多保留一个该size的Bucket。 2. BucketCache中Block缓存写入、读取流程 ...

July 28, 2020 · 1 min · jiezi

关于hbase:HBase原理RegionServer核心组件之HFile

MemStore中数据落盘之后会造成一个文件写入HDFS,这个文件称为HFile。HFile参考BigTable的SSTable和Hadoop的TFile实现。从HBase诞生到当初,HFile经验了3个版本,其中V2在0.92引入,V3在0.98引入。HFile V1版本在理论应用过程中发现占用内存过多,HFile V2版本针对此问题进行了优化,HFile V3版本和V2版本基本相同,只是在cell层面增加了对Tag数组的反对。鉴于此,本文次要针对V2版本进行剖析,对V1和V3版本感兴趣的读者能够参考社区官网文档。 HFile逻辑构造HFile V2的逻辑构造如图所示 HFile文件次要分为4个局部:Scanned block局部、Non-scanned block局部、Load-on-open局部和Trailer。 •Scanned Block局部:顾名思义,示意程序扫描HFile时所有的数据块将会被读取。这个局部蕴含3种数据块:Data Block,Leaf Index Block以及BloomBlock。其中Data Block中存储用户的KeyValue数据,Leaf Index Block中存储索引树的叶子节点数据,Bloom Block中存储布隆过滤器相干数据。 •Non-scanned Block局部:示意在HFile程序扫描的时候数据不会被读取,次要包含Meta Block和Intermediate Level Data Index Blocks两局部。 •Load-on-open局部:这部分数据会在RegionServer关上HFile时间接加载到内存中,包含FileInfo、布隆过滤器MetaBlock、Root Data Index和MetaIndexBlock。 •Trailer局部:这部分次要记录了HFile的版本信息、其余各个局部的偏移值和寻址信息。 HFile物理构造HFile物理构造如图所示。实际上,HFile文件由各种不同类型的Block(数据块)形成,尽管这些Block的类型不同,但却领有雷同的数据结构。 Block的大小能够在创立表列簇的时候通过参数blocksize=> '65535'指定,默认为64K。通常来讲,大号的Block有利于大规模的程序扫描,而小号的Block更有利于随机查问。因而用户在设置blocksize时须要依据业务查问特色进行衡量,默认64K是一个绝对折中的大小。 HFile中所有Block都领有雷同的数据结构,HBase将所有Block对立形象为HFile-Block。HFileBlock反对两种类型,一种类型含有checksum,另一种不含有checksum。为不便解说,本节所有HFileBlock都选用不含有checksum的HFileBlock。HFileBlock构造如图所示。 HFileBlock次要蕴含两局部:BlockHeader和BlockData。其中BlockHeader次要存储Block相干元数据,BlockData用来存储具体数据。Block元数据中最外围的字段是BlockType字段,示意该Block的类型,HBase中定义了8种BlockType,每种BlockType对应的Block都存储不同的内容,有的存储用户数据,有的存储索引数据,有的存储元数据(meta)。对于任意一种类型的HFileBlock,都领有雷同构造的BlockHeader,然而BlockData构造却不尽相同。下表列举了最外围的几种BlockType。 HFile的根底Block1. Trailer Block Trailer Block次要记录了HFile的版本信息、各个局部的偏移值和寻址信息,图为Trailer Block的数据结构,其中只显示了局部外围字段。 RegionServer在关上HFile时会加载所有HFile的Trailer局部以及load-on-open局部到内存中。理论加载过程会首先会解析Trailer Block,而后再进一步加载load-on-open局部的数据,具体步骤如下: 1)加载HFile version版本信息,HBase中version蕴含majorVersion和minorVersion两局部,前者决定了HFile的主版本——V1、V2还是V3;后者在主版本确定的根底上决定是否反对一些渺小修改,比方是否反对checksum等。不同的版本应用不同的文件解析器对HFile进行读取解析。 2)HBase会依据version信息计算Trailer Block的大小(不同version的TrailerBlock大小不同),再依据Trailer Block大小加载整个HFileTrailer Block到内存中。Trailer Block中蕴含很多统计字段,例如,TotalUncompressedBytes示意HFile中所有未压缩的KeyValue总大小。NumEntries示意HFile中所有KeyValue总数目。Block中字段CompressionCodec示意该HFile所应用的压缩算法,HBase中压缩算法次要有lzo、gz、snappy、lz4等,默认为none,示意不应用压缩。 3)Trailer Block中另两个重要的字段是LoadOnOpenDataOffset和LoadOnOpenDataSize,前者示意load-on-open Section在整个HFile文件中的偏移量,后者示意load-on-open Section的大小。依据此偏移量以及大小,HBase会在启动后将load-on-open Section的数据全副加载到内存中。load-on-open局部次要包含FileInfo模块、Root Data Index模块以及布隆过滤器Metadata模块,FileInfo是固定长度的数据块,次要记录了文件的一些统计元信息,比拟重要的是AVG_KEY_LEN和AVG_VALUE_LEN,别离记录了该文件中所有Key和Value的均匀长度。Root Data Index示意该文件数据索引的根节点信息,布隆过滤器Metadata记录了HFile中布隆过滤器的相干元数据。 2. Data BlockData Block是HBase中文件读取的最小单元。Data Block中次要存储用户的KeyValue数据,而KeyValue构造是HBase存储的外围。HBase中所有数据都是以KeyValue构造存储在HBase中。 内存和磁盘中的Data Block构造如图所示。 ...

July 28, 2020 · 2 min · jiezi

关于hbase:HBase原理RegionServer核心组件之MemStore

HBase零碎中一张表会被程度切分成多个Region,每个Region负责本人区域的数据读写申请。程度切分意味着每个Region会蕴含所有的列簇数据,HBase将不同列簇的数据存储在不同的Store中,每个Store由一个MemStore和一系列HFile组成,如图所示。 Region构造组成 HBase基于LSM树模型实现,所有的数据写入操作首先会程序写入日志HLog,再写入MemStore,当MemStore中数据大小超过阈值之后再将这些数据批量写入磁盘,生成一个新的HFile文件。LSM树架构有如下几个非常明显的劣势: •这种写入形式将一次随机IO写入转换成一个程序IO写入(HLog程序写入)加上一次内存写入(MemStore写入),使得写入性能失去极大晋升。大数据畛域中对写入性能有较高要求的数据库系统简直都会采纳这种写入模型,比方分布式列式存储系统Kudu、工夫序列存储系统Druid等。 •HFile中KeyValue数据须要依照Key排序,排序之后能够在文件级别依据有序的Key建设索引树,极大晋升数据读取效率。然而HDFS自身只容许程序读写,不能更新,因而须要数据在落盘生成HFile之前就实现排序工作,MemStore就是KeyValue数据排序的理论执行者。 •MemStore作为一个缓存级的存储组件,总是缓存着最近写入的数据。对于很多业务来说,最新写入的数据被读取的概率会更大,最典型的比方时序数据,80%的申请都会落到最近一天的数据上。实际上对于某些场景,新写入的数据存储在MemStore对读取性能的晋升至关重要。 •在数据写入HFile之前,能够在内存中对KeyValue数据进行很多更高级的优化。比方,如果业务数据保留版本仅设置为1,在业务更新比拟频繁的场景下,MemStore中可能会存储某些数据的多个版本。这样,MemStore在将数据写入HFile之前实际上能够抛弃老版本数据,仅保留最新版本数据。 MemStore内部结构下面讲到写入(包含更新删除操作)HBase中的数据都会首先写入MemStore,除此之外,MemStore还要承当业务多线程并发拜访的职责。那么一个很事实的问题就是,MemStore应该采纳什么样的数据结构,既可能保障高效的写入效率,又可能保障高效的多线程读取效率? 理论实现中,HBase采纳了跳跃表这种数据结构,当然,HBase并没有间接应用原始跳跃表,而是应用了JDK自带的数据结构ConcurrentSkipListMap。ConcurrentSkipListMap底层应用跳跃表来保证数据的有序性,并保证数据的写入、查找、删除操作都能够在O(logN)的工夫复杂度实现。除此之外,ConcurrentSkipListMap有个十分重要的特点是线程平安,它在底层采纳了CAS原子性操作,防止了多线程拜访条件下低廉的锁开销,极大地晋升了多线程拜访场景下的读写性能。 MemStore由两个ConcurrentSkipListMap(称为A和B)实现,写入操作(包含更新删除操作)会将数据写入ConcurrentSkipListMap A,当ConcurrentSkipListMap A中数据量超过肯定阈值之后会创立一个新的ConcurrentSkipListMap B来接管用户新的申请,之前曾经写满的ConcurrentSkipListMap A会执行异步f lush操作落盘造成HFile。 MemStore的GC问题MemStore从实质上来看就是一块缓存,能够称为写缓存。家喻户晓在Java零碎中,大内存零碎总会面临GC问题,MemStore自身会占用大量内存,因而GC的问题不可避免。不仅如此,HBase中MemStore工作模式的特殊性更会引起重大的内存碎片,存在大量内存碎片会导致系统看起来仿佛还有很多空间,但实际上这些空间都是一些十分小的碎片,曾经调配不出一块残缺的可用内存,这时会触发长时间的Full GC。 为什么MemStore的工作模式会引起重大的内存碎片?这是因为一个RegionServer由多个Region形成,每个Region依据列簇的不同又蕴含多个MemStore,这些MemStore都是共享内存的。这样,不同Region的数据写入对应的MemStore,因为共享内存,在JVM看来所有MemStore的数据都是混合在一起写入Heap的。此时如果Region1上对应的所有MemStore执行落盘操作,就会呈现图所示场景。 MemStore f lush产生内存条带 上图中不同Region由不同色彩示意,左边图为JVM中MemStore所占用的内存图,可见不同Region的数据在JVM Heap中是混合存储的,一旦深灰色条带示意的Region1的所有MemStore数据执行f lush操作,这些深灰色条带所占内存就会被开释,变成红色条带。这些红色条带会持续为写入MemStore的数据调配空间,进而会宰割成更小的条带。从JVM全局的视角来看,随着MemStore中数据的一直写入并且f lush,整个JVM将会产生大量越来越小的内存条带,这些条带实际上就是内存碎片。随着内存碎片越来越小,最初甚至调配不进去足够大的内存给写入的对象,此时就会触发JVM执行Full GC合并这些内存碎片。 MSLAB内存治理形式为了优化这种内存碎片可能导致的Full GC,HBase借鉴了线程本地调配缓存(Thread-Local Allocation Buffer,TLAB)的内存治理形式,通过程序化分配内存、内存数据分块等个性使得内存碎片更加粗粒度,无效改善Full GC状况。具体实现步骤如下: 1)每个MemStore会实例化失去一个MemStoreLAB对象。 2)MemStoreLAB会申请一个2M大小的Chunk数组,同时保护一个Chunk偏移量,该偏移量初始值为0。 3)当一个KeyValue值插入MemStore后,MemStoreLAB会首先通过KeyValue.getBuffer()获得data数组,并将data数组复制到Chunk数组中,之后再将Chunk偏移量往前挪动data. length。 4)以后Chunk满了之后,再调用new byte[2 1024 1024]申请一个新的Chunk。 这种内存治理形式称为MemStore本地调配缓存(MemStore-Local AllocationBuffer,MSLAB)。下图是针对MSLAB的一个简略示意图,右侧为JVM中MemStore所占用的内存图,和优化前不同的是,不同色彩的细条带会汇集在一起造成了2M大小的粗条带。这是因为MemStore会在将数据写入内存时首先申请2M的Chunk,再将理论数据写入申请的Chunk中。这种内存治理形式,使得f lush之后残留的内存碎片更加粗粒度,极大升高Full GC的触发频率。 MemStore Chunk Pool通过MSLAB优化之后,零碎因为MemStore内存碎片触发的Full GC次数会明显降低。然而这样的内存管理模式并不完满,还存在一些“小问题”。比方一旦一个Chunk写满之后,零碎会从新申请一个新的Chunk,新建Chunk对象会在JVM新生代申请新内存,如果申请比拟频繁会导致JVM新生代Eden区满掉,触发YGC。试想如果这些Chunk可能被循环利用,零碎就不须要申请新的Chunk,这样就会使得YGC频率升高,降职到老年代的Chunk就会缩小,CMS GC产生的频率也会升高。这就是MemStore Chunk Pool的核心思想,具体实现步骤如下: 1)零碎创立一个Chunk Pool来治理所有未被援用的Chunk,这些Chunk就不会再被JVM当作垃圾回收。2)如果一个Chunk没有再被援用,将其放入Chunk Pool。3)如果以后Chunk Pool曾经达到了容量最大值,就不会再接收新的Chunk。4)如果须要申请新的Chunk来存储KeyValue,首先从Chunk Pool中获取,如果可能获取失去就反复利用,否则就从新申请一个新的Chunk。 MSLAB相干配置HBase中MSLAB性能默认是开启的,默认的ChunkSize是2M,也能够通过参数"hbase.hregion.memstore.mslab.chunksize"进行设置,倡议放弃默认值。Chunk Pool性能默认是敞开的,须要配置参数"hbase.hregion.memstore.chunkpool.maxsize"为大于0的值能力开启,该值默认是0。"hbase.hregion.memstore.chunkpool.maxsize"取值为[0, 1],示意整个MemStore调配给Chunk Pool的总大小为hbase.hregion.memstore.chunkpool. maxsize * Memstore Size。另一个相干参数"hbase.hregion.memstore.chunkpool.initialsize"取值为[0, 1],示意初始化时申请多少个Chunk放到Pool外面,默认是0,示意初始化时不申请内存。 ...

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理RegionServer核心组件之MemStore

HBase零碎中一张表会被程度切分成多个Region,每个Region负责本人区域的数据读写申请。程度切分意味着每个Region会蕴含所有的列簇数据,HBase将不同列簇的数据存储在不同的Store中,每个Store由一个MemStore和一系列HFile组成,如图所示。 Region构造组成 HBase基于LSM树模型实现,所有的数据写入操作首先会程序写入日志HLog,再写入MemStore,当MemStore中数据大小超过阈值之后再将这些数据批量写入磁盘,生成一个新的HFile文件。LSM树架构有如下几个非常明显的劣势: •这种写入形式将一次随机IO写入转换成一个程序IO写入(HLog程序写入)加上一次内存写入(MemStore写入),使得写入性能失去极大晋升。大数据畛域中对写入性能有较高要求的数据库系统简直都会采纳这种写入模型,比方分布式列式存储系统Kudu、工夫序列存储系统Druid等。 •HFile中KeyValue数据须要依照Key排序,排序之后能够在文件级别依据有序的Key建设索引树,极大晋升数据读取效率。然而HDFS自身只容许程序读写,不能更新,因而须要数据在落盘生成HFile之前就实现排序工作,MemStore就是KeyValue数据排序的理论执行者。 •MemStore作为一个缓存级的存储组件,总是缓存着最近写入的数据。对于很多业务来说,最新写入的数据被读取的概率会更大,最典型的比方时序数据,80%的申请都会落到最近一天的数据上。实际上对于某些场景,新写入的数据存储在MemStore对读取性能的晋升至关重要。 •在数据写入HFile之前,能够在内存中对KeyValue数据进行很多更高级的优化。比方,如果业务数据保留版本仅设置为1,在业务更新比拟频繁的场景下,MemStore中可能会存储某些数据的多个版本。这样,MemStore在将数据写入HFile之前实际上能够抛弃老版本数据,仅保留最新版本数据。 MemStore内部结构下面讲到写入(包含更新删除操作)HBase中的数据都会首先写入MemStore,除此之外,MemStore还要承当业务多线程并发拜访的职责。那么一个很事实的问题就是,MemStore应该采纳什么样的数据结构,既可能保障高效的写入效率,又可能保障高效的多线程读取效率? 理论实现中,HBase采纳了跳跃表这种数据结构,当然,HBase并没有间接应用原始跳跃表,而是应用了JDK自带的数据结构ConcurrentSkipListMap。ConcurrentSkipListMap底层应用跳跃表来保证数据的有序性,并保证数据的写入、查找、删除操作都能够在O(logN)的工夫复杂度实现。除此之外,ConcurrentSkipListMap有个十分重要的特点是线程平安,它在底层采纳了CAS原子性操作,防止了多线程拜访条件下低廉的锁开销,极大地晋升了多线程拜访场景下的读写性能。 MemStore由两个ConcurrentSkipListMap(称为A和B)实现,写入操作(包含更新删除操作)会将数据写入ConcurrentSkipListMap A,当ConcurrentSkipListMap A中数据量超过肯定阈值之后会创立一个新的ConcurrentSkipListMap B来接管用户新的申请,之前曾经写满的ConcurrentSkipListMap A会执行异步f lush操作落盘造成HFile。 MemStore的GC问题MemStore从实质上来看就是一块缓存,能够称为写缓存。家喻户晓在Java零碎中,大内存零碎总会面临GC问题,MemStore自身会占用大量内存,因而GC的问题不可避免。不仅如此,HBase中MemStore工作模式的特殊性更会引起重大的内存碎片,存在大量内存碎片会导致系统看起来仿佛还有很多空间,但实际上这些空间都是一些十分小的碎片,曾经调配不出一块残缺的可用内存,这时会触发长时间的Full GC。 为什么MemStore的工作模式会引起重大的内存碎片?这是因为一个RegionServer由多个Region形成,每个Region依据列簇的不同又蕴含多个MemStore,这些MemStore都是共享内存的。这样,不同Region的数据写入对应的MemStore,因为共享内存,在JVM看来所有MemStore的数据都是混合在一起写入Heap的。此时如果Region1上对应的所有MemStore执行落盘操作,就会呈现图所示场景。 MemStore f lush产生内存条带 上图中不同Region由不同色彩示意,左边图为JVM中MemStore所占用的内存图,可见不同Region的数据在JVM Heap中是混合存储的,一旦深灰色条带示意的Region1的所有MemStore数据执行f lush操作,这些深灰色条带所占内存就会被开释,变成红色条带。这些红色条带会持续为写入MemStore的数据调配空间,进而会宰割成更小的条带。从JVM全局的视角来看,随着MemStore中数据的一直写入并且f lush,整个JVM将会产生大量越来越小的内存条带,这些条带实际上就是内存碎片。随着内存碎片越来越小,最初甚至调配不进去足够大的内存给写入的对象,此时就会触发JVM执行Full GC合并这些内存碎片。 MSLAB内存治理形式为了优化这种内存碎片可能导致的Full GC,HBase借鉴了线程本地调配缓存(Thread-Local Allocation Buffer,TLAB)的内存治理形式,通过程序化分配内存、内存数据分块等个性使得内存碎片更加粗粒度,无效改善Full GC状况。具体实现步骤如下: 1)每个MemStore会实例化失去一个MemStoreLAB对象。 2)MemStoreLAB会申请一个2M大小的Chunk数组,同时保护一个Chunk偏移量,该偏移量初始值为0。 3)当一个KeyValue值插入MemStore后,MemStoreLAB会首先通过KeyValue.getBuffer()获得data数组,并将data数组复制到Chunk数组中,之后再将Chunk偏移量往前挪动data. length。 4)以后Chunk满了之后,再调用new byte[2 1024 1024]申请一个新的Chunk。 这种内存治理形式称为MemStore本地调配缓存(MemStore-Local AllocationBuffer,MSLAB)。下图是针对MSLAB的一个简略示意图,右侧为JVM中MemStore所占用的内存图,和优化前不同的是,不同色彩的细条带会汇集在一起造成了2M大小的粗条带。这是因为MemStore会在将数据写入内存时首先申请2M的Chunk,再将理论数据写入申请的Chunk中。这种内存治理形式,使得f lush之后残留的内存碎片更加粗粒度,极大升高Full GC的触发频率。 MemStore Chunk Pool通过MSLAB优化之后,零碎因为MemStore内存碎片触发的Full GC次数会明显降低。然而这样的内存管理模式并不完满,还存在一些“小问题”。比方一旦一个Chunk写满之后,零碎会从新申请一个新的Chunk,新建Chunk对象会在JVM新生代申请新内存,如果申请比拟频繁会导致JVM新生代Eden区满掉,触发YGC。试想如果这些Chunk可能被循环利用,零碎就不须要申请新的Chunk,这样就会使得YGC频率升高,降职到老年代的Chunk就会缩小,CMS GC产生的频率也会升高。这就是MemStore Chunk Pool的核心思想,具体实现步骤如下: 1)零碎创立一个Chunk Pool来治理所有未被援用的Chunk,这些Chunk就不会再被JVM当作垃圾回收。2)如果一个Chunk没有再被援用,将其放入Chunk Pool。3)如果以后Chunk Pool曾经达到了容量最大值,就不会再接收新的Chunk。4)如果须要申请新的Chunk来存储KeyValue,首先从Chunk Pool中获取,如果可能获取失去就反复利用,否则就从新申请一个新的Chunk。 MSLAB相干配置HBase中MSLAB性能默认是开启的,默认的ChunkSize是2M,也能够通过参数"hbase.hregion.memstore.mslab.chunksize"进行设置,倡议放弃默认值。Chunk Pool性能默认是敞开的,须要配置参数"hbase.hregion.memstore.chunkpool.maxsize"为大于0的值能力开启,该值默认是0。"hbase.hregion.memstore.chunkpool.maxsize"取值为[0, 1],示意整个MemStore调配给Chunk Pool的总大小为hbase.hregion.memstore.chunkpool. maxsize * Memstore Size。另一个相干参数"hbase.hregion.memstore.chunkpool.initialsize"取值为[0, 1],示意初始化时申请多少个Chunk放到Pool外面,默认是0,示意初始化时不申请内存。 ...

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理RegionServer核心组件之HLog

RegionServer是HBase零碎中最外围的组件,次要负责用户数据写入、读取等根底操作。RegionServer组件实际上是一个综合体系,蕴含多个各司其职的外围模块:HLog、MemStore、HFile以及BlockCache。 RegionServer内部结构RegionServer是HBase零碎响应用户读写申请的工作节点组件,由多个外围模块组成,其内部结构如图所示。 一个RegionServer由一个(或多个)HLog、一个BlockCache以及多个Region组成。其中,HLog用来保证数据写入的可靠性;BlockCache能够将数据块缓存在内存中以晋升数据读取性能;Region是HBase中数据表的一个数据分片,一个RegionServer上通常会负责多个Region的数据读写。一个Region由多个Store组成,每个Store寄存对应列簇的数据,比方一个表中有两个列簇,这个表的所有Region就都会蕴含两个Store。每个Store蕴含一个MemStore和多个HFile,用户数据写入时会将对应列簇数据写入相应的MemStore,一旦写入数据的内存大小超过设定阈值,零碎就会将MemStore中的数据落盘造成HFile文件。HFile寄存在HDFS上,是一种定制化格局的数据存储文件,不便用户进行数据读取。 HLogHBase中系统故障复原以及主从复制都基于HLog实现。默认状况下,所有写入操作(写入、更新以及删除)的数据都先以追加模式写入HLog,再写入MemStore。大多数状况下,HLog并不会被读取,但如果RegionServer在某些异常情况下产生宕机,此时曾经写入MemStore中但尚未f lush到磁盘的数据就会失落,须要回放HLog补救失落的数据。此外,HBase主从复制须要主集群将HLog日志发送给从集群,从集群在本地执行回放操作,实现集群之间的数据复制。 HLog文件构造HLog文件的根本构造如图所示。 阐明如下: •每个RegionServer领有一个或多个HLog(默认只有1个,1.1版本能够开启MultiWAL性能,容许多个HLog)。每个HLog是多个Region共享的,图中Region A、Region B和Region C共享一个HLog文件。 •HLog中,日志单元WALEntry(图中小方框)示意一次行级更新的最小追加单元,它由HLogKey和WALEdit两局部组成,其中HLogKey由table name、region name以及sequenceid等字段形成。 WALEdit用来示意一个事务中的更新汇合,在0.94之前的版本中,如果一个事务对一行row R三列c1、c2、c3别离做了批改,那么HLog中会有3个对应的日志片段,如下所示:然而,这种日志构造无奈保障行级事务的原子性,如果RegionServer更新c2列之后产生宕机,那么一行记录中只有局部数据写入胜利。为了解决这样的问题,HBase将一个行级事务的写入操作示意为一条记录,如下所示:其中,WALEdit会被序列化为格局<-1, # of edits, , , >,比方<-1, 3, , , >,-1为标识符,示意这种新的日志构造。 HLog文件存储HBase中所有数据(包含HLog以及用户理论数据)都存储在HDFS的指定目录(假如为hbase-root)下,能够通过hadoop命令查看hbase-root目录下与HLog无关的子目录,如下所示:其中,/hbase/WALs存储以后还未过期的日志;/hbase/oldWALs存储曾经过期的日志。能够进一步查看/hbase/WALs目录下的日志文件,如下所示:/hbase/WALs目录下通常会有多个子目录,每个子目录代表一个对应的RegionServer。以hbase17.xj.bjbj.org,60020,1505980274300为例,hbase17.xj.bjbj.org示意对应的RegionServer域名,60020为端口号,1505980274300为目录生成时的工夫戳。每个子目录下存储该RegionServer内的所有HLog文件,如下所示: HLog文件为: HLog生命周期HLog文件生成之后并不会永恒存储在零碎中,它的使命实现后,文件就会生效最终被删除。HLog整个生命周期如图所示。 HLog生命周期蕴含4个阶段: 1)HLog构建:HBase的任何写入(更新、删除)操作都会先将记录追加写入到HLog文件中。 2)HLog滚动:HBase后盾启动一个线程,每隔一段时间(由参数'hbase.regionserver. logroll.period'决定,默认1小时)进行日志滚动。日志滚动会新建一个新的日志文件,接管新的日志数据。日志滚动机制次要是为了不便过期日志数据可能以文件的模式间接删除。 3)HLog生效:写入数据一旦从MemStore中落盘,对应的日志数据就会生效。为了不便解决,HBase中日志生效删除总是以文件为单位执行。查看某个HLog文件是否生效只需确认该HLog文件中所有日志记录对应的数据是否曾经实现落盘,如果日志中所有日志记录曾经落盘,则能够认为该日志文件生效。一旦日志文件生效,就会从WALs文件夹挪动到oldWALs文件夹。留神此时HLog并没有被零碎删除。 4)HLog删除:Master后盾会启动一个线程,每隔一段时间(参数'hbase.master.cleaner. interval',默认1分钟)查看一次文件夹oldWALs下的所有生效日志文件,确认是否能够删除,确认能够删除之后执行删除操作。确认条件次要有两个: •该HLog文件是否还在参加主从复制。对于应用HLog进行主从复制的业务,须要持续确认是否该HLog还在利用于主从复制。 •该HLog文件是否曾经在OldWALs目录中存在10分钟。为了更加灵便地治理HLog生命周期,零碎提供了参数设置日志文件的TTL(参数'hbase.master.logcleaner.ttl',默认10分钟),默认状况下oldWALs外面的HLog文件最多能够再保留10分钟。 文章基于《HBase原理与实际》一书

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理RegionServer核心组件之HLog

RegionServer是HBase零碎中最外围的组件,次要负责用户数据写入、读取等根底操作。RegionServer组件实际上是一个综合体系,蕴含多个各司其职的外围模块:HLog、MemStore、HFile以及BlockCache。 RegionServer内部结构RegionServer是HBase零碎响应用户读写申请的工作节点组件,由多个外围模块组成,其内部结构如图所示。 一个RegionServer由一个(或多个)HLog、一个BlockCache以及多个Region组成。其中,HLog用来保证数据写入的可靠性;BlockCache能够将数据块缓存在内存中以晋升数据读取性能;Region是HBase中数据表的一个数据分片,一个RegionServer上通常会负责多个Region的数据读写。一个Region由多个Store组成,每个Store寄存对应列簇的数据,比方一个表中有两个列簇,这个表的所有Region就都会蕴含两个Store。每个Store蕴含一个MemStore和多个HFile,用户数据写入时会将对应列簇数据写入相应的MemStore,一旦写入数据的内存大小超过设定阈值,零碎就会将MemStore中的数据落盘造成HFile文件。HFile寄存在HDFS上,是一种定制化格局的数据存储文件,不便用户进行数据读取。 HLogHBase中系统故障复原以及主从复制都基于HLog实现。默认状况下,所有写入操作(写入、更新以及删除)的数据都先以追加模式写入HLog,再写入MemStore。大多数状况下,HLog并不会被读取,但如果RegionServer在某些异常情况下产生宕机,此时曾经写入MemStore中但尚未f lush到磁盘的数据就会失落,须要回放HLog补救失落的数据。此外,HBase主从复制须要主集群将HLog日志发送给从集群,从集群在本地执行回放操作,实现集群之间的数据复制。 HLog文件构造HLog文件的根本构造如图所示。 阐明如下: •每个RegionServer领有一个或多个HLog(默认只有1个,1.1版本能够开启MultiWAL性能,容许多个HLog)。每个HLog是多个Region共享的,图中Region A、Region B和Region C共享一个HLog文件。 •HLog中,日志单元WALEntry(图中小方框)示意一次行级更新的最小追加单元,它由HLogKey和WALEdit两局部组成,其中HLogKey由table name、region name以及sequenceid等字段形成。 WALEdit用来示意一个事务中的更新汇合,在0.94之前的版本中,如果一个事务对一行row R三列c1、c2、c3别离做了批改,那么HLog中会有3个对应的日志片段,如下所示:然而,这种日志构造无奈保障行级事务的原子性,如果RegionServer更新c2列之后产生宕机,那么一行记录中只有局部数据写入胜利。为了解决这样的问题,HBase将一个行级事务的写入操作示意为一条记录,如下所示:其中,WALEdit会被序列化为格局<-1, # of edits, , , >,比方<-1, 3, , , >,-1为标识符,示意这种新的日志构造。 HLog文件存储HBase中所有数据(包含HLog以及用户理论数据)都存储在HDFS的指定目录(假如为hbase-root)下,能够通过hadoop命令查看hbase-root目录下与HLog无关的子目录,如下所示:其中,/hbase/WALs存储以后还未过期的日志;/hbase/oldWALs存储曾经过期的日志。能够进一步查看/hbase/WALs目录下的日志文件,如下所示:/hbase/WALs目录下通常会有多个子目录,每个子目录代表一个对应的RegionServer。以hbase17.xj.bjbj.org,60020,1505980274300为例,hbase17.xj.bjbj.org示意对应的RegionServer域名,60020为端口号,1505980274300为目录生成时的工夫戳。每个子目录下存储该RegionServer内的所有HLog文件,如下所示: HLog文件为: HLog生命周期HLog文件生成之后并不会永恒存储在零碎中,它的使命实现后,文件就会生效最终被删除。HLog整个生命周期如图所示。 HLog生命周期蕴含4个阶段: 1)HLog构建:HBase的任何写入(更新、删除)操作都会先将记录追加写入到HLog文件中。 2)HLog滚动:HBase后盾启动一个线程,每隔一段时间(由参数'hbase.regionserver. logroll.period'决定,默认1小时)进行日志滚动。日志滚动会新建一个新的日志文件,接管新的日志数据。日志滚动机制次要是为了不便过期日志数据可能以文件的模式间接删除。 3)HLog生效:写入数据一旦从MemStore中落盘,对应的日志数据就会生效。为了不便解决,HBase中日志生效删除总是以文件为单位执行。查看某个HLog文件是否生效只需确认该HLog文件中所有日志记录对应的数据是否曾经实现落盘,如果日志中所有日志记录曾经落盘,则能够认为该日志文件生效。一旦日志文件生效,就会从WALs文件夹挪动到oldWALs文件夹。留神此时HLog并没有被零碎删除。 4)HLog删除:Master后盾会启动一个线程,每隔一段时间(参数'hbase.master.cleaner. interval',默认1分钟)查看一次文件夹oldWALs下的所有生效日志文件,确认是否能够删除,确认能够删除之后执行删除操作。确认条件次要有两个: •该HLog文件是否还在参加主从复制。对于应用HLog进行主从复制的业务,须要持续确认是否该HLog还在利用于主从复制。 •该HLog文件是否曾经在OldWALs目录中存在10分钟。为了更加灵便地治理HLog生命周期,零碎提供了参数设置日志文件的TTL(参数'hbase.master.logcleaner.ttl',默认10分钟),默认状况下oldWALs外面的HLog文件最多能够再保留10分钟。 文章基于《HBase原理与实际》一书

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理客户端

HBase提供了面向Java、C/C++、Python等多种语言的客户端。因为HBase自身是Java开发的,所以非Java语言的客户端须要先拜访ThriftServer,而后通过ThriftServer的Java HBase客户端来申请HBase集群。当然,有局部第三方团队实现了其余一些HBase客户端,例如OpenTSDB团队应用的asynchbase和gohbase等,但因为社区客户端和服务端协定在大版本之间可能产生较大不兼容,而第三方开发的客户端个别会落后于社区,因而这里不举荐应用第三方客户端,倡议对立应用HBase社区的客户端。对其余语言的客户端,举荐应用ThriftServer的形式来拜访HBase服务。 另外,HBase也反对Shell交互式客户端。Shell客户端本质是用JRuby(用Java编写的Ruby解释器,不便Ruby脚本跑在JVM虚拟机上)脚本调用官网HBase客户端来实现的。因而,各种客户端的外围实现都在社区Java版本客户端上。本节次要探讨HBase社区Java客户端。 上面咱们通过一个拜访HBase集群的典型示例代码,论述HBase客户端的用法和设计,代码如下所示: public class TestDemo { private static final HBaseTestingUtility TEST_UTIL=new HBaseTestingUtility() ; public static final TableName tableName=TableName.valueOf("t estTable"); public static final byte[] ROW_KEYO=Bytes.toBytes("rowkey 0"); public static final byte[] ROW_KEY1=Bytes.toBytes("rowkey 1"); public static final byte[]FAMILY=Bytes.toBytes("family"); public static final byte[]QUALIFIER=Bytes.toBytes("qualifie r"); public static final byte[] VALUE-Bytes.toBytes("value"); @BeforeClass public static void setUpBeforeClass( throws Exception { TEST_UTIL.startMiniCluster(); } @AfterClass public static void tearDownAfterClass( throws Exception { TEST_UTIL.shutdownMiniCluster(; @Test public void test() throws IOException { Configuration conf=TEST_UTIL.getConfiguration(); try (Connection conn=ConnectionFactory.createConnection(co nf)){ try (Table table=conn.getTable(tableName)){ for (byte[]rowkey : new byte[][]ROW_KEYO,ROW_KEY1 }){ Put put=new Put(rowkey).addColumn(FAMILY,QUALIFIER, VALUE); table.put(put); } Scan scan=new Scan().withStartRow(ROW_KEY1).setLimit (1); try (ResultScanner scanner=table.getScanner(scan)){ List<Cell> cells=new ArrayList<>(); for (Result result : scanner){ cells.addAll(result.listCells(); Assert.assertEquals(cells.size(),1); Cell firstCell=cells.get(O); Assert.assertArrayEquals(CellUtil.cloneRow(firstCel l),ROW_KEY1); Assert.assertArrayEquals(CellUtil.cloneFamily(firstC ell),FAMILY); Assert.assertArrayEquals(CellUtil.cloneQualifier(fir stCel1),QUALIFIER); Assert.assertArrayEquals(CellUtil.cloneValue(firstCe ll),VALUE); } } } } }这个示例是一个拜访HBase的单元测试代码。咱们在类TestDemo初始化前,通过HBase的HBaseTestingUtility工具启动一个运行在本地的Mini HBase集群,最初跑完所有的单元测试样例之后,同样通过HBaseTestingUtility工具清理相干资源,并敞开集群。 ...

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理客户端

HBase提供了面向Java、C/C++、Python等多种语言的客户端。因为HBase自身是Java开发的,所以非Java语言的客户端须要先拜访ThriftServer,而后通过ThriftServer的Java HBase客户端来申请HBase集群。当然,有局部第三方团队实现了其余一些HBase客户端,例如OpenTSDB团队应用的asynchbase和gohbase等,但因为社区客户端和服务端协定在大版本之间可能产生较大不兼容,而第三方开发的客户端个别会落后于社区,因而这里不举荐应用第三方客户端,倡议对立应用HBase社区的客户端。对其余语言的客户端,举荐应用ThriftServer的形式来拜访HBase服务。 另外,HBase也反对Shell交互式客户端。Shell客户端本质是用JRuby(用Java编写的Ruby解释器,不便Ruby脚本跑在JVM虚拟机上)脚本调用官网HBase客户端来实现的。因而,各种客户端的外围实现都在社区Java版本客户端上。本节次要探讨HBase社区Java客户端。 上面咱们通过一个拜访HBase集群的典型示例代码,论述HBase客户端的用法和设计,代码如下所示: public class TestDemo { private static final HBaseTestingUtility TEST_UTIL=new HBaseTestingUtility() ; public static final TableName tableName=TableName.valueOf("t estTable"); public static final byte[] ROW_KEYO=Bytes.toBytes("rowkey 0"); public static final byte[] ROW_KEY1=Bytes.toBytes("rowkey 1"); public static final byte[]FAMILY=Bytes.toBytes("family"); public static final byte[]QUALIFIER=Bytes.toBytes("qualifie r"); public static final byte[] VALUE-Bytes.toBytes("value"); @BeforeClass public static void setUpBeforeClass( throws Exception { TEST_UTIL.startMiniCluster(); } @AfterClass public static void tearDownAfterClass( throws Exception { TEST_UTIL.shutdownMiniCluster(; @Test public void test() throws IOException { Configuration conf=TEST_UTIL.getConfiguration(); try (Connection conn=ConnectionFactory.createConnection(co nf)){ try (Table table=conn.getTable(tableName)){ for (byte[]rowkey : new byte[][]ROW_KEYO,ROW_KEY1 }){ Put put=new Put(rowkey).addColumn(FAMILY,QUALIFIER, VALUE); table.put(put); } Scan scan=new Scan().withStartRow(ROW_KEY1).setLimit (1); try (ResultScanner scanner=table.getScanner(scan)){ List<Cell> cells=new ArrayList<>(); for (Result result : scanner){ cells.addAll(result.listCells(); Assert.assertEquals(cells.size(),1); Cell firstCell=cells.get(O); Assert.assertArrayEquals(CellUtil.cloneRow(firstCel l),ROW_KEY1); Assert.assertArrayEquals(CellUtil.cloneFamily(firstC ell),FAMILY); Assert.assertArrayEquals(CellUtil.cloneQualifier(fir stCel1),QUALIFIER); Assert.assertArrayEquals(CellUtil.cloneValue(firstCe ll),VALUE); } } } } }这个示例是一个拜访HBase的单元测试代码。咱们在类TestDemo初始化前,通过HBase的HBaseTestingUtility工具启动一个运行在本地的Mini HBase集群,最初跑完所有的单元测试样例之后,同样通过HBaseTestingUtility工具清理相干资源,并敞开集群。 ...

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理布隆过滤器

1.案例如何高效判断元素w是否存在于汇合A之中?首先想到的答案是,把汇合A中的元素一个个放到哈希表中,而后在哈希表中查一下w即可。这样的确能够解决小数据量场景下元素存在性断定,但如果A中元素数量微小,甚至数据量远远超过机器内存空间,该如何解决问题呢? 实现一个基于磁盘和内存的哈希索引当然能够解决这个问题。而另一种低成本的形式就是借助布隆过滤器(Bloom Filter)来实现。 布隆过滤器由一个长度为N的01数组array组成。首先将数组array每个元素初始设为0。对汇合A中的每个元素w,做K次哈希,第i次哈希值对N取模失去一个index(i),即index(i)=HASH_i(w)%N,将array数组中的array[index(i)]置为1。最终array变成一个某些元素为1的01数组。 上面举个例子,如图所示,A={x, y, z},N=18,K=3。 初始化array=000000000000000000。对元素x,HASH_0(x)%N=1,HASH_1(x)%N=5,HASH_2(x)%N=13。因而array=010001000000010000。对元素y,HASH_0(y)%N=4,HASH_1(y)%N=11,HASH_2(y)%N=16。因而array=010011000001010010。对元素z,HASH_0(z)%N=3,HASH_1(y)%N=5,HASH_2(y)%N=11。因而array=010111000001010010。最终失去的布隆过滤器串为:010111000001010010。 此时,对于元素w,K次哈希值别离为:HASH_0(w)%N=4HASH_1(w)%N=13HASH_2(w)%N=15能够发现,布隆过滤器串中的第15位为0,因而能够确认w必定不在汇合A中。因为若w在A中,则第15位必然为1。 如果有另外一个元素t,K次哈希值别离为:HASH_0(t)%N=5HASH_1(t)%N=11HASH_2(t)%N=13咱们发现布隆过滤器串中的第5、11、13位都为1,然而却没法必定t肯定在汇合A中。 因而,布隆过滤器串对任意给定元素w,给出的存在性后果为两种: •w可能存在于汇合A中。•w必定不在汇合A中。 当N取K*|A|/ln2时(其中|A|示意汇合A元素个数),能保障最佳的误判率,所谓误判率也就是过滤器断定元素可能在汇合中但理论不在汇合中的占比。 举例来说,若汇合有20个元素,K取3时,则设计一个N=3×20/ln2=87二进制串来保留布隆过滤器比拟适合。 2.算法实现布隆过滤器的代码实现很短,如下所示: public class BloomFilter { private int k; private int bitsPerKey; private int bitLen; private byte[] result; public BloomFilter(int k,int bitsPerKey) { this.k = k; this.bitsPerKey = bitsPerKey; } public byte[] generate(byte[][] keys) { assert keys != null; bitLen=keys.length * bitsPerKey; bitLen=((bitLen+7) / 8) << 3; bitLen=bitLen < 64 ? 64 : bitLen; result = new byte[bitLen >> 3]; for ( int i=0; i < keys.length;i++){ assert keys[i] != null; int h = Bytes.hash(keys[i]); for (int t=0; t < k; t++){ int idx = (h % bitLen + bitLen) % bitLen; result[idx / 8] |= (1 << (idx % 8)); int delta=(h >> 17) | (h << 15); h += delta; } } return result; } public boolean contains(byte[] key) { assert result != null; int h=Bytes.hash(key); for (int t=0; t < k; t++) { int idx = ( h % bitLen + bitLen) % bitLen; if ((result[idx / 8] & (1 << (idx % 8))) == 0) { return false; } int delta=(h >> 17) | (h << 15); h += delta; } return true; }}有两个中央阐明一下: ...

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理LSM树

HBase的一个列簇(Column Family)实质上就是一棵LSM树(Log-StructuredMerge-Tree)。LSM树分为内存局部和磁盘局部。内存局部是一个保护有序数据汇合的数据结构。一般来讲,内存数据结构能够抉择均衡二叉树、红黑树、跳跃表(SkipList)等保护有序集的数据结构,这里因为思考并发性能,HBase抉择了体现更优良的跳跃表。磁盘局部是由一个个独立的文件组成,每一个文件又是由一个个数据块组成。 LSM树实质上和B+树一样,是一种磁盘数据的索引构造。但和B+树不同的是,LSM树的索引对写入申请更敌对。因为无论是何种写入申请,LSM树都会将写入操作解决为一次程序写,而HDFS善于的正是程序写(且HDFS不反对随机写),因而基于HDFS实现的HBase采纳LSM树作为索引是一种很适合的抉择。 LSM树的索引个别由两局部组成,一部分是内存局部,一部分是磁盘局部。内存局部个别采纳跳跃表来保护一个有序的KeyValue汇合。磁盘局部个别由多个外部KeyValue有序的文件组成。 1.KeyValue存储格局一般来说,LSM中存储的是多个KeyValue组成的汇合,每一个KeyValue个别都会用一个字节数组来示意。这里,首先须要来了解KeyValue这个字节数组的设计。 以HBase为例,这个字节数组串设计如图所示。总体来说,字节数组次要分为以下几个字段。其中Rowkey、Family、Qualifier、Timestamp、Type这5个字段组成KeyValue中的key局部。 • keyLen:占用4字节,用来存储KeyValue构造中Key所占用的字节长度。• valueLen:占用4字节,用来存储KeyValue构造中Value所占用的字节长度。• rowkeyLen:占用2字节,用来存储rowkey占用的字节长度。• rowkeyBytes:占用rowkeyLen个字节,用来存储rowkey的二进制内容。• familyLen:占用1字节,用来存储Family占用的字节长度。• familyBytes:占用familyLen字节,用来存储Family的二进制内容。• qualif ierBytes:占用qualif ierLen个字节,用来存储Qualif ier的二进制内 留神,HBase并没有独自调配字节用来存储qualif ierLen,因为能够通过keyLen和其余字段的长度计算出qualif ierLen。代码如下: • timestamp:占用8字节,示意timestamp对应的long值。• type:占用1字节,示意这个KeyValue操作的类型,HBase内有Put、Delete、Delete Column、DeleteFamily,等等。留神,这是一个十分要害的字段,表明了LSM树内存储的不只是数据,而是每一次操作记录。 Value局部间接存储这个KeyValue中Value的二进制内容。所以,字节数组串次要是Key局部的设计。 在比拟这些KeyValue的大小程序时,HBase依照如下形式(伪代码)来确定大小关系:留神,在HBase中,timestamp越大的KeyValue,排序越靠前。因为用户冀望优先读取到那些版本号更新的数据。 下面以HBase为例,剖析了HBase的KeyValue结构设计。通常来说,在LSM树的KeyValue中的Key局部,有3个字段必不可少: Key的二进制内容。 一个示意版本号的64位long值,在HBase中对应timestamp;这个版本号通常示意数据的写入先后顺序,版本号越大的数据,越优先被用户读取。甚至会设计肯定的策略,将那些版本号较小的数据过期淘汰(HBase中有TTL策略)。 type,示意这个KeyValue是Put操作,还是Delete操作,或者是其余写入操作。实质上,LSM树中寄存的并非数据自身,而是操作记录。这对应了LSM树(Log-Structured Merge-Tree)中Log的含意,即操作日志。 2.多路归并先看一个简略的问题:当初有K个文件,其中第i个文件外部存储有Ni个正整数(这些整数在文件内依照从小到大的顺序存储),如何设计一个算法将K个有序文件合并成一个大的有序文件?在排序算法中,有一类排序算法叫做归并排序,外面就有大家熟知的两路归并实现。当初相当于K路归并,因而能够拓展一下,思路相似。对每个文件设计一个指针,取出K个指针中数值最小的一个,而后把最小的那个指针后移,接着持续找K个指针中数值最小的一个,持续后移指针……直到N个文件全副读完为止,如图所示。算法复杂度剖析起来也较为容易,首先用一个最小堆来保护K个指针,每次从堆中取最小值,开销为logK,最多从堆中取次元素。因而最坏复杂度就是 3. LSM树的索引构造一个LSM树的索引次要由两局部形成:内存局部和磁盘局部。内存局部是一个ConcurrentSkipListMap,Key就是后面所说的Key局部,Value是一个字节数组。数据写入时,间接写入MemStore中。随着一直写入,一旦内存占用超过肯定的阈值时,就把内存局部的数据导出,造成一个有序的数据文件,存储在磁盘上。LSM树索引构造如图所示。内存局部导出造成一个有序数据文件的过程称为flush。为了防止f lush影响写入性能,会先把以后写入的MemStore设为Snapshot,不再答应新的写入操作写入这个Snapshot的MemStore。另开一个内存空间作为MemStore,让前面的数据写入。一旦Snapshot的MemStore写入结束,对应内存空间就能够开释。这样,就能够通过两个MemStore来实现稳固的写入性能。 LSM树索引构造 随着写入的减少,内存数据会一直地刷新到磁盘上。最终磁盘上的数据文件会越来越多。如果数据没有任何的读取操作,磁盘上产生很多的数据文件对写入并无影响,而且这时写入速度是最快的,因为所有IO都是程序IO。然而,一旦用户有读取申请,则须要将大量的磁盘文件进行多路归并,之后能力读取到所需的数据。因为须要将那些Key雷同的数据全局综合起来,最终抉择出适合的版本返回给用户,所以磁盘文件数量越多,在读取的时候随机读取的次数也会越多,从而影响读取操作的性能。 为了优化读取操作的性能,咱们能够设置肯定策略将选中的多个hf ile进行多路归并,合并成一个文件。文件个数越少,则读取数据时须要seek操作的次数越少,读取性能则越好。 一般来说,依照选中的文件个数,咱们将compact操作分成两种类型。一种是major compact,是将所有的hf ile一次性多路归并成一个文件。这种形式的益处是,合并之后只有一个文件,这样读取的性能必定是最高的;但它的问题是,合并所有的文件可能须要很长的工夫并耗费大量的IO带宽,所以major compact不宜应用太频繁,适宜周期性地跑。 另外一种是minor compact,即选中少数几个hf ile,将它们多路归并成一个文件。这种形式的长处是,能够进行部分的compact,通过大量的IO缩小文件个数,晋升读取操作的性能,适宜较高频率地跑;但它的毛病是,只合并了部分的数据,对于那些全局删除操作,无奈在合并过程中齐全删除。因而,minor compact尽管能缩小文件,但却无奈彻底清除那些delete操作。而major compact能齐全清理那些delete操作,保证数据的最小化。 总结:LSM树的索引构造实质是将写入操作全副转化成磁盘的程序写入,极大地提高了写入操作的性能。然而,这种设计对读取操作是十分不利的,因为须要在读取的过程中,通过归并所有文件来读取所对应的KV,这是十分耗费IO资源的。因而,在HBase中设计了异步的compaction来升高文件个数,达到进步读取性能的目标。因为HDFS只反对文件的程序写,不反对文件的随机写,而且HDFS善于的场景是大文件存储而非小文件,所以下层HBase抉择LSM树这种索引构造是最合适的。 文章基于《HBase原理与实际》一书

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理LSM树

HBase的一个列簇(Column Family)实质上就是一棵LSM树(Log-StructuredMerge-Tree)。LSM树分为内存局部和磁盘局部。内存局部是一个保护有序数据汇合的数据结构。一般来讲,内存数据结构能够抉择均衡二叉树、红黑树、跳跃表(SkipList)等保护有序集的数据结构,这里因为思考并发性能,HBase抉择了体现更优良的跳跃表。磁盘局部是由一个个独立的文件组成,每一个文件又是由一个个数据块组成。 LSM树实质上和B+树一样,是一种磁盘数据的索引构造。但和B+树不同的是,LSM树的索引对写入申请更敌对。因为无论是何种写入申请,LSM树都会将写入操作解决为一次程序写,而HDFS善于的正是程序写(且HDFS不反对随机写),因而基于HDFS实现的HBase采纳LSM树作为索引是一种很适合的抉择。 LSM树的索引个别由两局部组成,一部分是内存局部,一部分是磁盘局部。内存局部个别采纳跳跃表来保护一个有序的KeyValue汇合。磁盘局部个别由多个外部KeyValue有序的文件组成。 1.KeyValue存储格局一般来说,LSM中存储的是多个KeyValue组成的汇合,每一个KeyValue个别都会用一个字节数组来示意。这里,首先须要来了解KeyValue这个字节数组的设计。 以HBase为例,这个字节数组串设计如图所示。总体来说,字节数组次要分为以下几个字段。其中Rowkey、Family、Qualifier、Timestamp、Type这5个字段组成KeyValue中的key局部。 • keyLen:占用4字节,用来存储KeyValue构造中Key所占用的字节长度。• valueLen:占用4字节,用来存储KeyValue构造中Value所占用的字节长度。• rowkeyLen:占用2字节,用来存储rowkey占用的字节长度。• rowkeyBytes:占用rowkeyLen个字节,用来存储rowkey的二进制内容。• familyLen:占用1字节,用来存储Family占用的字节长度。• familyBytes:占用familyLen字节,用来存储Family的二进制内容。• qualif ierBytes:占用qualif ierLen个字节,用来存储Qualif ier的二进制内 留神,HBase并没有独自调配字节用来存储qualif ierLen,因为能够通过keyLen和其余字段的长度计算出qualif ierLen。代码如下: • timestamp:占用8字节,示意timestamp对应的long值。• type:占用1字节,示意这个KeyValue操作的类型,HBase内有Put、Delete、Delete Column、DeleteFamily,等等。留神,这是一个十分要害的字段,表明了LSM树内存储的不只是数据,而是每一次操作记录。 Value局部间接存储这个KeyValue中Value的二进制内容。所以,字节数组串次要是Key局部的设计。 在比拟这些KeyValue的大小程序时,HBase依照如下形式(伪代码)来确定大小关系:留神,在HBase中,timestamp越大的KeyValue,排序越靠前。因为用户冀望优先读取到那些版本号更新的数据。 下面以HBase为例,剖析了HBase的KeyValue结构设计。通常来说,在LSM树的KeyValue中的Key局部,有3个字段必不可少: Key的二进制内容。 一个示意版本号的64位long值,在HBase中对应timestamp;这个版本号通常示意数据的写入先后顺序,版本号越大的数据,越优先被用户读取。甚至会设计肯定的策略,将那些版本号较小的数据过期淘汰(HBase中有TTL策略)。 type,示意这个KeyValue是Put操作,还是Delete操作,或者是其余写入操作。实质上,LSM树中寄存的并非数据自身,而是操作记录。这对应了LSM树(Log-Structured Merge-Tree)中Log的含意,即操作日志。 2.多路归并先看一个简略的问题:当初有K个文件,其中第i个文件外部存储有Ni个正整数(这些整数在文件内依照从小到大的顺序存储),如何设计一个算法将K个有序文件合并成一个大的有序文件?在排序算法中,有一类排序算法叫做归并排序,外面就有大家熟知的两路归并实现。当初相当于K路归并,因而能够拓展一下,思路相似。对每个文件设计一个指针,取出K个指针中数值最小的一个,而后把最小的那个指针后移,接着持续找K个指针中数值最小的一个,持续后移指针……直到N个文件全副读完为止,如图所示。算法复杂度剖析起来也较为容易,首先用一个最小堆来保护K个指针,每次从堆中取最小值,开销为logK,最多从堆中取次元素。因而最坏复杂度就是 3. LSM树的索引构造一个LSM树的索引次要由两局部形成:内存局部和磁盘局部。内存局部是一个ConcurrentSkipListMap,Key就是后面所说的Key局部,Value是一个字节数组。数据写入时,间接写入MemStore中。随着一直写入,一旦内存占用超过肯定的阈值时,就把内存局部的数据导出,造成一个有序的数据文件,存储在磁盘上。LSM树索引构造如图所示。内存局部导出造成一个有序数据文件的过程称为flush。为了防止f lush影响写入性能,会先把以后写入的MemStore设为Snapshot,不再答应新的写入操作写入这个Snapshot的MemStore。另开一个内存空间作为MemStore,让前面的数据写入。一旦Snapshot的MemStore写入结束,对应内存空间就能够开释。这样,就能够通过两个MemStore来实现稳固的写入性能。 LSM树索引构造 随着写入的减少,内存数据会一直地刷新到磁盘上。最终磁盘上的数据文件会越来越多。如果数据没有任何的读取操作,磁盘上产生很多的数据文件对写入并无影响,而且这时写入速度是最快的,因为所有IO都是程序IO。然而,一旦用户有读取申请,则须要将大量的磁盘文件进行多路归并,之后能力读取到所需的数据。因为须要将那些Key雷同的数据全局综合起来,最终抉择出适合的版本返回给用户,所以磁盘文件数量越多,在读取的时候随机读取的次数也会越多,从而影响读取操作的性能。 为了优化读取操作的性能,咱们能够设置肯定策略将选中的多个hf ile进行多路归并,合并成一个文件。文件个数越少,则读取数据时须要seek操作的次数越少,读取性能则越好。 一般来说,依照选中的文件个数,咱们将compact操作分成两种类型。一种是major compact,是将所有的hf ile一次性多路归并成一个文件。这种形式的益处是,合并之后只有一个文件,这样读取的性能必定是最高的;但它的问题是,合并所有的文件可能须要很长的工夫并耗费大量的IO带宽,所以major compact不宜应用太频繁,适宜周期性地跑。 另外一种是minor compact,即选中少数几个hf ile,将它们多路归并成一个文件。这种形式的长处是,能够进行部分的compact,通过大量的IO缩小文件个数,晋升读取操作的性能,适宜较高频率地跑;但它的毛病是,只合并了部分的数据,对于那些全局删除操作,无奈在合并过程中齐全删除。因而,minor compact尽管能缩小文件,但却无奈彻底清除那些delete操作。而major compact能齐全清理那些delete操作,保证数据的最小化。 总结:LSM树的索引构造实质是将写入操作全副转化成磁盘的程序写入,极大地提高了写入操作的性能。然而,这种设计对读取操作是十分不利的,因为须要在读取的过程中,通过归并所有文件来读取所对应的KV,这是十分耗费IO资源的。因而,在HBase中设计了异步的compaction来升高文件个数,达到进步读取性能的目标。因为HDFS只反对文件的程序写,不反对文件的随机写,而且HDFS善于的场景是大文件存储而非小文件,所以下层HBase抉择LSM树这种索引构造是最合适的。 文章基于《HBase原理与实际》一书

July 27, 2020 · 1 min · jiezi

关于hbase:HBase原理跳跃表

跳跃表(SkipList)是一种能高效实现插入、删除、查找的内存数据结构,这些操作的冀望复杂度都是O(logN)。与红黑树以及其余的二分查找树相比,跳跃表的劣势在于实现简略,而且在并发场景下加锁粒度更小,从而能够实现更高的并发性。正因为这些长处,跳跃表宽泛应用于KV数据库中,诸如Redis、LevelDB、HBase都把跳跃表作为一种保护有序数据汇合的根底数据结构。 家喻户晓,链表这种数据结构的查问复杂度为O(N),这里N是链表中元素的个数。在曾经找到要删除元素的状况下,再执行链表的删除操作其实十分高效,只需把待删除元素前一个元素的next指针指向待删除元素的后一个元素即可,复杂度为O(1),如图所示 但问题是,链表的查问复杂度太高,因为链表在查问的时候,须要一一元素地查找。如果链表在查找的时候,可能防止顺次查找元素,那么查找复杂度将升高。而跳跃表就是利用这一思维,在链表之上额定存储了一些节点的索引信息,达到防止顺次查找元素的目标,从而将查问复杂度优化为O(logN)。将查问复杂度优化之后,天然也优化了插入和删除的复杂度。 1.定义跳跃表的定义如下: •跳跃表由多条分层的链表组成(设为S0, S1, S2, ... , Sn),例如图中有6条链表。•每条链表中的元素都是有序的。•每条链表都有两个元素:+∞(正无穷大)和- ∞(负无穷大),别离示意链表的头部和尾部。•从上到下,下层链表元素汇合是上层链表元素汇合的子集,即S1是S0的子集,S2是S1的子集。•跳跃表的高度定义为程度链表的层数。 2.查找在跳跃表中查找一个指定元素的流程比较简单。如图所示,以左上角元素(设为currentNode)作为终点查找元素5: •如果发现currentNode后继节点的值小于等于待查问值,则沿着这条链表向后查问,否则,切换到以后节点的下一层链表。•持续查问,直到找到待查问值为止(或者currentNode为空节点)为止。 3.插入跳跃表的插入算法要简单一点。如图所示。首先,须要依照上述查找流程找到待插入元素的前驱和后继;而后,依照如下随机算法生成一个高度值: (图在跳跃表插入元素48)最初,将待插入节点依照高度值生成一个垂直节点(这个节点的层数正好等于高度值),之后插入到跳跃表的多条链表中去。假如height=randomHeight(p),这里须要分两种状况探讨:•如果height大于跳跃表的高度,那么跳跃表的高度被晋升为height,同时须要更新头部节点和尾部节点的指针指向。•如果height小于等于跳跃表的高度,那么须要更新待插入元素前驱和后继的指针指向。 跳跃表的查找、删除、插入的复杂度都是O(logN)。 文章基于《HBase原理与实际》一书

July 27, 2020 · 1 min · jiezi

OpenTSDB-数据存储详解

本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/qayKiwk5QAIWI7-nyD3FVA 作者:DuZhimin随着互联网、尤其是物联网的倒退,咱们须要把各种类型的终端实时监测、查看与剖析设施所采集、产生的数据记录下来,在有工夫的坐标中将这些数据连点成线,往过来看能够做成多纬度报表,揭示其趋势性、规律性、异样性;往将来看能够做大数据分析,机器学习,实现预测和预警。 这些数据的典型特点是:产生频率快(每一个监测点一秒钟内可产生多条数据)、重大依赖于采集工夫(每一条数据均要求对应惟一的工夫)、测点多信息量大(实时监测零碎均有成千上万的监测点,监测点每秒钟都产生数据,每天产生几十GB的数据量)。 基于工夫序列数据的特点,关系型数据库无奈满足对工夫序列数据的无效存储与解决,因而迫切需要一种专门针对工夫序列数据来做优化解决的数据库系统。 一、简介1、时序数据时序数据是基于工夫的一系列的数据。 2、时序数据库时序数据库就是寄存时序数据的数据库,并且须要反对时序数据的疾速写入、长久化、多纬度的聚合查问等基本功能。 比照传统数据库仅仅记录了数据的以后值,时序数据库则记录了所有的历史数据。同时时序数据的查问也总是会带上工夫作为过滤条件。 3、OpenTSDB毫无脱漏的接管并存储大量的工夫序列数据。 3.1、存储无需转换,写的是什么数据存的就是什么数据时序数据以毫秒的精度保留永恒保留原始数据3.2、扩展性运行在Hadoop 和 HBase之上可扩大到每秒数百万次写入能够通过增加节点扩容3.3、读能力间接通过内置的GUI来生成图表还能够通过HTTP API查问数据另外还能够应用开源的前端与其交互4、OpenTSDB外围概念咱们来看一下这样一段信息:2019-12-5 22:31:21版本号为‘3.2.1’的某产品客户端的首页PV是1000W Metric:指标,即平时咱们所说的监控项。譬如下面的PVTags:维度,也即标签,在OpenTSDB外面,Tags由tagk和tagv组成的键值对,即tagk=takv。标签是用来形容Metric的,比方下面的某产品客户端的版本号 version=‘3.2.1’Value:一个Value示意一个metric的理论数值,比方:1000WTimestamp:即工夫戳,用来形容Value是什么时候产生的:比方:2019-12-5 22:31:21Data Point:即某个Metric在某个工夫点的数值,Data Point包含以下局部:Metric、Tags、Value、Timestamp保留到OpenTSDB的数据就是无数个DataPoint下面形容2019-12-5 22:31:21版本号为‘3.2.1’的某产品客户端的首页PV是1000W,就是1个DataPoint。 二、OpenTSDB的部署架构1、架构图 2、阐明OpenTSDB底层是应用HBase来存储数据的,也就是说搭建OpenTSDB之前,必须先搭建好HBase环境。OpenTSDB是由一系列的TSD和实用的命令行工具组成。利用通过运行一个或多个tsd(Time Series Daemon, OpenTSDB的节点)来与OpenTSDB的交互。每个TSD是独立的,没有master,没有共享状态,所以你能够运行尽可能多的 TSD 来解决工作负载。三、HBase简介从OpenTSDB的部署架构中咱们看到OpenTSDB是建设在HBase之上的,那么HBase又是啥呢?为了更好的分析OpenTSDB,这里咱们简要介绍一下HBase。 1、HBase是一个高可靠性、强一致性、高性能、面向列、可伸缩、实时读写的分布式开源NoSQL数据库。 2、HBase是无模式数据库,只须要提前定义列簇,并不需要指定列限定符。同时它也是无类型数据库,所有数据都是按二进制字节形式存储的。 3、它把数据存储在表中,表按“行键,列簇,列限定符和工夫版本”的四维坐标系来组织,也就是说如果要惟一定位一个值,须要四个都惟一才行。上面参考Excel来阐明一下: 4、对 HBase 的操作和拜访有 5 个根本形式,即 Get、Put、Delete 和 Scan 以及 Increment,HBase 基于非行键值查问的惟一路径是通过带过滤器的扫描。 5、数据在HBase中的存储(物理上): 6、数据在HBase中的存储(逻辑上): 四、 撑持OpenTSDB运行的HBase表如果你第一次用你的HBase实例运行OpenTSDB,须要创立必要的HBase表,OpenTSDB 运行仅仅须要四张表:tsdb, tsdb-uid, tsdb-tree 和 tsdb-meta,所有的DataPoint 数据都保留在这四张表中,建表语句如下: 1、tsdb-uidcreate 'tsdb-uid',{NAME => 'id', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'},{NAME => 'name', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}2、tsdbcreate 'tsdb',{NAME => 't', VERSIONS => 1, COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}3、tsdb-treecreate 'tsdb-tree',{NAME => 't', VERSIONS => 1, COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}4、tsdb-metacreate 'tsdb-meta',{NAME => 'name', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}前面将对照理论数据来专门解说这四张表别离存储的内容。 ...

July 16, 2020 · 1 min · jiezi