一起重新开始学大数据-Hbase篇-day 55 浅谈布隆过滤器、Hbase读写、Hbase的HA和Mapreduce读写Hbase数据

本文详细介绍了HBase中的布隆过滤器原理及其在提升查询性能中的作用,阐述了HBase的数据读写流程,包括写入时的MemStore与HLog,以及读取时的BlockCache与HFile。同时,讨论了HBase的高可用性(HA)机制,并展示了MapReduce如何读写HBase数据,包括从HBase读取数据到HDFS以及从HDFS写入HBase的示例代码。
摘要由CSDN通过智能技术生成
一起重新开始学大数据-Hbase篇-day 55 浅谈布隆过滤器、Hbase读写、Hbase的HA和Mapreduce读写Hbase数据

在这里插入图片描述

浅谈布隆过滤器


概述:
    Bloom Filter(布隆过滤器)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
   在计算机科学中,我们常常会碰到时间换空间或者空间换时间的情况,即为了达到某一个方面的最优而牺牲另一个方面。Bloom Filter在时间空间这两个因素之外又引入了另一个因素:错误率。在使用Bloom Filter判断一个元素是否属于某个集合时,会有一定的错误率。也就是说,有可能把不属于这个集合的元素误认为属于这个集合(False Positive),但不会把属于这个集合的元素误认为不属于这个集合(False Negative)。在增加了错误率这个因素之后,Bloom Filter通过允许少量的错误来节省大量的存储空间。
   它的用法其实是很容易理解的,我们拿个HBase中应用的例子来说下,我们已经知道rowKey存放在HFile中,那么为了从一系列的HFile中查询某个rowkey,我们就可以通过 Bloom Filter 快速判断 rowkey 是否在这个HFile中,从而过滤掉大部分的HFile,减少需要扫描的Block。


图解析:
  BloomFilter对于HBase的随机读性能至关重要,对于get操作以及部分scan操作可以剔除掉不会用到的HFile文件,减少实际IO次数,提高随机读性能。在此简单地介绍一下Bloom Filter的工作原理,Bloom Filter使用位数组来实现过滤,初始状态下位数组每一位都为0,如下图所示:
在这里插入图片描述
  假如此时有一个集合S = {x1, x2, … xn},Bloom Filter使用k个独立的hash函数,分别将集合中的每一个元素映射到{1,…,m}的范围。对于任何一个元素,被映射到的数字作为对应的位数组的索引,该位会被置为1。比如元素x1被hash函数映射到数字8,那么位数组的第8位就会被置为1。下图中集合S只有两个元素x和y,分别被3个hash函数进行映射,映射到的位置分别为(0,3,6)和(4,7,10),对应的位会被置为1:
在这里插入图片描述
  在假如要判断另一个元素是否是在此集合中,只需要被这3个hash函数进行映射,查看对应的位置是否有0存在,如果有的话,表示此元素肯定不存在于这个集合,否则有可能存在。下图所示就表示z肯定不在集合{x,y}中:
在这里插入图片描述
从上面的内容我们可以得知,Bloom Filter有两个很重要的参数

  • 哈希函数个数
  • 位数组的大小

布隆过滤器(Bloom Filter)在HBase中的作用
HFile 中和 Bloom Filter 相关的Block:

  • Scanned Block Section(扫描HFile时被读取):Bloom Block
  • Load-on-open-section(regionServer启动时加载到内存):BloomFilter Meta Block、Bloom Index Block
  • Bloom Block:Bloom数据块,存储Bloom的位数组
  • Bloom Index Block:Bloom数据块的索引
  • BloomFilter Meta Block:从HFile角度看bloom数据块的一些元数据信息,大小个数等等。

HBase中每个HFile都有对应的位数组,KeyValue在写入HFile时会先经过几个hash函数的映射,映射后将对应的数组位改为1,get请求进来之后再进行hash映射,如果在对应数组位上存在0,说明该get请求查询的数据不在该HFile中。

HFile中的Bloom Block中存储的就是上面说得位数组,当HFile很大时,Data Block 就会很多,同时KeyValue也会很多,需要映射入位数组的rowKey也会很多,所以为了保证准确率,位数组就会相应越大,那Bloom Block也会越大,为了解决这个问题就出现了Bloom Index Block,一个HFile中有多个Bloom Block(位数组),根据rowKey拆分,一部分连续的Key使用一个位数组。这样查询rowKey就要先经过Bloom Index Block(在内存中)定位到Bloom Block,再把Bloom Block加载到内存,进行过滤。

Hbase的读写


在这里插入图片描述
HBase读写流程:
写流程:
  首先由客户端(HBase shell、Java API)发起一个写请求。然后客户端会去连接ZK,在ZK里查找Meta表(记录了每张表的每一个region所储存的rowkey的范围)的位置,比如说在node1上,那么就会去连接node1,然后根据所要写入的数据的rowkey去和meta里的数据进行对比,找到该rowkey需要写入的region所在的regionserver,例如在node2,那么客户端就会去连接node2上的RS,然后将数据(是一个Put对象)写入,先将数据写入RS上的HLOG中,然后再将数据写入Region中的MemStore,当写完memstore后会立即返回(写请求到这就完成了,整个过程不需要HMaster参与:当Memstore中的数据达到128M则会触发Flush刷写操作形成storefile)

读流程:
  跟写流程差不多。不管是读或写,都需要根据所写入或读取的数据的Rowkey去结合ZK及Meta表中的数据定位到Rowkey所属的Region所在的RS,例如在node1.那么客户端将会去连接node1上面的RS,首先先从BLOCKCACHE中找,如果没有再去MemStore中找。如果再找不到则会去HFILE中查找如果所查找的数据所在的列簇设置了in_memory=true。则会将查找到的数据放入缓存

Client为了加快读写请求。会在第一次找到Meta的位置时,将其位置缓存


Hbase的HA(高可用)


在这里插入图片描述
HmasterHA启动

在node1或node2上再启动一个Hmaster ,cd /usr/local/soft/hbase-1.4.6/bin 执行 ./hbase-daemonsh start master

Mapreduce读写Hbase数据


在这里插入图片描述


注意:

若执行代码过程中显示找不到main找不到依赖
在pom.xml中添加标签如下,打包过程连带打包依赖

<build>
        <plugins>

            <!-- Java Compiler -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>


            <!-- 带依赖jar 插件-->
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

从Hbase中读取数据到HDFS

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class MRReadHBase {
    // 读取HBase students表数据 并统计每个班级的人数
    public static class MyMapper extends TableMapper<Text, IntWritable> {
        @Override
        protected void map(ImmutableBytesWritable key, Result value, Mapper<ImmutableBytesWritable, Result, Text, IntWritable>.Context context) throws IOException, InterruptedException {
            // 进入map任务中的key就是rowkey
            String rowkey = Bytes.toString(key.get());
            // 进入map任务中的value就是hbase中的一条数据
            byte[] row = value.getRow(); // 通过getRow也可以取出rowkey来
            String clazz = Bytes.toString(value.getValue("info".getBytes(), "clazz".getBytes()));
            context.write(new Text(clazz), new IntWritable(1));
        }
    }

    public static class MyReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
        @Override
        protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
            int cnt = 0;
            for (IntWritable value : values) {
                cnt++;
            }
            context.write(key, new IntWritable(cnt));
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        Configuration conf = new Configuration();
        conf.set("hbase.zookeeper.quorum","master:2181,node1:2181,node2:2181");
        Job job = Job.getInstance(conf);
        job.setJobName("MRReadHBase");
        job.setJarByClass(MRReadHBase.class);

        // 使用TableMapReduceUtil配置Map任务
        TableMapReduceUtil.initTableMapperJob("students"
                , new Scan()
                , MyMapper.class
                , Text.class
                , IntWritable.class
                , job
        );

        // 配置Reduce任务
        job.setReducerClass(MyReduce.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        // 配置输出路径
        FileOutputFormat.setOutputPath(job, new Path("/mrHBase01"));

        job.waitForCompletion(true);

    }
}

从本地HDFS中读取数据到Hbase

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.client.Mutation;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.mapred.TableOutputFormat;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

// 读取本地score.txt文件 计算每个学生的总分 并将结果写入HBase
public class MRWriteHBase {
    public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
        @Override
        protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
            String[] splits = value.toString().split(",");
            String rowkey = splits[0];
            int score = Integer.parseInt(splits[2]);
            context.write(new Text(rowkey), new IntWritable(score));
        }
    }

    public static class WriteHBase extends TableReducer<Text, IntWritable, NullWritable> {
        @Override
        protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, NullWritable, Mutation>.Context context) throws IOException, InterruptedException {
            int sum = 0; // 保存总分
            for (IntWritable value : values) {
                sum += value.get();
            }
            Put put = new Put(key.getBytes());
            put.addColumn("cf1".getBytes(), "ss".getBytes(), (sum + "").getBytes());
            context.write(NullWritable.get(), put);
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {

        Configuration conf = new Configuration();
        conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");
        Job job = Job.getInstance(conf);
        job.setJobName("MRWriteHBase");
        job.setJarByClass(MRWriteHBase.class);

        // 配置Map任务
        job.setMapperClass(MyMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        // 使用TableMapReduceUtil配置Reduce任务
        TableMapReduceUtil.initTableReducerJob(
                "sum_score"
                , WriteHBase.class
                , job
        );

        // 配置输入路径
        FileInputFormat.addInputPath(job,new Path("/mrHBaseInput1"));

        job.waitForCompletion(true);
    }
    /**编写代码后执行步骤
     * 在HBase中建表:create 'sum_score','cf1'
     * 将score.txt 上传到 /mrHBaseInput1
     * 打包上传jar包
     * hadoop jar HBase-1.0-jar-with-dependencies.jar com.shujia.Demo6MRWriteHBase
     */
}

从Hbase中读取数据到Hbase

package com.tiand7;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;

import java.io.IOException;

public class MRfromHbase {
        public static class Mymap extends TableMapper<Text,Text>{
                @Override
                protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
                        byte[] bytes = key.get();
                        String rowkey = Bytes.toString(bytes);
                        String clazz = Bytes.toString(value.getValue("info".getBytes(), "name".getBytes()));
                        context.write(new Text(rowkey),new Text(clazz));
                }
        }
        public static class MyReduce extends TableReducer<Text,Text,NullWritable>{
                @Override
                protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
                        Put put = new Put(key.getBytes());
                        for (Text value : values) {
                                put.addColumn("info".getBytes(),"name".getBytes(),value.getBytes());
                        }
                        context.write(NullWritable.get(),put);

                }
        }
        public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
                Configuration conf = new Configuration();
                conf.set("hbase.zookeeper.quorum", "master:2181,node1:2181,node2:2181");
                Job job = Job.getInstance(conf);
                job.setJobName("MRfromHbase");
                job.setJarByClass(MRfromHbase.class);

//                map
                TableMapReduceUtil.initTableMapperJob("students",new Scan(),Mymap.class,Text.class,Text.class,job);

//                reduce
                TableMapReduceUtil.initTableReducerJob("nametip",MyReduce.class,job);

                job.waitForCompletion(true);
        }

}

|
|
|
|

上一章-Hbase篇-day 54 Hbase介绍、shell、过滤器
下一章-Hbase篇-day 56 Phoenix
|
|
|
|
|

听说长按大拇指👍会发生神奇的事情呢!好像是下面的画面,听说点过的人🧑一个月内就找到了对象的💑💑💑,第二天买彩票中了大奖💴$$$,考试直接拿满分💯,颜值突然就提升了😎,虽然对你好像也不需要,你说是吧,吴彦祖🤵!

在这里插入图片描述在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你的动作太慢了!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值