2011-06-17 6 views
19

Zasadniczo całe pytanie znajduje się w tytule. Zastanawiam się, czy możliwe jest dołączanie do pliku znajdującego się na HDFS z wielu komputerów jednocześnie? Coś jak przechowywanie strumienia zdarzeń stale wytwarzanych przez wiele procesów. Zamówienie nie jest ważne.Czy można równolegle dołączać do pliku HDFS wielu klientów?

Przypominam, że przesłuchanie w jednej z prezentacji technicznych Google, że GFS obsługuje takie funkcje dołączania, ale próbuje niektórych ograniczonych testów z HDFS (albo z regularnym dopiskiem do pliku() lub z SequenceFile) nie wydaje się działać.

Dzięki,

+0

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

Odpowiedz

11

Nie sądzę, że jest to możliwe w HDFS. Nawet jeśli nie zależy Ci na kolejności rekordów, zależy ci na kolejności bajtów w pliku. Nie chcesz, aby pisarz A napisał częściowy zapis, który następnie zostanie uszkodzony przez pisarza B. Jest to trudny problem, który HDFS rozwiązuje samodzielnie, a więc nie.

Utwórz plik na jednego pisarza. Przekaż wszystkie pliki do dowolnego pracownika MapReduce, który musi odczytać te dane. Jest to znacznie prostsze i pasuje do projektu HDFS i Hadoop. Jeśli kod inny niż MapReduce musi odczytać te dane jako jeden strumień, należy kolejno przesyłać każdy plik lub napisać bardzo szybkie zadanie MapReduce w celu skonsolidowania plików.

+0

Dzięki. Chyba nie zdawałem sobie sprawy, że nie musi to być jeden plik na zadanie MapReduce. Napisanie jednego pliku na jeden komputer powinno być bardzo łatwe do wdrożenia, być może przy użyciu kolejki w pamięci zgodnie z sugestią w innej odpowiedzi, aby uniknąć blokowania. – maximdim

+4

@ Spike Tylko dla wyjaśnienia, że ​​GFS obsługuje jednoczesne dołączanie. Z ich artykułu GFS: "Rekordowy dodatek jest szeroko wykorzystywany przez nasze rozproszone aplikacje, w których wielu klientów na różnych maszynach jednocześnie dołącza do tego samego pliku." –

+0

Powinieneś otrzymać [wyjątek stwierdzający, że plik już istnieje] (https://issues.apache.org/jira/browse/HDFS-8177). Ten jira mówi: "HDFS obsługuje pojedynczy program piszący dla danego pliku." Możesz skonsolidować pliki zgodnie z sugestią zawartą w tej odpowiedzi, używając ['getmerge'] (https://hadoop.apache.org/docs/current/ hadoop-project-dist/hadoop-common/FileSystemShell.html # getmerge) – EthanP

4

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.

+0

Nie sądzę, że GFS obsługuje równoczesne dołączanie. BigTable nie potrzebuje tej funkcji, zapisuje pliki SSTable oddzielnie, a każdy plik jest własnością jednego procesu. "Zasadniczo nie można zrównoleglić we/wy" jest także fałszywą instrukcją. Jeśli otworzysz wiele plików HDFS, możesz pisać do nich równolegle i będzie działał szybciej, o ile twój klaster ma wolną pamięć IO (zakładając, że scenarzysta nie jest wąskim gardłem). –

+0

na pewno można wszystko sparametryzować, ale nie ma sensu. Ponieważ twój dysk twardy ma tylko jedną głowę. Równoległe pisanie jest szybsze niż pozwolenie na wypukłe pisanie 10 plików równolegle. –

+0

To jest dość dobry opis: http://stackoverflow.com/questions/1367689/interleaved-parallel-file-read-slower-than-sequential-read –

Powiązane problemy