栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

肝到半夜3点,上亿行数据,秒级查询

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

肝到半夜3点,上亿行数据,秒级查询

一.背景

当前有一个大约10G的txt文本文件,数据格式如下

uid        phone
10位数字  11位数字

需求是要根据uid做到秒级的查询,显示其对应的phone

二.思路

将所有的数据按照id做一个排序
然后将排序好的数据做二分查找(理论上可以1秒以内)

三.技术选型 1排序

普通单机排序肯定不行了,跑的话得跑老长时间
所以选择最近刚刚学的hadoop

2二分查找

在排好序的基础上进行二分查询
这种算法就算是全地球的数据加起来也能秒出
但是遇到的问题是,如何做到文件的随机读取呢?
经过一番百度与前辈的指导找到了java随机读取文件的api RandomAccessFile

四.实现 1.排序

将下面的代码放到集群上跑个半小时就完成了排序

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

import java.io.IOException;


public class Sort {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        //参数解析器(这个一定要放在job创建之前!!!!)
        GenericOptionsParser optionsParser = new GenericOptionsParser(conf,args);
        String[] remainingArgs = optionsParser.getRemainingArgs();
        Job job = Job.getInstance(conf,"long类型数据排序");

        job.setJarByClass(Sort.class);
        job.setMapperClass(SortMapper.class);
        job.setReducerClass(SortReducer.class);

        job.setOutputKeyClass(LongWritable.class);
        job.setOutputValueClass(LongWritable.class);

        String[] input = remainingArgs[0].split(",");
        for(String filePath:input){
            FileInputFormat.addInputPath(job,new Path(filePath));
        }
        //指定输出结果文件路径
        FileOutputFormat.setOutputPath(job,new Path(remainingArgs[1]));
        //指定job执行模式(等待任务执行完成后,提交任务的客户端才会退出!)
        System.exit(job.waitForCompletion(true) ? 0 : 1);

    }
    public static class SortMapper extends Mapper {
        private LongWritable resKey = new LongWritable();
        private LongWritable resValue = new LongWritable();
        private long key;
        private long val;
        @Override
        protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            String[] split = value.toString().split("t");
            //没切分成功的也直接跳过
            if(split.length!=2){
                return;
            }

            //对长度不正确的直接跳过
            if(split[0].length()!=11||split[1].length()!=10){
                System.out.println("-------长度不正确的脏数据---------");
                System.out.println("脏数据key--->"+split[1]);
                System.out.println("脏数据value--->"+split[0]);
                return;
            }

            try {
                resKey.set(Long.parseLong(split[1]));
                resValue.set(Long.parseLong(split[0]));
            } catch (NumberFormatException e) {
                System.out.println("-------非数字的脏数据直接跳过---------");
                System.out.println("脏数据key--->"+split[1]);
                System.out.println("脏数据value--->"+split[0]);
                return;
            }
            context.write(resKey,resValue);
        }
    }
    public static class SortReducer extends Reducer {
        @Override
        protected void reduce(LongWritable key, Iterable values, Context context) throws IOException, InterruptedException {
            for(LongWritable val :values){
                context.write(key,val);
            }
        }
    }
}
2.二分法(文件随机读取)

这里仅放了文件随机读写的代码,这个方法是最核心的,二分法百度一大堆

	//这个方法是文件随机读取的核心
    public static String readByRowNum(long rowNum,int rowByte,File fin) {
        byte[] buf = new byte[0];
        try {
            RandomAccessFile ras = new RandomAccessFile(fin,"r");
            buf = new byte[rowByte];
            long totalOffset =  rowByte*(rowNum-1);
            //跳过一定的字节
            ras.seek(totalOffset);
            //从跳过字节开始的地方开始读取
            ras.read(buf,0,rowByte);
        } catch (IOException e) {
            return null;
        }
        return new String(buf);
    }
五.总结

做这个小项目的最大收获就是了解到了java的文件随机读写在处理大文件的时候可以很方便
有任何技术问题的大家可以私信我,一起进步.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/318200.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号