我正在使用mongo-hadoop connector,这使得Hadoop可以从MongoDB获取数据并将其保存到MongoDB中。我发现在MongoDB数据进行Hadoop Map-Reduce作业后,MongoDB数据已重复。
环境:Hadoop版本为3.1.1,MongoDB版本为4.0.4,mongo-hadoop连接器为mongo-hadoop-core-2.0.2.jar,mongo-java-driver-3.8.2.jar和Docker版本是18.03.1-ce。有两个名为server1,server2的本地服务器。它们具有公共IP,因此我可以在它们上建立hadoop集群或mongo分片环境。为了运行hadoop和MongoDB,我使用了Docker和Docker编排,以便容器可以在覆盖网络上相互交换数据包。服务器1具有Hadoop主容器,Hadoop slave1容器,MongoDB路由器容器,MongoDB配置器容器,服务器2具有Hadoop slave2容器,Hadoop slave3容器以及MongoDB shard1容器,MongoDB shard2容器。 MongoDB具有30MB tsv data file,块大小为8MB。当我设置Hadoop集群和MongoDB分片时,我让容器通过它们的容器名称相互连接(例如,Hadoop主机发送带有'slave1'或'mongorouter'的ping。它工作良好)。
问题:问题是,使用MongoDB数据(30MB数据)设置了Hadoop集群和MongoDB Sharding(分片集合只是一个)WordCount MR作业后,WordCount结果被重复,详细地,数据乘以2.例如,正常结果为[a 1,b 2],然后重复结果为[a 2,b 4]。如果我创建另一个分片集合(相同的30MB数据,相同的代码,相同的数据库,只是不同的集合名称,所以分片的集合为两个。MR作业仅使用新的分片的集合),那么结果将乘以3([a 3, b 6])。如果我以相同的方式添加更多分片集合,则结果将成倍增加。如果我没有设置Mongo分片环境,那么结果就是我所期望的。我真的不知道发生了什么。我注意到MongoCollectionSpliter正在增加。分片越多,MR结果中的MongoCollectionSpliter就越多(我在下面附上了日志)
这是WordCount MR代码。
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.conf.Configuration;
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.bson.BSONObject;
import org.bson.BasicBSONObject;
import com.mongodb.hadoop.MongoInputFormat;
import com.mongodb.hadoop.MongoOutputFormat;
import com.mongodb.hadoop.io.BSONWritable;
import com.mongodb.hadoop.util.MongoConfigUtil;
public class BigdataBench{
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
MongoConfigUtil.setInputURI(conf, "mongodb://" + args[0]);
MongoConfigUtil.setOutputURI(conf, "mongodb://" + args[1]);
Job job = Job.getInstance(conf, "WordCount");
job.setJarByClass(BigdataBench.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(BSONWritable.class);
job.setInputFormatClass(MongoInputFormat.class);
job.setOutputFormatClass(MongoOutputFormat.class);
job.waitForCompletion(true);
}
public static class Map extends Mapper<Object, BSONObject, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private final Text dataOutput = new Text();
public void map(Object key, BSONObject value, Context context) throws IOException, InterruptedException {
String data = value.get("data").toString();
for(String whiteSpaceSplit : data.split(" ")) {
String[] tapSplit = whiteSpaceSplit.split("\t");
for(String split : tapSplit) {
dataOutput.set(split);
context.write(dataOutput, one);
}
}
}
}
public static class Reduce extends Reducer<Text, IntWritable, Text, BSONWritable> {
private BSONWritable reduceResult = new BSONWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
BasicBSONObject output = new BasicBSONObject();
int sum = 0;
for(IntWritable s : values) {
sum+=s.get();
}
String wordCount = String.valueOf(sum);
output.put("word", wordCount);
reduceResult.setDoc(output);
context.write(key, reduceResult);
}
}
}
我把问题安排成矩阵。
MR结果太长,因此我将其放入this google doc。
如果您有相同的问题或解决方案,请回答并帮助我。预先感谢。