Εκμάθηση HDFS: Architecture, Read & Write Operaσμού

⚡ Έξυπνη Σύνοψη

Το HDFS είναι το κατανεμημένο επίπεδο αποθήκευσης του Hadoop, το οποίο χωρίζει πολύ μεγάλα αρχεία σε αναπαραγόμενα μπλοκ σε εμπορικά μηχανήματα, έτσι ώστε ένα μόνο NameNode tracks μεταδεδομένα, ενώ πολλά DataNodes εξυπηρετούν αξιόπιστα αιτήματα ανάγνωσης και εγγραφής.

  • 🔘 Archiδομή: Το NameNode διατηρεί την εικόνα του χώρου ονομάτων και το αρχείο καταγραφής επεξεργασίας, ενώ το DataNode αποθηκεύει τα πραγματικά αντίγραφα μπλοκ.
  • ☑️ Μέγεθος μπλοκ: Το Hadoop 1.x είχε προεπιλεγμένα μπλοκ 64 MB, ενώ τα Hadoop 2.x και 3.x είχαν προεπιλεγμένα μπλοκ 128 MB.
  • Αντιγραφή: Τρία αντίγραφα ανά μπλοκ είναι η προεπιλογή, κατανεμημένα σε racks, έτσι ώστε μια βλάβη υλικού να μην χάνει ποτέ δεδομένα.
  • 🧪 Διαδρομή ανάγνωσης: Τα FSDataInputStream και DFSInputStream ανακτούν τις θέσεις των μπλοκ από το NameNode και, στη συνέχεια, μεταδίδουν ροή byte απευθείας από τα DataNodes.
  • Διαδρομή εγγραφής: Το DFSOutputStream τοποθετεί πακέτα σε ουρά, το DataStreamer δημιουργεί έναν αγωγό DataNode και μια ουρά επικύρωσης προστατεύει από την απώλεια πακέτων.
  • 🧭 Επιλογές πρόσβασης: Το org.apache.hadoop.fs Java Το API και το κέλυφος dfs του hdfs καλύπτουν και τα δύο λειτουργίες ανοίγματος, ανάγνωσης, εγγραφής και κλεισίματος.

Εκμάθηση HDFS

Τι είναι το HDFS;

Το HDFS είναι ένα κατανεμημένο σύστημα αρχείων για την αποθήκευση πολύ μεγάλων αρχείων δεδομένων, το οποίο εκτελείται σε συμπλέγματα βασικού υλικού. Είναι ανεκτικό σε σφάλματα, επεκτάσιμο και εξαιρετικά απλό στην επέκταση. Το Hadoop συνοδεύεται από το HDFS (Hadoop Distributed File System).

Όταν τα δεδομένα υπερβαίνουν τη χωρητικότητα αποθήκευσης σε ένα μόνο φυσικό μηχάνημα, είναι απαραίτητο να τα διαιρέσουμε σε έναν αριθμό ξεχωριστών μηχανημάτων. Ένα σύστημα αρχείων που διαχειρίζεται συγκεκριμένες λειτουργίες αποθήκευσης σε ένα δίκτυο μηχανών ονομάζεται κατανεμημένο σύστημα αρχείων. Το HDFS είναι ένα τέτοιο λογισμικό.

ΚΑΕ Archiδομή

Ένα σύμπλεγμα HDFS αποτελείται κυρίως από ένα NameNode που διαχειρίζεται τα μεταδεδομένα του συστήματος αρχείων και Κόμβοι δεδομένων που αποθηκεύουν τα πραγματικά δεδομένα.

  • NameNode: Το NameNode μπορεί να θεωρηθεί ως ο κύριος κόμβος του συστήματος. Διατηρεί το δέντρο του συστήματος αρχείων και τα μεταδεδομένα για όλα τα αρχεία και τους καταλόγους που υπάρχουν στο σύστημα. Δύο αρχεία, η «εικόνα namespace» και το «αρχείο καταγραφής επεξεργασιών», χρησιμοποιούνται για την αποθήκευση πληροφοριών μεταδεδομένων. Το NameNode γνωρίζει όλα τα DataNodes που περιέχουν μπλοκ δεδομένων για ένα δεδομένο αρχείο, ωστόσο, δεν αποθηκεύει μόνιμα τις θέσεις των μπλοκ. Αυτές οι πληροφορίες ανακατασκευάζονται κάθε φορά από τα DataNodes κατά την εκκίνηση του συστήματος.
  • DataNode: Τα DataNodes είναι slaves που βρίσκονται σε κάθε μηχάνημα σε ένα cluster και παρέχουν τον πραγματικό χώρο αποθήκευσης. Είναι υπεύθυνα για την εξυπηρέτηση αιτημάτων ανάγνωσης και εγγραφής από τους πελάτες.

Επειδή ένα μόνο NameNode θα αποτελούσε μοναδικό σημείο αποτυχίας, τα τρέχοντα clusters εκτελούν ένα ενεργό NameNode παράλληλα με ένα εφεδρικό NameNode που μοιράζεται το αρχείο καταγραφής επεξεργασιών μέσω ενός quorum JournalNodes, με αυτόματη ανακατεύθυνση μεταξύ των δύο.

Οι λειτουργίες ανάγνωσης και εγγραφής στο HDFS λειτουργούν σε επίπεδο μπλοκ. Τα αρχεία δεδομένων στο HDFS χωρίζονται σε κομμάτια μεγέθους μπλοκ, τα οποία αποθηκεύονται ως ανεξάρτητες μονάδες. Το προεπιλεγμένο μέγεθος μπλοκ είναι 64 MB στο Hadoop 1.x. Από το Hadoop 2.x και μετά, το προεπιλεγμένο μέγεθος dfs.blocksize είναι 128 MB.

Το HDFS λειτουργεί με βάση την έννοια της αντιγραφής δεδομένων, όπου δημιουργούνται πολλαπλά αντίγραφα μπλοκ δεδομένων και κατανέμονται σε κόμβους σε όλο το σύμπλεγμα, ώστε να επιτρέπεται η υψηλή διαθεσιμότητα δεδομένων σε περίπτωση βλάβης του κόμβου. Ο προεπιλεγμένος συντελεστής αντιγραφής είναι τρία (dfs.replication), και όταν ένα DataNode σταματά να στέλνει παλμούς, το NameNode αντιγράφει αυτόματα τα μπλοκ του αλλού.

Γνωρίζεις? Ένα αρχείο σε HDFS, το οποίο είναι μικρότερο από ένα μπλοκ, δεν καταλαμβάνει την πλήρη αποθήκευση ενός μπλοκ.

Διάβασε Operation σε HDFS

Ένα αίτημα ανάγνωσης δεδομένων εξυπηρετείται από το HDFS, το NameNode και το DataNodes. Ας ονομάσουμε τον αναγνώστη «client». Το παρακάτω διάγραμμα απεικονίζει τη λειτουργία ανάγνωσης αρχείου στο Hadoop.

Ροή δεδομένων λειτουργίας ανάγνωσης HDFS μεταξύ πελάτη, NameNode και DataNodes

  1. Ένας πελάτης ξεκινά ένα αίτημα ανάγνωσης καλώντας τη μέθοδο 'open()' του αντικειμένου FileSystem. Πρόκειται για ένα αντικείμενο τύπου DistributedFileSystem.
  2. Αυτό το αντικείμενο συνδέεται με το NameNode χρησιμοποιώντας RPC και λαμβάνει πληροφορίες μεταδεδομένων, όπως τις τοποθεσίες των μπλοκ του αρχείου. Λάβετε υπόψη ότι αυτές οι διευθύνσεις είναι των πρώτων μπλοκ ενός αρχείου.
  3. Σε απάντηση σε αυτό το αίτημα μεταδεδομένων, επιστρέφονται οι διευθύνσεις των DataNodes που έχουν ένα αντίγραφο αυτού του μπλοκ.
  4. Μόλις ληφθούν οι διευθύνσεις των DataNodes, ένα αντικείμενο τύπου FSDataInputStream επιστρέφεται στον client. Το FSDataInputStream περιέχει το DFSInputStream το οποίο φροντίζει για τις αλληλεπιδράσεις με το DataNode και το NameNode. Στο βήμα 4 που φαίνεται στο παραπάνω διάγραμμα, ένας client καλεί τη μέθοδο 'read()' η οποία προκαλεί το DFSInputStream να δημιουργήσει μια σύνδεση με το πρώτο DataNode που περιέχει το πρώτο μπλοκ ενός αρχείου.
  5. Τα δεδομένα διαβάζονται με τη μορφή ροών όπου ο πελάτης καλεί επανειλημμένα τη μέθοδο 'read()'. Αυτή η διαδικασία της λειτουργίας read() συνεχίζεται μέχρι να φτάσει στο τέλος του μπλοκ.
  6. Μόλις επιτευχθεί το τέλος ενός μπλοκ, το DFSInputStream κλείνει τη σύνδεση και προχωρά για να εντοπίσει τον επόμενο DataNode για το επόμενο μπλοκ.
  7. Μόλις ο πελάτης ολοκληρώσει την ανάγνωση, καλεί τη μέθοδο close().

Γράφω Operation σε HDFS

Σε αυτήν την ενότητα, θα κατανοήσουμε πώς τα δεδομένα εγγράφονται σε HDFS μέσω αρχείων. Το παρακάτω διάγραμμα traces που γράφουν διαδρομή.

Αγωγός λειτουργίας εγγραφής HDFS με DataQueue, DataStreamer και Ack Queue

  1. Ένας πελάτης ξεκινά μια λειτουργία εγγραφής καλώντας τη μέθοδο 'create()' του αντικειμένου DistributedFileSystem, η οποία δημιουργεί ένα νέο αρχείο – Βήμα αρ. 1 στο παραπάνω διάγραμμα.
  2. Το αντικείμενο DistributedFileSystem συνδέεται με το NameNode χρησιμοποιώντας μια κλήση RPC και ξεκινά τη δημιουργία νέου αρχείου. Ωστόσο, αυτή η λειτουργία δημιουργίας αρχείου δεν συσχετίζει κανένα μπλοκ με το αρχείο. Είναι ευθύνη του NameNode να επαληθεύσει ότι το αρχείο (το οποίο δημιουργείται) δεν υπάρχει ήδη και ότι ο υπολογιστής-πελάτης έχει τα σωστά δικαιώματα για να δημιουργήσει ένα νέο αρχείο. Εάν ένα αρχείο υπάρχει ήδη ή ο υπολογιστής-πελάτης δεν έχει επαρκή δικαιώματα για να δημιουργήσει ένα νέο αρχείο, τότε δημιουργείται ένα IOException στον υπολογιστή-πελάτη. Διαφορετικά, η λειτουργία είναι επιτυχής και δημιουργείται μια νέα εγγραφή για το αρχείο από το NameNode.
  3. Μόλις δημιουργηθεί μια νέα εγγραφή στο NameNode, ένα αντικείμενο τύπου FSDataOutputStream επιστρέφεται στον πελάτη. Ένας πελάτης το χρησιμοποιεί για να γράψει δεδομένα στο HDFS. Καλείται η μέθοδος εγγραφής δεδομένων (βήμα 3 στο διάγραμμα).
  4. Το FSDataOutputStream περιέχει ένα αντικείμενο DFSOutputStream το οποίο φροντίζει για την επικοινωνία με τους DataNodes και τον NameNode. Ενώ ο υπολογιστής-πελάτης συνεχίζει να γράφει δεδομένα, το DFSOutputStream συνεχίζει να δημιουργεί πακέτα με αυτά τα δεδομένα. Αυτά τα πακέτα τοποθετούνται σε μια ουρά που ονομάζεται DataQueue.
  5. Υπάρχει ένα ακόμη στοιχείο που ονομάζεται DataStreamer το οποίο καταναλώνει αυτό το DataQueue. Το DataStreamer ζητά επίσης από το NameNode την κατανομή νέων μπλοκ, επιλέγοντας έτσι τα επιθυμητά DataNodes που θα χρησιμοποιηθούν για αναπαραγωγή.
  6. Τώρα, η διαδικασία αναπαραγωγής ξεκινά δημιουργώντας μια διοχέτευση χρησιμοποιώντας DataNodes. Στην περίπτωσή μας, επιλέξαμε ένα επίπεδο αναπαραγωγής 3 και ως εκ τούτου υπάρχουν 3 Κόμβοι Δεδομένων στη γραμμή.
  7. Το DataStreamer χύνει πακέτα στον πρώτο DataNode στη διοχέτευση.
  8. Κάθε DataNode σε έναν αγωγό αποθηκεύει το πακέτο που λαμβάνει και το προωθεί στον δεύτερο DataNode στον αγωγό.
  9. Μια άλλη ουρά, η «Ουρά Επιβεβαίωσης», συντηρείται από το DFSOutputStream για την αποθήκευση πακέτων που περιμένουν επιβεβαίωση από τους DataNodes.
  10. Μόλις ληφθεί επιβεβαίωση για ένα πακέτο στην ουρά από όλους τους κόμβους δεδομένων στη διοχέτευση, αφαιρείται από την «Ουρά αποδοχής». Σε περίπτωση αποτυχίας του DataNode, τα πακέτα από αυτήν την ουρά χρησιμοποιούνται για την επανεκκίνηση της λειτουργίας.
  11. Αφού ένας πελάτης ολοκληρώσει την εγγραφή δεδομένων, καλεί τη μέθοδο close() (Βήμα 9 στο διάγραμμα). Η κλήση της μεθόδου close() έχει ως αποτέλεσμα την εκκαθάριση των υπόλοιπων πακέτων δεδομένων στον αγωγό, ακολουθούμενη από την αναμονή για επιβεβαίωση.
  12. Μόλις ληφθεί μια τελική επιβεβαίωση, επικοινωνείται με το NameNode για να του γνωστοποιηθεί ότι η λειτουργία εγγραφής αρχείου έχει ολοκληρωθεί.

Πρόσβαση στο HDFS χρησιμοποιώντας το Java API

Σε αυτήν την ενότητα, προσπαθούμε να κατανοήσουμε την Java διεπαφή που χρησιμοποιείται για την πρόσβαση στο σύστημα αρχείων του Hadoop.

Για να αλληλεπιδράσει προγραμματιστικά με το σύστημα αρχείων του Hadoop, το Hadoop παρέχει πολλαπλές Java κλάσεις. Το πακέτο με όνομα org.apache.hadoop.fs περιέχει κλάσεις χρήσιμες για τον χειρισμό ενός αρχείου στο σύστημα αρχείων του Hadoop. Αυτές οι λειτουργίες περιλαμβάνουν άνοιγμα, ανάγνωση, εγγραφή και κλείσιμο. Το API αρχείων Hadoop είναι γενικό και μπορεί να επεκταθεί για να αλληλεπιδρά με συστήματα αρχείων εκτός από το HDFS.

Ανάγνωση αρχείου από HDFS, μέσω προγραμματισμού

Αντικείμενο java.net.URL χρησιμοποιείται για την ανάγνωση του περιεχομένου ενός αρχείου. Αρχικά, πρέπει να φτιάξουμε Java αναγνωρίζω τα hdfs του Hadoop URL σχήμα. Αυτό γίνεται καλώντας το σύνολοURLΜέθοδος StreamHandlerFactory στο URL αντικείμενο και μεταβίβαση μιας παρουσίας του FsUrlStreamHandlerFactory σε αυτό. Αυτή η μέθοδος πρέπει να εκτελείται μόνο μία φορά ανά FMV, επομένως περικλείεται σε ένα στατικό μπλοκ.

Ένα παράδειγμα κώδικα είναι -

public class URLCat {
    static {
        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
    }
    public static void main(String[] args) throws Exception {
        InputStream in = null;
        try {
            in = new URL(args[0]).openStream();
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }
}

Αυτός ο κώδικας ανοίγει και διαβάζει τα περιεχόμενα ενός αρχείου. Η διαδρομή αυτού του αρχείου στο HDFS διαβιβάζεται στο πρόγραμμα ως όρισμα γραμμής εντολών.

Πρόσβαση στο HDFS χρησιμοποιώντας τη διεπαφή γραμμής εντολών

Αυτός είναι ένας από τους απλούστερους τρόπους αλληλεπίδρασης με το HDFS. Η διεπαφή γραμμής εντολών υποστηρίζει λειτουργίες συστήματος αρχείων, όπως ανάγνωση αρχείου, δημιουργία καταλόγων, μετακίνηση αρχείων, διαγραφή δεδομένων και δημιουργία καταλόγων.

Μπορούμε να τρέξουμε '$HADOOP_HOME/bin/hdfs dfs -help' για να λάβετε λεπτομερή βοήθεια για κάθε εντολή. Εδώ, το 'dfs' είναι μια εντολή shell του HDFS που υποστηρίζει πολλαπλές υποεντολές. Στις τρέχουσες εκδόσεις του Hadoop hdfs dfs είναι η προτιμώμενη μορφή, ενώ η παλαιότερη Hadoop fs Η εντολή εκτελεί την ίδια εργασία για οποιοδήποτε υποστηριζόμενο σύστημα αρχείων.

Μερικές από τις ευρέως χρησιμοποιούμενες εντολές παρατίθενται παρακάτω μαζί με ορισμένες λεπτομέρειες για την καθεμία.

1. Αντιγράψτε ένα αρχείο από το τοπικό σύστημα αρχείων στο HDFS

$HADOOP_HOME/bin/hdfs dfs -copyFromLocal temp.txt /

Αυτή η εντολή αντιγράφει το αρχείο temp.txt από το τοπικό σύστημα αρχείων στο HDFS, όπως φαίνεται στην παρακάτω έξοδο.

Η εντολή hdfs dfs -copyFromLocal αντιγράφει το temp.txt στο HDFS

2. Μπορούμε να απαριθμήσουμε αρχεία που υπάρχουν σε έναν κατάλογο χρησιμοποιώντας την εντολή -ls

$HADOOP_HOME/bin/hdfs dfs -ls /

Στην παρακάτω λίστα μπορούμε να δούμε το αρχείο 'temp.txt' (που αντιγράφηκε νωρίτερα) στον κατάλογο ' / '.

Η εντολή hdfs dfs -ls εμφανίζει την έξοδο temp.txt στον ριζικό κατάλογο HDFS.

3. Εντολή για αντιγραφή ενός αρχείου στο τοπικό σύστημα αρχείων από το HDFS

$HADOOP_HOME/bin/hdfs dfs -copyToLocal /temp.txt

Αυτή η εντολή αντικατοπτρίζει την εντολή -get και δέχεται μια σαφή τοπική διαδρομή προορισμού ως δεύτερο όρισμα. Η παρακάτω έξοδος δείχνει το temp.txt που αντιγράφηκε στο τοπικό σύστημα αρχείων.

hdfs dfs -copyToLocal έξοδος που εμφανίζει το temp.txt που αντιγράφηκε στο τοπικό σύστημα αρχείων

4. Εντολή για τη δημιουργία νέου καταλόγου

$HADOOP_HOME/bin/hdfs dfs -mkdir /mydirectory

Η εντολή ολοκληρώνεται σιωπηλά, όπως φαίνεται στην παρακάτω προτροπή.

Εντολή hdfs dfs -mkdir δημιουργία του φακέλου /mydirectory στο HDFS

Ελέγξτε αν ο κατάλογος έχει δημιουργηθεί ή όχι. Τώρα, θα πρέπει να ξέρετε πώς να το κάνετε 😉

Συχνές Ερωτήσεις

Τα μεγάλα μπλοκ διατηρούν τα μεταδεδομένα NameNode μικρά και επιτρέπουν σε έναν mapper να διαβάσει μια μεγάλη διαδοχική σειρά byte πριν την εκ νέου αναζήτηση. Επομένως, ο χρόνος αναζήτησης στο δίσκο γίνεται ένα πολύ μικρό κλάσμα του χρόνου μεταφοράς, γεγονός που καθιστά γρήγορες τις σαρώσεις ολόκληρου του αρχείου.

Το NameNode σταματά να λαμβάνει παλμούς, σημειώνει τον κόμβο ως νεκρό και προγραμματίζει την εκ νέου αναπαραγωγή κάθε μπλοκ που έπεσε κάτω από τον συντελεστή αναπαραγωγής του σε υγιή DataNodes. Οι εγγραφές εν πτήσει ανακτώνται από την ουρά επικύρωσης, έτσι ώστε ο πελάτης να μην χάνει πακέτα.

Δεν βρίσκεται σε σωστά διαμορφωμένο σύμπλεγμα. Το HDFS High Availability εκτελεί έναν ενεργό και έναν αναμονής NameNode που μοιράζονται επεξεργασίες μέσω του JournalNodes και οι ελεγκτές ανακατεύθυνσης ZooKeeper προωθούν αυτόματα την αναμονή όταν ο ενεργός κόμβος σταματήσει να ανταποκρίνεται.

Και οι δύο ανεβάζουν δεδομένα στο HDFS. Η επιλογή -copyFromLocal περιορίζει την πηγή στο τοπικό σύστημα αρχείων, ενώ η επιλογή -put δέχεται οποιαδήποτε υποστηριζόμενη πηγή, συμπεριλαμβανομένης μιας άλλης διαδρομής HDFS ή stdin. Η συμπεριφορά είναι κατά τα άλλα πανομοιότυπη, επομένως η επιλογή -copyFromLocal απλώς καταγράφει την πρόθεση.

Κάθε αρχείο, κατάλογος και μπλοκ καταλαμβάνει μνήμη στο NameNode, επομένως εκατομμύρια μικροσκοπικά αρχεία εξαντλούνται από το σωρό πολύ πριν γεμίσουν οι δίσκοι. Ο συνδυασμός τους σε αρχεία ακολουθίας, τα αρχεία Avro, ORC, Parquet ή HAR διατηρούν τα μεταδεδομένα διαχειρίσιμα.

Η αναπαραγωγή διατηρεί τρία πλήρη αντίγραφα, κοστίζοντας 200% επιπλέον χώρο αποθήκευσης. Η κωδικοποίηση διαγραφής, που προστέθηκε στο Hadoop 3, αποθηκεύει κελιά ισοτιμίας και επιτυγχάνει παρόμοια ανθεκτικότητα με περίπου 50% επιβάρυνση, ανταλλάσσοντας φθηνότερο χώρο αποθήκευσης με υψηλότερο κόστος CPU και δικτύου κατά την ανάκτηση.

Τα μοντέλα μηχανικής μάθησης που έχουν εκπαιδευτεί σε αρχεία καταγραφής ελέγχου NameNode και μετρήσεις DataNode μπορούν να προβλέψουν την εξάντληση της χωρητικότητας, να επισημάνουν τα hot blocks και να εντοπίσουν δίσκους που παρουσιάζουν βλάβη πριν από την απόρριψή τους. Η ανίχνευση ανωμαλιών σε μοτίβα πρόσβασης ανακαλύπτει επίσης νωρίς τις εργασίες που δεν λειτουργούν.

Το Copilot ολοκληρώνει γρήγορα το γνωστό στερεότυπο org.apache.hadoop.fs, όπως κλήσεις FileSystem.get, FSDataInputStream loops και IOUtils.copyBytes. Να επαληθεύετε πάντα τον δημιουργημένο κώδικα με την έκδοση Hadoop που χρησιμοποιείται, επειδή τα ονόματα API και οι παρωχημένες μέθοδοι διαφέρουν αισθητά μεταξύ του Hadoop 2.x και του 3.x.

Συνοψίστε αυτήν την ανάρτηση με: