前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Hadoop基础教程-第7章 MapReduce进阶(7.7 MapReduce 全排序)

Hadoop基础教程-第7章 MapReduce进阶(7.7 MapReduce 全排序)

作者头像
程裕强
发布于 2022-05-06 10:49:34
发布于 2022-05-06 10:49:34
23400
代码可运行
举报
运行总次数:0
代码可运行

第7章 MapReduce进阶

7.7 MapReduce 全排序

7.7.1 全排序方法介绍

MapReduce默认只是保证同一个分区内的Key是有序的,但是不保证全局有序。如果我们将所有的数据全部发送到一个Reduce,那么不就可以实现结果全局有序。所以前文7.6节二次排序已经实现了最终结果有序,也就是全排序。 MapReduce全排序的方法1: 每个map任务对自己的输入数据进行排序,但是无法做到全局排序,需要将数据传递到reduce,然后通过reduce进行一次总的排序,但是这样做的要求是只能有一个reduce任务来完成。

并行程度不高,无法发挥分布式计算的特点。

MapReduce全排序的方法2:

针对方法1的问题,现在介绍方法2来进行改进;

使用多个partition对map的结果进行分区,且分区后的结果是有区间的,将多个分区结果拼接起来,就是一个连续的全局排序文件。

Hadoop自带的Partitioner的实现有两种,一种为HashPartitioner, 默认的分区方式,计算公式 hash(key)%reducernum,另一种为TotalOrderPartitioner, 为排序作业创建分区,分区中数据的范围需要通过分区文件来指定。分区文件可以人为创建,如采用等距区间,如果数据分布不均匀导致作业完成时间受限于个别reduce任务完成时间的影响,该方法需要人工干预,缺少自动化。也可以通过抽样器,先对数据进行抽样,根据数据分布生成分区文件,避免数据倾斜。

常见采样器

  • IntervalSampler 以一定的间隔定期从划分中选择key,对有排序的数据来说更好
  • RandomSameler 以指定的采样率均匀的从数据集中选择样本
  • SplitSampler 只采样一个分片的前n条记录,所以不适合有排序的数据

7.7.2准备数据

编写生成测试数据的脚本

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@node1 data]# vi genData.sh
[root@node1 data]# cat genData.sh
#!/bin/sh

for i in {1..100000};do
    echo -e $RANDOM'\t'$RANDOM
done;

其中,$RANDOM 是Shell内置的,用于生成五位内的随机正整数。

执行下面命令生成测试数据 sh genData.sh > genData.txt

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@node1 data]# sh genData.sh > genData.txt
[root@node1 data]# tail -10 genData.txt 
6958    15414
9321    7638
4028    9313
2666    2903
17318   26805
8430    9119
20876   25596
26221   22424
32196   10570
606 6683

执行下面命令将生成的数据上传到HDFS hdfs dfs -put genData.txt input

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@node1 data]# hdfs dfs -put genData.txt input
[root@node1 data]# hdfs dfs -ls input
Found 5 items
-rw-r--r--   3 root hbase        333 2017-06-23 16:11 input/books.txt
-rw-r--r--   3 root hbase         82 2017-06-23 11:04 input/dept.txt
-rw-r--r--   3 root hbase        513 2017-06-23 11:04 input/emp.txt
-rw-r--r--   3 root hbase    1332178 2017-06-26 10:15 input/genData.txt
-rw-r--r--   3 root hbase  871353053 2017-06-23 14:19 input/ncdc.txt

创建分区存放目录 hdfs dfs -mkdir partition

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@node1 ~]# hdfs dfs -mkdir partition
[root@node1 ~]# hdfs dfs -ls /user/root
Found 3 items
drwxr-xr-x   - root hbase          0 2017-06-26 13:49 /user/root/input
drwxr-xr-x   - root hbase          0 2017-06-26 15:11 /user/root/output
drwxr-xr-x   - root hbase          0 2017-06-26 15:29 /user/root/partition

7.7.3 编程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package cn.hadron.mr.sort;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
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.input.KeyValueTextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.partition.InputSampler;
import org.apache.hadoop.mapreduce.lib.partition.TotalOrderPartitioner;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import java.io.IOException;

public class TotalOrder extends Configured implements Tool {
    /**
     * Mapper
     */
    public static class TotalOrderMapper extends Mapper<Text, Text, Text, Text> {
        @Override
        protected void map(Text key, Text value, Context context) throws IOException, InterruptedException {
            //IntWritable intWritable = new IntWritable(Integer.parseInt(key.toString()));
            context.write(key, new Text(key+"\t"+value));
        }
    }

    /**
     * Reducer
     */
    public static class TotalOrderReducer extends Reducer<Text, Text, Text, NullWritable> {
        @Override
        protected void reduce(Text key, Iterable<Text> values, Context context)
                throws IOException, InterruptedException {
            for (Text value : values)
                context.write(value, NullWritable.get());
        }
    }

    /**
     * Comparator
     */
    public static class KeyComparator extends WritableComparator {
        protected KeyComparator() {
            super(Text.class, true);
        }

        @Override
        public int compare(WritableComparable k1, WritableComparable k2) {
            return k1.compareTo(k2);
    /*      int v1 = Integer.parseInt(k1.toString());
            int v2 = Integer.parseInt(k2.toString());
            return v1 - v2;*/
        }
    }

    @Override
    public int run(String[] args) throws Exception {
        System.setProperty("HADOOP_USER_NAME", "root");
        //Configuration config = new Configuration();
        Configuration config = getConf();
        // 设置fs.defaultFS
        config.set("fs.defaultFS", "hdfs://192.168.1.117:8020");
        // 设置yarn.resourcemanager节点
        config.set("yarn.resourcemanager.hostname", "hds119");

        FileSystem fs = FileSystem.get(config);
        Job job = Job.getInstance(config);
        job.setJarByClass(TotalOrder.class);
        // 文件输入格式,第一个\t(tab键)之前的所有内容当做Key(Text),之后全部作为Value(Text)。
        job.setInputFormatClass(KeyValueTextInputFormat.class);
        job.setSortComparatorClass(KeyComparator.class);

        // 输入输出路径
        Path inpath=new Path("/user/root/input/genData.txt");
        FileInputFormat.addInputPath(job, inpath);
        Path outpath = new Path("/user/root/output/");
        if (fs.exists(outpath)) {
            fs.delete(outpath, true);
        }
        FileOutputFormat.setOutputPath(job, outpath);

        job.setMapperClass(TotalOrderMapper.class);
        job.setReducerClass(TotalOrderReducer.class);

        job.setNumReduceTasks(3);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(NullWritable.class);

        //设置分区文件存放路径
        TotalOrderPartitioner.setPartitionFile(job.getConfiguration(), new Path("/user/root/myPartition/"));

        job.setPartitionerClass(TotalOrderPartitioner.class);

        //参数:被选中概论0.1,选择的样本数,最大读取InputSplit数
        InputSampler.Sampler<Text,Text> sampler = new InputSampler.RandomSampler<>(0.1, 1000, 10);
        //写入分区文件
        InputSampler.writePartitionFile(job, sampler);

        job.setJobName("TotalOrder");

        boolean f = job.waitForCompletion(true);
        System.out.println(f);
        return f ? 0 : 1;
    }

    public static void main(String[] args) throws Exception {
        int exitCode = ToolRunner.run(new TotalOrder(), args);
        System.exit(exitCode);
    }
}

7.7.4 运行结果

Eclipse运行结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
log4j:WARN No appenders could be found for logger (org.apache.hadoop.util.Shell).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
true

查看HDFS输出结果 hdfs dfs -ls output

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@hds117 data]# hdfs dfs -ls output
Found 4 items
-rw-r--r--   3 root hbase          0 2017-06-26 16:09 output/_SUCCESS
-rw-r--r--   3 root hbase     390480 2017-06-26 16:09 output/part-r-00000
-rw-r--r--   3 root hbase     375603 2017-06-26 16:09 output/part-r-00001
-rw-r--r--   3 root hbase     366094 2017-06-26 16:09 output/part-r-00002

hdfs dfs -cat /user/root/output/part-r-00000|head -n 10 hdfs dfs -cat /user/root/output/part-r-00001|head -n 10 hdfs dfs -cat /user/root/output/part-r-00002|head -n 10

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@hds117 ~]# hdfs dfs -cat /user/root/output/part-r-00000|head -n 10
0   12553
0   11024
0   20589
0   17571
1   32756
1   29087
1   26260
1   4495
cat: Unable to write to output stream.
[root@hds117 ~]# hdfs dfs -cat /user/root/output/part-r-00001|head -n 10
19975   30234
19975   23946
19975   29221
19975   30553
19976   4200
19977   32477
19977   32217
19978   6330
cat: Unable to write to output stream.
[root@hds117 ~]# hdfs dfs -cat /user/root/output/part-r-00002|head -n 10
29601   3263
29601   28477
29601   8625
29601   7689
29601   28880
29602   24693
29602   23077
29602   15098
cat: Unable to write to output stream.
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Spring Security 4 Hibernate整合 注解和xml例子(带源码)
下一篇文章:Spring Security 4 整合Hibernate Bcrypt密码加密(带源码)
明明如月学长
2021/08/27
1.1K0
Spring Security 4 Hibernate整合 注解和xml例子(带源码)
SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制
根据文章内容总结的摘要
林老师带你学编程
2018/01/04
4.2K0
SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制
重学SpringBoot3-集成Spring Security(二)
在上一节中,我们讨论了Spring Security 的认证功能,通过实现用户身份验证来确保系统的安全性。而在本节中,我们将深入了解授权机制,如何控制用户在系统中可以访问的资源和操作。
CoderJia
2024/10/18
3800
重学SpringBoot3-集成Spring Security(二)
springmvc、spring、hibernate整合示例
在mysql数据库中建立一个user表,已对user的增删改查为例,整合springmvc、spring、hibernate。 1.web.xml中的配置:①spring监听器;②spring mvc的servlet;③字符编码过滤器。 <!-- spring 监听器的配置 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <c
yawn
2018/03/14
1.2K0
Spring Security 4 使用@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全(带源码)
【相关已翻译的本系列其他文章,点击分类里面的spring security 4】
明明如月学长
2021/08/27
2.7K0
Spring Security 4 基于角色的登录例子(带源码)
原文网址: http://websystique.com/spring-security/spring-security-4-role-based-login-example/
明明如月学长
2021/08/27
1.2K0
Spring+SpringMVC+Hibernate简单整合(转)
SpringMVC又一个漂亮的web框架,他与Struts2并驾齐驱,Struts出世早而占据了一定优势,下面同样做一个简单的应用实例,介绍SpringMVC的基本用法,接下来的博客也将梳理一下Struts2和SpringMVC的一些异同,通过梳理和旧知识的联系,让学习的成本变低,花很短的时间就可以了解一门貌似新的技术,其实本质没变。
yaohong
2019/09/11
8630
Spring Security 4 自定义登录表单 注解和XML例子(带源码)
上一篇文章: Spring Security 4 Hello World 基于注解 和 XML 例子  下一篇:Spring Security 4 退出 示例
明明如月学长
2021/08/27
8520
SpringBoot入门建站全系列(十二)Spring Security使用token做认证
Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。
品茗IT
2019/08/14
3.4K0
Spring Security和JWT实现登录授权认证
IUserService的实现类,注册时会将用户权限设置为ROLE_USER,同时将密码使用BCrypt加密
朝雨忆轻尘
2019/06/18
4.7K2
Spring MVC 4 文件上传下载 Hibernate+MySQL例子 (带源码)
【本系列其他教程正在陆续翻译中,点击分类:spring 4 mvc 进行查看。源码下载地址在文章末尾。】
明明如月学长
2021/08/27
6460
重学SpringBoot3-集成Spring Security(四)
在现代应用开发中,安全性和数据管理是两大重要模块。Spring Security 提供了全面的安全解决方案,而 Spring Data JPA 则简化了与数据库的交互。将两者结合,可以在保护应用的同时,轻松实现基于用户身份的访问控制、权限管理和安全的数据存储操作。
CoderJia
2024/10/20
3320
重学SpringBoot3-集成Spring Security(四)
SpringBoot整合SpringSecurity简单实现登入登出从零搭建
技术栈 : SpringBoot + SpringSecurity + jpa + freemark ,完整项目地址 : https://github.com/EalenXie/spring-security-login
EalenXie
2020/09/21
5.3K0
SpringBoot整合SpringSecurity简单实现登入登出从零搭建
Spring整合HibernateJPA
现如今的ORM框架还是比较多的比如Hibernate,TopLink以及OpenJPA等等,为了简化ORM框架的使用,JPA随之产生。
Java鱼头
2022/12/01
3981
React.js 集成 Spring Boot 开发 Web 应用
使用文档: https://nowa-webpack.github.io/nowa/
一个会写诗的程序员
2018/08/17
3.2K0
React.js  集成 Spring Boot 开发 Web 应用
spring之整合Hibernate
这里需要说明的是table="SH_BOOK"中SH是表的前缀,我们在写hql语句时不用带上,系统会自动识别。
西西嘛呦
2020/08/26
4770
spring之整合Hibernate
struts2+spring+hibernate整合步骤(1)
struts2、hibernate、spring所需jar包 struts-core-2.x.x.jar ----struts核心包 xwork-core-2.x.x.jar -----身体ruts在其撒很难过构建 ognl-2.6.x.jar ----对象导航语言 freemarker-2.3.x.jar ------struts2的ui标签的模板使用 commons-fileupload-1.2.x.jar ----文件上传组件 2.1.6版本后需加入此文件 str
Java帮帮
2018/03/15
7380
SpringMVC+Hibernate4
 1) /SpringMVCHibernate4/src/main/webapp/view/index.jsp
py3study
2020/01/08
3620
Spring Security 4 Hello World 基于注解 和 XML 例子(带源码)
原文:http://websystique.com/spring-security/spring-security-4-hello-world-annotation-xml-example/
明明如月学长
2021/08/27
5180
详细介绍SpringBoot整合SpringSecurity
  本文我们来详细给小伙伴们介绍下SpringBoot整合SpringSecurity的过程,用到的技术为:SpringBoot2.2.1+SpringSecurity+SpringDataJPA+jsp来整合。
用户4919348
2019/12/11
1.1K0
详细介绍SpringBoot整合SpringSecurity
推荐阅读
相关推荐
Spring Security 4 Hibernate整合 注解和xml例子(带源码)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档