Αποθηκεύστε αποτελεσματικά εκατοντάδες εκατομμύρια μικρά αρχεία. Αυτο-φιλοξενούμενη λύση

Αποθηκεύστε αποτελεσματικά εκατοντάδες εκατομμύρια μικρά αρχεία. Αυτο-φιλοξενούμενη λύση

Αγαπητέ Κοινότητα, Αυτό το άρθρο θα επικεντρωθεί στην αποτελεσματική αποθήκευση και ανάκτηση εκατοντάδων εκατομμυρίων μικρών αρχείων. Σε αυτό το στάδιο, προτείνεται η τελική λύση για συστήματα αρχείων συμβατά με POSIX με πλήρη υποστήριξη κλειδαριών, συμπεριλαμβανομένων κλειδαριών συμπλέγματος, και φαινομενικά ακόμη και χωρίς πατερίτσες.

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

Η ιδέα είναι η εξής:

Με απλά λόγια, μικρά αρχεία μεταφορτώνονται μέσω του διακομιστή, αποθηκεύονται απευθείας στο αρχείο και διαβάζονται επίσης από αυτό και τοποθετούνται μεγάλα αρχεία δίπλα-δίπλα. Σχέδιο: 1 φάκελος = 1 αρχείο, συνολικά έχουμε πολλά εκατομμύρια αρχεία με μικρά αρχεία, και όχι αρκετές εκατοντάδες εκατομμύρια αρχεία. Και όλα αυτά υλοποιούνται πλήρως, χωρίς κανένα σενάριο ή τοποθέτηση αρχείων σε αρχεία tar/zip.

Θα προσπαθήσω να το κρατήσω σύντομο, ζητώ συγγνώμη εκ των προτέρων εάν η ανάρτηση είναι μακροσκελή.

Όλα ξεκίνησαν από το γεγονός ότι δεν μπορούσα να βρω έναν κατάλληλο διακομιστή στον κόσμο που θα μπορούσε να αποθηκεύσει δεδομένα που ελήφθησαν μέσω του πρωτοκόλλου HTTP απευθείας σε αρχεία, χωρίς τα μειονεκτήματα που είναι εγγενή στα συμβατικά αρχεία και την αποθήκευση αντικειμένων. Και ο λόγος για την αναζήτηση ήταν το σύμπλεγμα Origin των 10 διακομιστών που είχε μεγαλώσει σε μεγάλη κλίμακα, στο οποίο είχαν ήδη συσσωρευτεί 250,000,000 μικρά αρχεία και η αναπτυξιακή τάση δεν επρόκειτο να σταματήσει.

Για όσους δεν τους αρέσει να διαβάζουν άρθρα, μια μικρή τεκμηρίωση είναι ευκολότερη:

εδώ и εδώ.

Και docker ταυτόχρονα, τώρα υπάρχει μια επιλογή μόνο με το nginx μέσα για κάθε περίπτωση:

docker run -d --restart=always -e host=localhost -e root=/var/storage 
-v /var/storage:/var/storage --name wzd -p 80:80 eltaline/wzd

Επόμενο:

Εάν υπάρχουν πολλά αρχεία, απαιτούνται σημαντικοί πόροι και το χειρότερο είναι ότι κάποιοι από αυτούς σπαταλούνται. Για παράδειγμα, όταν χρησιμοποιείτε ένα σύστημα αρχείων συμπλέγματος (σε αυτήν την περίπτωση, MooseFS), το αρχείο, ανεξάρτητα από το πραγματικό του μέγεθος, καταλαμβάνει πάντα τουλάχιστον 64 KB. Δηλαδή, για αρχεία μεγέθους 3, 10 ή 30 KB, απαιτούνται 64 KB στο δίσκο. Εάν υπάρχουν ένα τέταρτο του δισεκατομμυρίου αρχείων, χάνουμε από 2 έως 10 terabyte. Δεν θα είναι δυνατή η δημιουργία νέων αρχείων επ' αόριστον, καθώς το MooseFS έχει έναν περιορισμό: όχι περισσότερο από 1 δισεκατομμύριο με ένα αντίγραφο κάθε αρχείου.

Καθώς ο αριθμός των αρχείων αυξάνεται, χρειάζεται πολλή μνήμη RAM για τα μεταδεδομένα. Η συχνή απόρριψη μεγάλων μεταδεδομένων συμβάλλει επίσης στη φθορά των μονάδων SSD.

διακομιστής wZD. Τακτοποιούμε τα πράγματα στους δίσκους.

Ο διακομιστής είναι γραμμένος στο Go. Πρώτα απ 'όλα, έπρεπε να μειώσω τον αριθμό των αρχείων. Πως να το κάνεις? Λόγω αρχειοθέτησης, αλλά στην προκειμένη περίπτωση χωρίς συμπίεση, αφού τα αρχεία μου είναι απλά συμπιεσμένες εικόνες. Το BoltDB ήρθε στη διάσωση, το οποίο έπρεπε ακόμα να εξαλειφθεί από τις αδυναμίες του, αυτό αντικατοπτρίζεται στην τεκμηρίωση.

Συνολικά, αντί για ένα τέταρτο του δισεκατομμυρίου αρχείων, στην περίπτωσή μου είχαν απομείνει μόνο 10 εκατομμύρια αρχεία Bolt. Αν είχα την ευκαιρία να αλλάξω την τρέχουσα δομή του αρχείου καταλόγου, θα ήταν δυνατό να τη μειώσω σε περίπου 1 εκατομμύριο αρχεία.

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

Αρχιτεκτονική και χαρακτηριστικά του διακομιστή wZD.

Αποθηκεύστε αποτελεσματικά εκατοντάδες εκατομμύρια μικρά αρχεία. Αυτο-φιλοξενούμενη λύση

Ο διακομιστής λειτουργεί με λειτουργικά συστήματα Linux, BSD, Solaris και OSX. Δοκίμασα μόνο για αρχιτεκτονική AMD64 σε Linux, αλλά θα πρέπει να λειτουργεί για ARM64, PPC64, MIPS64.

Κύρια χαρακτηριστικά:

  • Multithreading;
  • Πολυδιακομιστής, που παρέχει ανοχή σφαλμάτων και εξισορρόπηση φορτίου.
  • Μέγιστη διαφάνεια για τον χρήστη ή τον προγραμματιστή.
  • Υποστηριζόμενες μέθοδοι HTTP: GET, HEAD, PUT και DELETE.
  • Έλεγχος της συμπεριφοράς ανάγνωσης και γραφής μέσω κεφαλίδων πελάτη.
  • Υποστήριξη για ευέλικτους εικονικούς κεντρικούς υπολογιστές.
  • Υποστήριξη ακεραιότητας δεδομένων CRC κατά τη γραφή/ανάγνωση.
  • Ημιδυναμικά buffer για ελάχιστη κατανάλωση μνήμης και βέλτιστο συντονισμό απόδοσης δικτύου.
  • Αναβαλλόμενη συμπίεση δεδομένων.
  • Επιπλέον, προσφέρεται ένας πολλαπλών νημάτων αρχειοθέτησης wZA για τη μετεγκατάσταση αρχείων χωρίς διακοπή της υπηρεσίας.

Πραγματική εμπειρία:

Αναπτύσσω και δοκιμάζω τον διακομιστή και τον αρχειοθέτη σε ζωντανά δεδομένα εδώ και πολύ καιρό, τώρα λειτουργεί με επιτυχία σε ένα σύμπλεγμα που περιλαμβάνει 250,000,000 μικρά αρχεία (εικόνες) που βρίσκονται σε 15,000,000 καταλόγους σε ξεχωριστούς δίσκους SATA. Ένα σύμπλεγμα 10 διακομιστών είναι ένας διακομιστής Origin που είναι εγκατεστημένος πίσω από ένα δίκτυο CDN. Για την εξυπηρέτηση του, χρησιμοποιούνται 2 διακομιστές Nginx + 2 διακομιστές wZD.

Για όσους αποφασίσουν να χρησιμοποιήσουν αυτόν τον διακομιστή, θα ήταν συνετό να σχεδιάσουν τη δομή του καταλόγου, εάν υπάρχει, πριν από τη χρήση. Επιτρέψτε μου να κάνω μια κράτηση αμέσως ότι ο διακομιστής δεν προορίζεται να στριμώξει τα πάντα σε ένα αρχείο 1 Bolt.

Δοκιμή απόδοσης:

Όσο μικρότερο είναι το μέγεθος του συμπιεσμένου αρχείου, τόσο πιο γρήγορες εκτελούνται οι λειτουργίες GET και PUT σε αυτό. Ας συγκρίνουμε τον συνολικό χρόνο για την εγγραφή του προγράμματος-πελάτη HTTP με τα κανονικά αρχεία και τα αρχεία Bolt, καθώς και με την ανάγνωση. Συγκρίνεται η εργασία με αρχεία μεγεθών 32 KB, 256 KB, 1024 KB, 4096 KB και 32768 KB.

Όταν εργάζεστε με τα αρχεία Bolt, ελέγχεται η ακεραιότητα των δεδομένων κάθε αρχείου (χρησιμοποιείται το CRC), πριν από την εγγραφή και επίσης μετά την εγγραφή, πραγματοποιείται ανάγνωση και επανυπολογισμός κατά τη διάρκεια της πτήσης, αυτό φυσικά δημιουργεί καθυστερήσεις, αλλά το κύριο πράγμα είναι η ασφάλεια των δεδομένων.

Έκανα δοκιμές απόδοσης σε μονάδες SSD, καθώς οι δοκιμές σε μονάδες SATA δεν δείχνουν σαφή διαφορά.

Γραφήματα με βάση τα αποτελέσματα των δοκιμών:

Αποθηκεύστε αποτελεσματικά εκατοντάδες εκατομμύρια μικρά αρχεία. Αυτο-φιλοξενούμενη λύση
Αποθηκεύστε αποτελεσματικά εκατοντάδες εκατομμύρια μικρά αρχεία. Αυτο-φιλοξενούμενη λύση

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

Έχουμε μια εντελώς διαφορετική εικόνα κατά τη δοκιμή ανάγνωσης και εγγραφής αρχείων μεγέθους 32 MB:

Αποθηκεύστε αποτελεσματικά εκατοντάδες εκατομμύρια μικρά αρχεία. Αυτο-φιλοξενούμενη λύση

Η χρονική διαφορά μεταξύ των αρχείων ανάγνωσης είναι εντός 5-25 ms. Με την εγγραφή τα πράγματα είναι χειρότερα, η διαφορά είναι περίπου 150 ms. Αλλά σε αυτήν την περίπτωση δεν χρειάζεται να ανεβάσετε μεγάλα αρχεία· απλώς δεν έχει νόημα να το κάνετε· μπορούν να ζουν χωριστά από τα αρχεία.

* Από τεχνική άποψη, μπορείτε να χρησιμοποιήσετε αυτόν τον διακομιστή για εργασίες που απαιτούν NoSQL.

Βασικές μέθοδοι εργασίας με διακομιστή wZD:

Φόρτωση κανονικού αρχείου:

curl -X PUT --data-binary @test.jpg http://localhost/test/test.jpg

Η μεταφόρτωση ενός αρχείου στο αρχείο Bolt (εάν η παράμετρος διακομιστή fmaxsize, η οποία καθορίζει το μέγιστο μέγεθος αρχείου που μπορεί να συμπεριληφθεί στο αρχείο, δεν ξεπεραστεί. Εάν γίνει υπέρβαση, το αρχείο θα μεταφορτωθεί ως συνήθως δίπλα στο αρχείο):

curl -X PUT -H "Archive: 1" --data-binary @test.jpg http://localhost/test/test.jpg

Λήψη αρχείου (εάν υπάρχουν αρχεία με τα ίδια ονόματα στο δίσκο και στο αρχείο, τότε κατά τη λήψη, προτεραιότητα δίνεται από προεπιλογή στο μη αρχειοθετημένο αρχείο):

curl -o test.jpg http://localhost/test/test.jpg

Λήψη αρχείου από το αρχείο Bolt (αναγκαστική):

curl -o test.jpg -H "FromArchive: 1" http://localhost/test/test.jpg

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

Τεκμηρίωση wZD
Τεκμηρίωση wZA

Ο διακομιστής προς το παρόν υποστηρίζει μόνο το πρωτόκολλο HTTP· δεν λειτουργεί ακόμη με HTTPS. Η μέθοδος POST επίσης δεν υποστηρίζεται (δεν έχει αποφασιστεί ακόμη αν χρειάζεται ή όχι).

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

Εκκρεμότητες:

  • Ανάπτυξη του δικού σας αντιγραφέα και διανομέα + geo για τη δυνατότητα χρήσης σε μεγάλα συστήματα χωρίς συστήματα αρχείων συμπλέγματος (Όλα για ενήλικες)
  • Δυνατότητα πλήρους αντίστροφης ανάκτησης μεταδεδομένων εάν χαθούν εντελώς (εάν χρησιμοποιείτε διανομέα)
  • Εγγενές πρωτόκολλο για τη δυνατότητα χρήσης μόνιμων συνδέσεων δικτύου και προγραμμάτων οδήγησης για διαφορετικές γλώσσες προγραμματισμού
  • Προηγμένες δυνατότητες χρήσης του στοιχείου NoSQL
  • Συμπιέσεις διαφορετικών τύπων (gzip, zstd, snappy) για αρχεία ή τιμές μέσα στα αρχεία Bolt και για κανονικά αρχεία
  • Κρυπτογράφηση διαφορετικών τύπων για αρχεία ή τιμές μέσα στα αρχεία Bolt και για κανονικά αρχεία
  • Καθυστερημένη μετατροπή βίντεο από την πλευρά του διακομιστή, συμπεριλαμβανομένης της GPU

Έχω τα πάντα, ελπίζω αυτός ο διακομιστής να είναι χρήσιμος σε κάποιον, άδεια BSD-3, διπλά πνευματικά δικαιώματα, αφού αν δεν υπήρχε εταιρεία όπου εργάζομαι, ο διακομιστής δεν θα είχε γραφτεί. Είμαι ο μόνος προγραμματιστής. Θα ήμουν ευγνώμων για τυχόν σφάλματα και αιτήματα λειτουργιών που θα βρείτε.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο