Hadoop 将值写入文件而不移动到reducer
我有这样的记录输入, a | 1 | Y, b | 0 | N, c | 1 | N, d | 2 | Y, e | 1 | Y 现在,在mapper中,我必须检查第三列的值。如果是“Y”,则该记录必须直接写入输出文件,而无需将该记录移动到reducer,否则,“N”值记录必须移动到reducer进行进一步处理 所以, a | 1 | Y, d | 2 | Y, e | 1 | Y 不应去减速器,但 b | 0 | N, c | 1 | N 应该转到reducer,然后转到输出文件Hadoop 将值写入文件而不移动到reducer,hadoop,mapreduce,Hadoop,Mapreduce,我有这样的记录输入, a | 1 | Y, b | 0 | N, c | 1 | N, d | 2 | Y, e | 1 | Y 现在,在mapper中,我必须检查第三列的值。如果是“Y”,则该记录必须直接写入输出文件,而无需将该记录移动到reducer,否则,“N”值记录必须移动到reducer进行进一步处理 所以, a | 1 | Y, d | 2 | Y, e | 1 | Y 不应去减速器,但 b | 0 | N, c | 1 | N 应该转到reducer,然后转到输出文件 我怎样才能做
我怎样才能做到这一点呢?您可能要做的是将“Y”和“N”类型的记录从映射器中分离到两个不同的文件中 接下来,为两个新生成的“Y”和“N”类型的数据集运行saparate作业。 对于“Y”类型,将减缩器的数量设置为0,以便不使用减缩器。对于'N'类型,使用减缩器按照您想要的方式进行操作
希望这有帮助。在地图功能中,您将逐行获得输入。使用|作为分隔符,将其按照进行拆分。(确切地说,通过使用
String.split()
方法)
看起来像这样
String[] line = value.toString().split('|');
通过行[2]
然后,使用一个简单的if-else
语句,发出带有N值的输出以供进一步处理。看看这是否有效
public class Xxxx {
public static class MyMapper extends
Mapper<LongWritable, Text, LongWritable, Text> {
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
FileSystem fs = FileSystem.get(context.getConfiguration());
Random r = new Random();
FileSplit split = (FileSplit)context.getInputSplit();
String fileName = split.getPath().getName();
FSDataOutputStream out = fs.create(new Path(fileName + "-m-" + r.nextInt()));
String parts[];
String line = value.toString();
String[] splits = line.split(",");
for(String s : splits) {
parts = s.split("\\|");
if(parts[2].equals("Y")) {
out.writeBytes(line);
}else {
context.write(key, value);
}
}
out.close();
fs.close();
}
}
public static class MyReducer extends
Reducer<LongWritable, Text, LongWritable, Text> {
public void reduce(LongWritable key, Iterable<Text> values,
Context context) throws IOException, InterruptedException {
for(Text t : values) {
context.write(key, t);
}
}
}
/**
* @param args
* @throws IOException
* @throws InterruptedException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
conf.set("fs.default.name", "hdfs://localhost:9000");
conf.set("mapred.job.tracker", "localhost:9001");
Job job = new Job(conf, "Xxxx");
job.setJarByClass(Xxxx.class);
Path outPath = new Path("/output_path");
job.setMapperClass(MyMapper.class);
job.setReducerClass(MyReducer.class);
FileInputFormat.addInputPath(job, new Path("/input.txt"));
FileOutputFormat.setOutputPath(job, outPath);
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
公共类Xxxx{
公共静态类MyMapper扩展
映射程序{
public void映射(LongWritable键、文本值、上下文上下文)抛出IOException、InterruptedException{
FileSystem fs=FileSystem.get(context.getConfiguration());
随机r=新随机();
FileSplit split=(FileSplit)context.getInputSplit();
字符串文件名=split.getPath().getName();
FSDataOutputStream out=fs.create(新路径(fileName+“-m-”+r.nextInt());
字符串部分[];
字符串行=value.toString();
String[]splits=line.split(“,”);
用于(字符串s:拆分){
零件=s.split(“\\\\”);
如果(部分[2]。等于(“Y”){
out.writeBytes(行);
}否则{
编写(键、值);
}
}
out.close();
fs.close();
}
}
公共静态类MyReducer扩展
减速器{
public void reduce(可写长键、可写值、,
上下文)抛出IOException、InterruptedException{
对于(文本t:值){
context.write(key,t);
}
}
}
/**
*@param args
*@抛出异常
*@抛出中断异常
*@ClassNotFoundException
*/
公共静态void main(字符串[]args)引发IOException、ClassNotFoundException、InterruptedException{
//TODO自动生成的方法存根
Configuration conf=新配置();
conf.set(“fs.default.name”hdfs://localhost:9000");
conf.set(“mapred.job.tracker”,“localhost:9001”);
作业作业=新作业(配置,“Xxxx”);
job.setJarByClass(Xxxx.class);
路径输出路径=新路径(“/output_Path”);
setMapperClass(MyMapper.class);
job.setReducerClass(MyReducer.class);
addInputPath(作业,新路径(“/input.txt”);
setOutputPath(作业,输出路径);
系统退出(作业等待完成(真)?0:1;
}
}
这不太清楚。您只是不想运行reducer吗?我不想移动第三列值为“Y”的记录,剩余值应移动到reducer。因此,您希望映射程序将第三列值为“Y”的记录直接写入HDFS,而第三列值为“N”的记录只应进入reducer?如果有其他帮助,该如何操作?如果您执行context.write()如果你有一个减速机在你的工作中,它会被调用,如果或否则。对不起,我不太明白。