Google powinien mieć trochę bardziej zaawansowany system plików, który obsługuje wiele bardziej swobodny dostęp lepiej niż HDFS. Korzystają z BigTable znacznie częściej i obszerniej, co wymaga szybszej modyfikacji bloków i współbieżnego odczytu/zapisu bloku. Ale faktycznie możesz zaimplementować coś podobnego. Ostatnio zrobiłem to, pisząc webcrawlera.
Zasadniczo nie można sparaliżować IO. Więc musisz użyć kolejki i sekwencyjnie dołączyć do pliku sekwencji.
private final ConcurrentLinkedQueue<FetchResult> queue = new ConcurrentLinkedQueue<FetchResult>();
private final Configuration conf = new Configuration();
private SequenceFile.Writer writer = null;
public boolean running = true;
public FetchResultPersister() throws IOException {
FileSystem fs = FileSystem.get(conf);
Path out = new Path("files/crawl/result.seq");
fs.delete(out, true);
writer = new SequenceFile.Writer(fs, conf, out, Text.class, Text.class);
}
public final void add(final FetchResult result) {
queue.offer(result);
}
@Override
public final void run() {
long retrieved = 0L;
while (running) {
final FetchResult poll = queue.poll();
if (poll != null) {
try {
writer.append(new Text(poll.url), asText(poll.outlinks));
retrieved++;
if (retrieved % 100 == 0) {
System.out
.println("Retrieved " + retrieved + " sites!");
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// close etc omitted
}
Głównym założeniem jest to, że dysk IO nie blokuje obliczeń.
Zasadniczo używasz tylko ConcurrentLinkedQueue
, który jest zsynchronizowany i dodajesz wyniki z różnych wątków. Jak widać, jest to również uruchomione w wątku, polling dla nowych wyników do zapisu w pliku sekwencji.
Jestem pewien, że GFS obsługuje te rzeczy natywnie, HDFS nie (w tym momencie) nie.
Oto kilka szczegółów tła, dlaczego append nie jest to możliwe, jeszcze: [Plik Dołącza do HDFS] (http://www.cloudera.com/blog/2009/07/file-appends-in-hdfs) – Dag