史上最全面最完整的大数据学习第八章 Hbase(四)MR on Hbase & Hbase的 架构

Hbase ---- 初识 与 环境搭建

Hbase(二) shell操作

Hbase(三)Java API

Hbase(四)MR on Hbase & Hbase的 架构

Hbase(五) Hbase 的读写流程

Hbase完结篇 Hbase 集群搭建以及相关操作)

五、MR On HBase

5.1 依赖

		 <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>1.2.4</version>
        </dependency>
          <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.4</version>
        </dependency>
           <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
            <version>2.6.0</version>
        </dependency>
          <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.6.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.6.0</version>
            
        </dependency> 
	 @Test
    public void putData02() throws Exception {

        /*
         *ali baidu sina
         *
         * rowkey :公司名称+编号
         * */


        BufferedMutator mutator = connection.getBufferedMutator(TableName.valueOf("csdn:t_user1"));

        String[] company = {"baidu", "ali", "sina"};


        ArrayList<Put> puts = new ArrayList<Put>();

        for (int i = 0; i < 1000; i++) {

            String companyName = company[new Random().nextInt(3)];


            String empid = "";
            if (i < 10) {

                empid = "00" + i;


            } else if (i < 100) {

                empid = "0" + i;

            } else {

                empid = "" + i;
            }


            String rowKey = companyName + ":" + empid;

            Put put = new Put(rowKey.getBytes());

            put.addColumn("cf1".getBytes(), "name".getBytes(), ("zs" + i).getBytes());
            put.addColumn("cf1".getBytes(), "salary".getBytes(), Bytes.toBytes(100.0 * i));
            put.addColumn("cf2".getBytes(), "age".getBytes(), "18".getBytes());
            put.addColumn("cf2".getBytes(), "sex".getBytes(), "true".getBytes());

            puts.add(put);

        }

        mutator.mutate(puts);
        mutator.close();

    }

package com.csdn.mrdemo;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.mapreduce.TableInputFormat;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableOutputFormat;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.MRJobConfig;

public class AVGJob {
    public static void main(String[] args) throws Exception {
        System.setProperty("HADOOP_USER_NAME", "root");

        Configuration conf = new Configuration();
        /*
         * 设置跨平台提交
         * */
        conf.set("mapreduce.app-submission.cross-platform", "true");

        conf.addResource("conf2/core-site.xml");
        conf.addResource("conf2/hdfs-site.xml");
        conf.addResource("conf2/mapred-site.xml");
        conf.addResource("conf2/yarn-site.xml");


        conf.set("hbase.zookeeper.quorum", "HadoopNode00");
        conf.set("hbase.zookeeper.property.clientPort", "2181");


        conf.set(MRJobConfig.JAR, "D:\\大数据\\Code\\BigData\\HBase_Test\\target\\HBase_Test-1.0-SNAPSHOT.jar");


        Job job = Job.getInstance(conf);

        job.setInputFormatClass(TableInputFormat.class);
        job.setOutputFormatClass(TableOutputFormat.class);


        TableMapReduceUtil.initTableMapperJob(
                "baizhi:t_user1",
                new Scan(),
                AVGMapper.class,
                Text.class,
                DoubleWritable.class,
                job
        );

        TableMapReduceUtil.initTableReducerJob(
                "baizhi:t_result",
                AVGReducer.class,
                job
        );

        job.waitForCompletion(true);
    }
}

package com.csdn.mrdemo;


import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.Text;

import java.io.IOException;

public class AVGMapper extends TableMapper<Text, DoubleWritable> {
    @Override
    protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {

        /*
         * key  为rowky
         * value 为rowky 下所代表的值
         * */

        /*
         * 获取到rowkey的值
         * */
        byte[] bytes = key.get();
        /*
         * 转成字符串进行分割  获取下标为0的公司名字
         * */
        String companyName = Bytes.toString(bytes).split(":")[0];


        byte[] salaryBytes = value.getValue("cf1".getBytes(), "salary".getBytes());

        /*
         * 工资数据
         * */
        double salary = Bytes.toDouble(salaryBytes);


        context.write(new Text(companyName), new DoubleWritable(salary));


    }
}

package com.csdn.mrdemo;


import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;

import java.io.IOException;

public class AVGReducer extends TableReducer<Text, DoubleWritable, NullWritable> {

    @Override
    protected void reduce(Text key, Iterable<DoubleWritable> values, Context context) throws IOException, InterruptedException {

        double totalSalary = 0;
        int countPeople = 0;

        for (DoubleWritable value : values) {

            totalSalary += value.get();
            countPeople++;

        }
        Put put = new Put(key.getBytes());
        put.addColumn("cf1".getBytes(), "avgSalary".getBytes(), (totalSalary / countPeople + "").getBytes());

        context.write(NullWritable.get(), put);


    }
}

六 、HBase架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rUf2DRGA-1594544562381)(assets/1573022781166.png)]

6.1 Zookeeper

HBase通过zk来做Master的高可用,RegionServer的监控、元数据的入口以及集群配置的维护工作;具体如下:

通过ZK保证集群中只有一个Master可用,在主的Master的出现异常后,会通过竞争机制产生新的Master

通过ZK监控RegionServer的状态,当RegionServer有异常时,同时Master RegionServer上下线信息。

通过ZK存储元数据

ZK作为统一的入口地址

6.2 HMaster

为RegionServer分配Region,维护集群的负载均衡,维护集群的元数据信息,发现失效的Region,将失效的Region分配到正常的RegionServer上,当RegionServer失效时,协调对应的HLog的拆分。

6.3 HRegionServer

HRegionServer直接对接用户的读写请求,是真正的干活的额节点,功能如下:

管理Master为其分配的Region

处理来自客户端的读写请求,负责与HDFS进行交互,负责Region变大后的拆分。

6.3.1 Region

  • HBase 表根据Rowkey 划分成Region,理论上一个Region包含该表格从起始行到结束之间的所有行。
  • 但是往往有可能一个Region没有办法存储这个表中所有的行,会进行切分 数据大小>=N^2*128MB(N为Region数量),当N=9时,切分大小会超过10GB,此时就按照10GB进行切分。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-emZs10EL-1594544562393)(assets/1573010149953.png)]

  • Region由Store 组成
  • Region会被分配到称之为“HRegionServer”的节点上
Store

每一个Region由一个或者多个Store组成,至少是一个Store 。HBase会把经常访问的数据放在一个Store里面,即一个列簇组成一个Store ,有多少个列簇就多少个Store 。

在Store 中,由一个memStore 和 0个或者多个StoreFile 组成

MemStore
  • 写缓存。数据先写入到MemStore,触发flush机制后写到磁盘中
  • 以key-value的形式存储到内存中
  • MemStore的6种Flush机制(当MemStore Flush触发后,同一Region下的所有的MemStore都会刷新)
    • MemStore级别:当Region中人一个MemStore的大小达到上限(默认为128MB hbase.hregion.memstore.flush.size),会触发MemStore刷新
    • Region级别:当Region中所有的MemStore大小总和达到的上限(256MB hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size,默认 2* 128M = 256M)
    • RegionServer级别:当RegionServer中所有的MemStore大小总和达到上限(hbase.regionserver.global.memstore.upperLimit * hbase_heapsize,默认 40%的JVM内存使用量),会触发部分Memstore刷新。Flush顺序是按照Memstore由大到小执行,先Flush Memstore最大的Region,再执行次大的,直至总体Memstore内存使用量低于阈值(hbase.regionserver.global.memstore.lowerLimit * hbase_heapsize,默认 38%的JVM内存使用量)。
    • 当一个RegionServer中HLog数量达到了上限(可通过参数hbase.regionserver.maxlogs配置)时,系统会选取最早的一个 HLog对应的一个或多个Region进行flush
    • HBase定期刷新Memstore:默认周期为1小时,确保Memstore不会长时间没有持久化。为避免所有的MemStore在同一时间都进行flush导致的问题,定期的flush操作有20000左右的随机延时。
    • 手动执行flush:用户可以通过shell命令 flush ‘tablename’或者flush ‘region name’分别对一个表或者一个Region进行flush。
StoreFile|HFile

HFile(StoreFile) 用于存储HBase的数据(Cell/KeyValue)。在HFile中的数据是按RowKey、Column Family、 Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列。

由于MemStore中存储的Cell遵循相同的排列顺序,因而Flush过程是顺序写,由于不需要不停的移动磁盘指针,因此磁盘的顺序写性能很高。

HFile的组成分为6部分,分别是数据块、元数据块、FileInfo块、数据索引块、元数据索引块、HFile文件尾,它们的详细描述如下:

名称描述
数据块由多个Block(块)组成,每个块的格式为: [块头] + [Key长] + [Value长] + [Key] + [Value]。
元数据块元数据是Key-Value类型的值,但元数据块只保存元数据的Value值,元数据的Key值保存在第五项(元数据索引块)中。 该块由多个元数据值组成。
FileInfo块该块保存与HFile相关的一些信息。 FileInfo是以Key值排序Key-Value类型的值,基本格式为: KeyValue元素的个数 + (Key + Value类型id + Value) + (Key + Value类型id + Value) + ……
数据索引块该块的组成为: 索引块头 + (数据块在文件中的偏移 + 数据块长 + 数据块的第一个Key) + (数据块在文件中的偏移 + 数据块长 + 数据块的第一个Key) + ……
元数据索引块该块组成格式同数据块索引,只是部分的意义不一样,组成格式: 索引块头 + (元数据在文件中的偏移 + 元数据Value长 + 元数据Key) + (元数据在文件中的偏移 + 元数据Value长 + 元数据Key) + ……
HFile文件尾该块记录了其他各块在HFile文件中的偏移信息和其他一些元信息。组成格式如下: 文件尾 + Fileinfo偏移 + 数据块索引偏移 + 数据块索引个数 + 元数据索引偏移 + 元数据索引个数 + 数据块中未压缩数据字节数 + 数据块中全部数据的Key-Value个数 + 压缩代码标识 + 版本标识

6.3.2 WAL

Write Ahead Log | HLog

  • 一个文件

  • 0.94之前叫做HLog,存储在/hbase/.logs/目录中

  • 0.94之后存储在HDFS上的**/hbase/WALs/{HRegionServer_name}**中

  • 记录RegionServer 上所有的编辑信息(Puts/Deletes,属于哪个Region),在写入MemStore之前。

  • 理论上一个RegionServer上只有一个WAL实例,数据操作为串行,造成性能瓶颈。在1.0之后 ,可以通过使用底层HDFS的多管道实现了多WAL并行写入。提高了吞吐量(但是并行化是通过对多个Region进行分区实现的,如果只有一个Region那么该方案无效)下面是配置多WAL示例:hbase-site.xml 配置

<property>   
  <name>hbase.wal.provider</name>   
  <value>multiwal</value> 
</property>

6.4 BlockCache|HBase Block(了解)

  • 读缓存,数据被读取之后仍然缓存在内存中
  • 有LruBlockCache(效率较高,GC压力大)和BucketCache(效率较低,没有GC压力)两种BlockCache,默认为LruBlockCache
  • 每个RegionServer中只有一个BlockCache实例

6.5 HDFS

HDFS为HBase提供最终的底层数据存储服务,同时为HBase提供高可用(HLog存储在HDFS)的支持,具体功能概括如下:

提供元数据和表数据的磁层分布式存储服务

数据多副本,保证高可靠性和高可用性

献给每一个正在努力的我们,就算在忙,也要注意休息和饮食哦!我就是我,一个在互联网跌跌撞撞,摸爬滚打的热忱,给个三连吧~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值