Tôi đang cố gắng thực hiện sắp xếp thứ cấp trong mapreduce bằng khóa tổng hợp có chứa:
Vấn đề là sau khi sắp xếp tôi nhận được rất nhiều bộ giảm dựa trên toàn bộ khóa tổng hợp
Thông qua việc gỡ lỗi, tôi đã xác minh rằng mã băm và hàm so sánh là chính xác. Từ nhật ký gỡ lỗi, mỗi khối đến từ một bộ giảm tốc khác nhau, điều này cho biết việc nhóm hoặc phân vùng không thành công. Từ nhật ký gỡ lỗi:
14/12/14 00:55:12 THÔNG TIN phổ biếnitweet.EtanReducer: key=the voice
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: the voice: Thu Dec 11 17:51:03 +0000 2014
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: the voice: Thu Dec 11 17:51:03 +0000 2014
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: phím giọng nói kết thúc
14/12/14 00:55:12 THÔNG TIN phổ biếnitweet.EtanReducer: key=top gear
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: top gear: Thu Dec 11 17:51:04 +0000 2014
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: key top gear đã kết thúc
14/12/14 00:55:12 THÔNG TIN phổ biếnitweet.EtanReducer: key=truyện kinh dị Mỹ
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: truyện kinh dị Mỹ: Thu Dec 11 17:51:04 +0000 2014
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: câu chuyện kinh dị quan trọng của Mỹ đã kết thúc
14/12/14 00:55:12 THÔNG TIN phổ biếnitweet.EtanReducer: key=the voice
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: the voice: Thu Dec 11 17:51:04 +0000 2014
14/12/14 00:55:12 INFO phổ biếnitweet.EtanReducer: phím giọng nói kết thúc
Như bạn có thể thấy, bài phát biểu được gửi đến hai bộ giảm tốc khác nhau nhưng có dấu thời gian khác nhau. Bất kỳ trợ giúp sẽ được đánh giá rất cao. Các tổ hợp phím thuộc các lớp sau:
lớp công khai ProgramKey triển khai WritableComparable {
chương trình Chuỗi riêng tư;
riêng tư Dấu thời gian dài;
ProgramKey công khai() {
}
public ProgramKey(Chương trình chuỗi, Dấu thời gian dài) {
this.program = chương trình;
this.timestamp = dấu thời gian;
}
@Ghi đè
int công khai so sánhTo(ProgramKey o) {
kết quả int = chương trình.compareTo(o.program);
nếu (kết quả == 0) {
kết quả = timestamp.compareTo(o.timestamp);
}
return result;
}
@Ghi đè
public void write(DataOutput dataOutput) ném IOException {
WritableUtils.writeString(dataOutput, chương trình);
dataOutput.writeLong(dấu thời gian);
}
@Ghi đè
public void readFields(DataInput dataInput) ném IOException {
chương trình = WritableUtils.readString(dataInput);
dấu thời gian = dataInput.readLong();
}
Trình phân vùng, GroupingComparator và SortingComparator mà tôi đã triển khai là:
lớp công khai ProgramKeyPartitioner mở rộng Trình phân vùng {
@Ghi đè
public int getPartition(ProgramKey chương trìnhKey, TweetObject tweetObject, int numPartitions) {
int hash = chương trìnhKey.getProgram().hashCode();
phân vùng int = hàm băm % numPartitions;
trả lại phân vùng;
}
}
lớp công khai ProgramKeyGroupingComparator mở rộng WritableComparator {
ProgramKeyGroupingComparator() được bảo vệ() {
super(ProgramKey.class, true);
}
@Ghi đè
public int so sánh(WritableComparable a, WritableComparable b) {
ProgramKey k1 = (ProgramKey) a;
ProgramKey k2 = (ProgramKey) b;
return k1.getProgram().compareTo(k2.getProgram());
}
}
lớp công khai TimeStampComparator mở rộng WritableComparator {
được bảo vệ TimeStampComparator() {
super(ProgramKey.class, true);
}
@Ghi đè
public int so sánh(WritableComparable a, WritableComparable b) {
ProgramKey ts1 = (ProgramKey)a;
ProgramKey ts2 = (ProgramKey)a;
int result = ts1.getProgram().compareTo(ts2.getProgram());
nếu (kết quả == 0) {
kết quả = ts1.getTimestamp().compareTo(ts2.getTimestamp());
}
return result;
}
}
public static void main(String[] args) ném IOException,
InterruptedException, ClassNotFoundException {
//Tạo cấu hình
Cấu hình conf = Cấu hình mới();
//Tạo công việc
Công việc công việc = Công việc mới(conf, "test1");
job.setJarByClass(EtanMapReduce.class);
// Đặt phân vùng keyComparator và groupComparator
job.setPartitionerClass(ProgramKeyPartitioner.class);
job.setGroupingComparatorClass(ProgramKeyGroupingComparator.class);
job.setSortComparatorClass(TimeStampComparator.class);
// Thiết lập MapReduce
job.setMapperClass(EtanMapper.class);
job.setMapOutputKeyClass(ProgramKey.class);
job.setMapOutputValueClass(TweetObject.class);
job.setReducerClass(EtanReducer.class);
// Chỉ định khóa/giá trị
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(TweetObject.class);
//Đầu vào
FileInputFormat.addInputPath(công việc, inputPath);
job.setInputFormatClass(TextInputFormat.class);
//đầu ra
FileOutputFormat.setOutputPath(công việc, outDir);
job.setOutputFormatClass(TextOutputFormat.class);
// Xóa đầu ra nếu tồn tại
Hệ thống tệp hdfs = FileSystem.get(conf);
if (hdfs.exists(outputDir))
hdfs.delete(outputDir, true);
//Thực hiện công việc
logger.info("bắt đầu công việc");
int code = job.waitForCompletion(true) ? 0 : 1;
System.exit(mã);
}
biên tập...
Dường như có lỗi đánh máy trong TimeStampComparator của bạn... bạn đặt ts2 thành a trong khi lẽ ra nó phải được đặt thành b:
ProgramKey ts1 = (ProgramKey)a;
ProgramKey ts2 = (ProgramKey)a;
Khi nào bạn nên:
ProgramKey ts1 = (ProgramKey)a;
ProgramKey ts2 = (ProgramKey)b;
Điều này sẽ dẫn đến các cặp khóa/giá trị được sắp xếp không chính xác và làm mất hiệu lực giả định được đưa ra bởi bộ so sánh nhóm rằng các cặp khóa/giá trị đã được sắp xếp.
Đồng thời kiểm tra xem tên chương trình gốc có ở định dạng UTF-8 hay không, vì đó là những gì WritableUtils giả định. Trang mã mặc định của hệ thống của bạn có phải là UTF-8 không?
Tôi là một lập trình viên xuất sắc, rất giỏi!