HBase原理

目录

                                   

                                            HBase原理

1 HBase架构

2 HBase中的核心概念

3 HBase的存储机制

4 HBase的寻址机制

5 HBase的读写流程

6 HBase的设计

7 HBase和Hive的整合


               

                                            HBase原理

1 HBase架构

HBase的架构为主从架构,HMaster为主节点,HRegionServer为从节点

(1)HMaster职责:

①进行Region的分配,每一个Region分配到哪一个RegionServer上;

②负责RegionServer的负载均衡

③通过zookeeper发小失效的RegionServer并重新分配在它上面的Region

④HDFS上的HBase的垃圾文件回收

⑤处理schema更新请求,表的创建,删除,更改,列簇的增加等,将schema写入到zookeeper中

(2)HRegionserver职责

①管理每个Region

②负责每一个Region的分裂

(3)zookeeper职责

①进行HMaster的active的选举,避免单点故障

②存储HBase的寻址机制

③存储RegionServer的存活状态,HMaster通过zookeeper获取每一个HRegionServer的状态

④存储表的schema表结构

2 HBase中的核心概念

(1)Region

每一个表的数据,都需要进行划分成多个Region,Region对HBase表的划分是在行的方向上的。一个Region代表一个表中的多行数据,一定是行键范围内的数据。

Region是HBase进行分布式存储的最小单位,负载均衡的的存储单位,注意并不是物理存储的最小单位。一个Region是不能再进行分割的,在分布式存储的时候一个Region只能存储在一个HRegionserver即一个节点上,一个HRegionserver是可以存储多个Region的。

一个HBase表刚创建的时候只有一个Region,进行数据插入的时候,写入的都是这一个Region,随着数据插入的,数据量不断的增加当数据量达到一定值的时候(默认为10G)就会进行切分,将一个Region切分为2个Region,一旦切分完成,就会面临Region的重新分配,由HMaster分配每一个Region存储在哪个HRegionServer,原来的那个Region就没用了,进行下线。

配置文件中对切分大小的配置如下:

<property><name>hbase.hregion.max.filesize</name><value>10737418240</value><description>Maximum HStoreFile size. If any one of a column families' HStoreFiles hasgrown to exceed this value, the hosting HRegion is split in two.</description>
</property>

每一个Region中一个列族的物理文件达到10G才进行切分,切分的时候是按照rowkey的中间值进行切分的。

一个表是对应多个Region,多个Region对应多个物理文件的(一个列族一个物理文件)。每一个Region 都有一个全局唯一的一个编号,hdfs位置为:/user/hbase/data/default(namespace)/table_hbase(table)/313c7bb8491d6207ac0153c0392cc392(region编号)

刚开始对Hbase中表数据进行插入操作时候,操作只有一个Region,在这个Region分裂之前  操作的都是这一个Region 操作的只有一个Regionserver ,会出现 数据热点,anemia如何解决呢,下面表设计时再进行介绍。

(2)Store

一个Store对应一个列族,Store是HBase物理存储的最小单位,1个Region对应多个Store,多个Store对应多个列族。一个Store中包含一个MemStore和多个StoreFile。

(3)MemStore

每一个Store中,都有一位于内存中的MemStore存储空间,写入数据的时候,每一个Store中的数据先写入到MemStore,读取数据的时候先从内存中读取MemStore。

(4)StoreFile

每一个Store有多个位于硬盘的StoreFile磁盘文件,当MemStore达到一定阈值(默认为128M)的时候,就会将数据flush,形成一个个的StoreFile,配置文件中的参数如下

<property><name>hbase.hregion.memstore.flush.size</name><value>134217728</value><description>Memstore will be flushed to disk if size of the memstoreexceeds this number of bytes.  Value is checked by a thread that runsevery hbase.server.thread.wakefrequency.</description>
</property> 

(5)HFile

最终StoreFile文件以HFile格式存储在HDFS上。

(6)WAL(HLog)

WAL:write-ahead-log预写日志文件,为了防止在MemStore中数据丢失,在写入数据之前,会先将对数据的操作写入到WAL文件中。

一个HRegionServer中只会存储一个WAL文件,一个HREgionServer中的所有的Region共用一个WAL文件,便于管理日志。

3 HBase的存储机制

(1)0.96版本之前的存储机制

①原始表:存储原始数据的

②.meta表:存储原始数据的索引的,按照rowkey创建原始表索引

③-root-表:存储.meta表的索引的表,这个是最终索引,无论多大,只有一个Region不可分割了。-root-表的最终Region的存储位置存储在了zookeeper中,所以zookeeper中存储的是HBase的寻址路径。

(2)0.96版本之后的存储机制

①原始表:存储原始数据的

②.meta表:存储原始数据的索引的,按照rowkey创建原始表索引。.meta无论多大,只存储在一个Region,不可再进行分割了。.meta表的Region的存储位置存储在了zookeeper中。

.meta表中的一条数据相当于原始表至少10个G的数据,所以.meta表很难达到分割范围,除非数据量超级大才能达到。

4 HBase的寻址机制

HBase表最终会被拆分成一个个的Region,每一个Region可能会存储在不同的HRegionServer,每一个Region都是有独立编号的,无论读还是写操作,首先都要定位到在哪一个Region中,到对应的存储了该Region的HRegionServer上找到这个Region进行操作。

(1)0.96版本之前的寻址过程:

①客户端首先访问zookeeper,获取存储了-root-表的RegionServer的位置,以及Region的编号

②访问-root-表的Region,获取存储了.meta表的RegionServer的位置,以及Region的编号

③访问.meta表,获取可需要查询的rk所在的Region位置,获取原始数据的RegionServer的位置,以及Region的编号

④开始真正的访问对应RegionServer上的Region的的表数据

(2)0.96版本之后的寻址过程

①客户端首先访问zookeeper,获取存储.meta表的HRegionServer的位置,以及Region编号

②访问.meta表的Region,获取原始数据表中对应的HRegionServer的Region编号

③开始真正的访问对应RegionServer上的Region的的表数据

5 HBase的读写流程

(1)写流程(put|delete)

①客户端根据rowkey经常3次往返(寻址机制)找到对应的Region所在的RegionServer;

②客户端向RegionServer提交写请求;

③RegionServer找到目标Region

④Region检查数据是否与schema表结构的表名,列簇是否一致,一致则允许写入,不一致则报错直接返回。

⑤如果客户端没有指定版本,则获取当前的时间作为数据版本

⑥将更新操作写入到WAL文件中

⑦将更新写入到对应的Store中的MemSore

⑧判断MemStore是否需要flush刷新为StoreFile文件,默认当阈值MemStore文件大小达到128M的时候开始flush,形成StoreFile文件。

⑨当一个StoreFile的个数达到一定的阈值的时候就会触发compact合并,compact合并有minor compact和major compact:

minor join小合并,触发条件默认为StoreFile文件的个数达到3个的时候触发,将3个StoreFile合并为1个StoreFile文件,这个合并是没有任何逻辑操作的,只是物理操作,简单的将文件进行累加合并,只是在文件的个数上减少了,不会对真正需要删除的数据进行删除,只是打了标记,客户端看不到。

major join:当达到阈值(默认为7天)后,会将7天的多个HFile文件进行合并为1个HFile,这个合并是执行逻辑操作的,进行真正的数据删除,将所有需要删除的数据进行真正的合并删除。需要删除的数据有以下几种:

1)执行delete操作的数据;

2)版本超过给定的需要保存的版本的数据,将过期的数据删除

3)TTL过期的数据

⑩判断一个Store中的所有文件的总大小是否达到Region的切分标准,默认为128M,达到切分标准就会对Region进行切分,HMaster对新的Region进行重新的分配,丢弃旧的Region。

(2)读流程(get|scan)

①客户端根据rowkey经过3次往返(寻址机制)找到对应的Region所在的RegionServer

②客户端向对应的RegionServer的·Region发送读数据请求

③客户端先在Region的对应的Store的MemStore(Blockcache)中进行读取

④MemStore有数据则直接返回,没有数据则到HFile文件进行读取。

 

6 HBase的设计

(1)表设计

①防止数据热点问题,建表的时候最好进行表的预分区,插入数据的时候,rowkey不要顺序递增。

HBase中你的数据热点:进行读写操作的时候,频繁操作某一个Region造成这个Region所在的RegionServer热点,根源是经常访问的数据集中分配到了个别Region

②列族不建议过多

(2)列族设计

①将具有相同io属性的列放在同一个列簇中;

②列簇不宜过多,不要超过3个,因为不同的列簇需要跨文件访问

(3)行键设计

思路:首先根据业务,需要安装哪一个字段查询,然后要避免热点产生

①保证唯一性

②不宜过长,0-100byte,最好不要超过16byte,最好是8的倍数。原因如下

1)行键存储在每一个列簇文件中的StoreFile,如果太大会造成磁盘空间的浪费

2)行键信息也会写入到每一个Store的MemStore中,如果过长,会造成内存空间的极大浪费

2)大部分计算机的底层存储时8通道的

③散列性

rowkey是按照字典顺序排序的,如果rowkey过于集中,会造成数据操作集中在个别的Region上,造成数据热点

有效措施如下:

1)采用hash

2)加盐:在原生的rowkey前面加上随机数

3)反转:将字符串或时间戳进行反转

4)使用uuid或md5等方法

7 HBase和Hive的整合

HBase:是NoSQL分布式数据库,表结构是四维表。擅长做实时随机查询,没有分析函数join等

Hive:数据仓库,擅长做数据分许,有大量函数可以使用

HBase语法是不支持分析的,想要对HBase中的数据做数据分析就要将HBase和Hive整合,便于对HBase数据做统计分析。Hive读取HBase中的数据,将HBase中的数据转换二维表数据,需要hive-hbase-handler-2.3.2.jar包(整合的核心包)中的HBaseStorageHandler类,将HBase中的数据进行压平。

整个步骤如下:

①设置HBase的zookeeper访问路径:

set hbase.zookeeper.quorum=bigdata01:2181,bigdata02:2181,bigdata03:2181;

②设置HBase在zookeeper的访问路径,存储节点

set zookeeper.znode.parent=/hbase;

③将Hive的解析HBase的jar包添加到Hive的classpath下

add jar /home/refuel/opt/modules/apache-hive-2.3.2-bin/lib/hive-hbase-handler-2.3.2.jar;

 

整合完后在Hive中 读取HBase的表,在Hive建表语句指定解析类,全关联如下

create external table Hive_HBase(rowkey string, base_info map<string, string>, extra_info map<string, string>) 
row format delimited fields terminated by '\t' 
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties ("hbase.columns.mapping" = ":key,base_info:,extra_info:")
tblproperties ("hbase.table.name" = "Hive_HBase");with serdeproperties   指定hbase表和hive的对应关系的
hbase.columns.mapping   指定hbase表和hive表映射   和hive中的建表语句一一对应的指定hbase 对应值的时候  k(列族名):v(列族下的对应的列和值) key:base_infovalue:  name:zs    age:12              :key   获取rowkey 的值
hbase.table.name:  指定对应的表名

部分关联如下

create external table Hive_HBase02(rowkey string,name string,age int,math int) 
row format delimited fields terminated by '\t' 
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties ("hbase.columns.mapping" = ":key,base_info:name,base_info:age,extra_info:math") 
tblproperties ("hbase.table.name" = "Hive_HBase02");

8 HBase的BulkLoad

HBase的数据导入有3种方式:①put方式一条条插入;②MapReduce方式并发导入;③BulkLoad方式

MapReduce与put方式导入数据的过程:文本数据---》HRegionServer---》WAL---》MemStore---》StoreFile---》HFile

BulkLoad方式将文本数据(结构化或半结构化)直接转换为HFile格式的数据,转换完成之后再将这个HFile数据放置在HBase的对应的表的存储目录下

所以BulkLoad的优势是省去了中间的写入数据的复杂的过程,直接得到最终的结果,效率极高。

BulkLoad如何进行海量数据的导入的呢?,如下两个重要的类

(1)HBase中提供了一个进行数据装换的类PutSortReducer将数据封装为HFile需要的格式

ImmutableBytesWritable:行键       Put:需要插入的数据对象       KeyValue:单元格

(2)HBase中还提供了一个输出格式的类HFileOutputFormat2 ,数据的为HFile格式数据,而不是文本。

所以实现如下:

Map端:

            读取每一行文本数据,并封装PutSortReducer需要的数据

            输出的key为ImmutaByteaWritable,输出的value为Put

Reduce端:

            使用PutSortReducer类,进行准备Hfile需要的数据

驱动类:

            文件输出格式采用HFileOutputFormat2

注意:上面的这些操作仅仅是将文本数据转换为HFile格式的数据。转换完成之后,还要将这个HFile数据放置在HBase的对应的表的存储目录下面。

具体实现代码如下:

import java.io.IOException;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.HFileOutputFormat2;
import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;public class BulkLoadMR {static class MyMapper extends Mapper<LongWritable, Text, ImmutableBytesWritable, Put> {ImmutableBytesWritable mk = new ImmutableBytesWritable();@Overrideprotected void map(LongWritable key, Text value,Mapper<LongWritable, Text, ImmutableBytesWritable, Put>.Context context)throws IOException, InterruptedException {String[] datas = value.toString().split("\t");if (datas.length == 3) {mk.set(datas[0].getBytes());Put p = new Put(datas[0].getBytes());p.addColumn("column_faily1".getBytes(), "name".getBytes(), datas[1].getBytes());p.addColumn("column_faily2".getBytes(), "age".getBytes(), datas[2].getBytes());context.write(mk, p);}}}public static void main(String[] args) throws Exception {Configuration conf = new Configuration();conf.set("fs.defaultFS", "hdfs://bigdatagroup/");conf.set("hbase.zookeeper.quorum", "bigdata01:2181,bigdata02:2181,bigdata03:2181");Job job = Job.getInstance(conf);job.setJarByClass(BulkLoadMR.class);job.setMapperClass(MyMapper.class);job.setMapOutputKeyClass(ImmutableBytesWritable.class);job.setMapOutputValueClass(Put.class);job.setOutputKeyClass(ImmutableBytesWritable.class);job.setOutputValueClass(KeyValue.class);FileInputFormat.addInputPath(job, new Path("/data/student"));// 指定输出HFileOutputFormat2job.setOutputFormatClass(HFileOutputFormat2.class);// 进行输出HFileOutputFormat2.setOutputPath(job, new Path("/user/hbase/bulkload"));Connection conn = ConnectionFactory.createConnection(conf);HTable table = (HTable) conn.getTable(TableName.valueOf("table_bulkload"));// 设置对应表 参数1 job 参数2 表对象 参数3 加载region相关参数的// 准备需要的操作HFileOutputFormat2.configureIncrementalLoad(job, table, table.getRegionLocator());job.waitForCompletion(true);// 上面的这些操作仅仅是将文本数据转换为HFile格式的数据。// 转换完成之后,还要将这个HFile数据放置在HBase的对应的表的存储目录下面。LoadIncrementalHFiles loadH = new LoadIncrementalHFiles(conf);Admin admin = conn.getAdmin();// 进行加载// 参数1 hdfs 输出hfile 路径 参数2 admin 参数3 table 参数4:regioin信息对象loadH.doBulkLoad(new Path("/user/hbase/bulkload"), admin, table, table.getRegionLocator());}
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库实例:用户登录

如下遍流程图&#xff0c;接下来的代码就按照这个逻辑来写 创建user_login.py文件&#xff0c;代码如下 #codingutf-8 from MySQLdb import* from hashlib importsha1 if __name____main__: try: #接收输入用户名、密码 unameraw_input(请输入用户名&…

数据库实例:mysql与mongo结合用户登录

加入mongodb后登录逻辑如下图&#xff0c;将图中nosql的位置换为mongodb即可 用户数据存储的集合名称为py_users&#xff0c;文档格式为{uname:用户名,upwd:密码} 将原来MySQL操作的代码封装到一个方法中&#xff0c;代码如下 def mysql_login(): #mongodb中没有则到mysql中…

LeetCode 1609. 奇偶树(层序遍历)

文章目录1. 题目2. 解题1. 题目 如果一棵二叉树满足下述几个条件&#xff0c;则可以称为 奇偶树 &#xff1a; 二叉树根节点所在层下标为 0 &#xff0c;根的子节点所在层下标为 1 &#xff0c;根的孙节点所在层下标为 2 &#xff0c;依此类推。偶数下标 层上的所有节点的值都…

数据的特征工程

数据的特征工程 1 什么是数据的特征工程 特征工程是将原始数据转换为更好地代表预测模型的潜在问题的特征的过程&#xff0c;从而提高了对未知数据的模型准确性。 特征工程的意义&#xff1a;将直接影响模型的预测结果。 2 数据的来源与类型 2.1 数据的来源 企业日益积累…

数据库实例:mysql与redis结合用户登录

加入redis后登录逻辑如下图&#xff0c;将图中nosql的位置换为redis即可 用户数据存的键为用户名&#xff0c;值为密码 将原来MySQL操作的代码封装到一个方法中&#xff0c;代码如下 defmysql_login(): #redis中没有则到mysql中查询 sqlselect upwd from py_users wher…

LeetCode 1610. 可见点的最大数目(atan2函数求夹角)

文章目录1. 题目2. 解题1. 题目 给你一个点数组 points 和一个表示角度的整数 angle &#xff0c;你的位置是 location &#xff0c;其中 location [posx, posy] 且 points[i] [xi, yi] 都表示 X-Y 平面上的整数坐标。 最开始&#xff0c;你面向东方进行观测。你 不能 进行…

[翻译]API Guides - Bound Services

官方文档原文地址&#xff1a;http://developer.android.com/guide/components/bound-services.html 一个Bound Service是一个客户端-服务器接口的服务。一个Bound Service允许组件&#xff08;像activity&#xff09;绑定一个service&#xff0c;发送请求&#xff0c;接受结果…

sklearn数据集与估计器

sklearn数据集与估计器 1 sklearn数据集 &#xff08;1&#xff09;数据来源&#xff1a;大多数以文件的形式 &#xff08;csv文件..&#xff09;, 因为mysql有性能瓶颈、读取速度遭到限制&#xff0c;数据大的时候很费时间 &#xff08;2&#xff09;读取数据的工具&#…

LeetCode 935. 骑士拨号器(动态规划)

文章目录1. 题目2. 解题1. 题目 国际象棋中的骑士可以按下图所示进行移动&#xff1a; 这一次&#xff0c;我们将 “骑士” 放在电话拨号盘的任意数字键&#xff08;如上图所示&#xff09;上&#xff0c; 接下来&#xff0c;骑士将会跳 N-1 步。每一步必须是从一个数字键跳到…

k近邻算法(KNN)-分类算法

k近邻算法(KNN)-分类算法 1 概念 定义&#xff1a;如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别&#xff0c;则该样本也属于这个类别。 k-近邻算法采用测量不同特征值之间的距离来进行分类。 2 优缺点 优点&#xff1a;简单&a…

LeetCode 822. 翻转卡片游戏(哈希)

文章目录1. 题目2. 解题1. 题目 在桌子上有 N 张卡片&#xff0c;每张卡片的正面和背面都写着一个正数&#xff08;正面与背面上的数有可能不一样&#xff09;。 我们可以先翻转任意张卡片&#xff0c;然后选择其中一张卡片。 如果选中的那张卡片背面的数字 X 与任意一张卡片…

朴素贝叶斯算法-分类算法

朴素贝叶斯算法-分类算法 1 概率基础 概率定义为一件事情发生的可能性 联合概率&#xff1a;包含多个条件&#xff0c;且所有条件同时成立的概率&#xff0c;记作P(A,B) 条件概率&#xff1a;事件A在另一个事件B已经发生条件下的发送概率&#xff0c;记作P(A|B) 在A1,A2相…

django简介及环境搭建

MVC简介 MVC框架的核心思想是&#xff1a;解耦&#xff0c;让不同的代码块之间降低耦合&#xff0c;增强代码的可扩展性和可移植性&#xff0c;实现向后兼容 M全拼为Model&#xff0c;主要封装对数据库层的访问&#xff0c;内嵌ORM框架&#xff0c;实现面向对象的编程来操作数据…

LeetCode 1312. 让字符串成为回文串的最少插入次数(区间DP)

文章目录1. 题目2. 解题1. 题目 给你一个字符串 s &#xff0c;每一次操作你都可以在字符串的任意位置插入任意字符。 请你返回让 s 成为回文串的 最少操作次数 。 「回文串」是正读和反读都相同的字符串。 示例 1&#xff1a; 输入&#xff1a;s "zzazz" 输出&…

Django创建项目

创建项目的名称为test1&#xff0c;完成“图书-英雄”信息的维护&#xff0c;创建应用名称为booktest 创建项目 cd /home/Desktop/ mkdir pytest cd pytest 创建项目的命令如下&#xff1a; django-admin startproject test1 项目默认目录说明 进入test1目录&#xff0c;查看…

分类模型的评估

分类模型的评估 在许多实际问题中&#xff0c;衡量分类器任务的成功程度是通过固定的性能指标来获取。一般最常见使用的是准确率&#xff0c;即预测结果正确的百分比&#xff0c;方法为estimator.score() 1 混淆矩阵 有时候&#xff0c;我们关注的是样本是否被正确诊断出来。…

LeetCode 996. 正方形数组的数目(回溯+剪枝)

文章目录1. 题目2. 解题1. 题目 给定一个非负整数数组 A&#xff0c;如果该数组每对相邻元素之和是一个完全平方数&#xff0c;则称这一数组为正方形数组。 返回 A 的正方形排列的数目。两个排列 A1 和 A2 不同的充要条件是存在某个索引 i&#xff0c;使得 A1[i] ! A2[i]。 …

[Java]java反射随笔

类是面向对象的灵魂&#xff0c;一切事物都可以以类来抽象。 在java使用过程中&#xff0c;我们可能会经常用到一个反射的知识&#xff0c;只是别人都封装好的&#xff0c;如jdbc的加载驱动类有一句Class.for(“…jdbc…”).newInstance.当然框架也是离不开了反射&#xff0c;s…

模型的选择与调优

模型的选择与调优 1 交叉验证 1.1 交叉验证过程 交叉验证&#xff1a;为了让被评估的模型更加准确可信 交叉验证的意义&#xff1a;为了使一部分数据即当成验证集&#xff0c;也做过训练集&#xff0c;更加准确得出准确率&#xff0c;把最后的准确率取平均值。 注意&#…

Django创建图书管理项目(完整版

一、创建项目test1及应用booktest 创建应用booktest 二、安装应用 在test1/settings.py中INSTALLED_APPS下添加应用的名称就可以完成安装 初始项目的INSTALLED_APPS如下图&#xff1a; 在元组中添加一个新的项&#xff0c;当前示例为booktest booktest, 三、设计模型 1.定义模型…