Γεια σας φίλοι! Υπάρχουν άνθρωποι με διαφορετικά επίπεδα εμπειρίας που συνεισφέρουν στο φόρουμ μας - και αυτό είναι υπέροχο! Αλλά αυτή τη στιγμή, ψάχνω για πραγματικούς τιτάνες του Ruby!
Το Elasticsearch είναι μια μηχανή αναζήτησης που βασίζεται σε μια αξιόπιστη και ώριμη βιβλιοθήκη - την Apache Lucene. Τεράστια δραστηριότητα στο git έργο αποθετήριο και η εφαρμογή του σε έργα όπως το GitHub, το SoundCloud, το Stack Overflow και το LinkedIn μαρτυρούν τη μεγάλη δημοτικότητά του. Το μέρος "Elastic" τα λέει όλα για τη φύση του συστήματος, του οποίου οι δυνατότητες είναι τεράστιες: από μια απλή αναζήτηση αρχείων σε μικρή κλίμακα, μέσω της ανακάλυψης γνώσης, μέχρι την ανάλυση μεγάλων δεδομένων σε πραγματικό χρόνο. αυτό που κάνει το Elastic ένα πιο ισχυρό από τον ανταγωνισμό είναι το σύνολο των προεπιλεγμένων ρυθμίσεων και συμπεριφορών, οι οποίες επιτρέπουν τη δημιουργία μιας συστάδας και την έναρξη της προσθήκης εγγράφων στο ευρετήριο μέσα σε λίγα λεπτά. Το Elastic θα διαμορφώσει μια συστάδα για εσάς, θα ορίσει ένα ευρετήριο και θα ορίσει τους τύπους των πεδίων για το πρώτο έγγραφο που λαμβάνεται, και όταν προσθέσετε έναν άλλο διακομιστή, θα ασχοληθεί αυτόματα με τον διαχωρισμό των δεδομένων του ευρετηρίου μεταξύ των διακομιστών. δυστυχώς, η προαναφερθείσα αυτοματοποίηση δεν μας καθιστά σαφές τι συνεπάγονται οι προεπιλεγμένες ρυθμίσεις και συχνά αποδεικνύεται παραπλανητική. Αυτό το άρθρο αποτελεί την αρχή μιας σειράς όπου θα ασχοληθώ με τα πιο δημοφιλή gotchas, τα οποία μπορεί να συναντήσετε κατά τη διαδικασία δημιουργίας εφαρμογών βασισμένων στο Elastic.
Ο αριθμός των θραυσμάτων δεν μπορεί να αλλάξει
Ας ευρετηριάσουμε το πρώτο έγγραφο χρησιμοποιώντας index API:
$ curl -XPUT 'http://localhost:9200/myindex/employee/1' -d '{
"first_name" : "Jane",
"last_name" : "Smith",
"steet_number": 12
}'
Αυτή τη στιγμή, η Elastic δημιουργεί ένα ευρετήριο για εμάς, με τίτλο myindex. Αυτό που δεν είναι ορατό εδώ είναι ο αριθμός των shards που αντιστοιχούν στο ευρετήριο. Τα shards μπορούν να γίνουν κατανοητά ως μεμονωμένες διεργασίες που είναι υπεύθυνες για την ευρετηρίαση, την αποθήκευση και την αναζήτηση κάποιου μέρους των εγγράφων ενός ολόκληρου ευρετηρίου. Κατά τη διάρκεια της διαδικασίας ευρετηρίασης εγγράφων, το elastic αποφασίζει σε ποιο shard θα πρέπει να βρεθεί ένα έγγραφο. Αυτό βασίζεται στον ακόλουθο τύπο:
shard = hash(document_id) % number_of_primary_shards
Είναι πλέον σαφές ότι ο αριθμός των πρωτογενών shards δεν μπορεί να αλλάξει για ένα ευρετήριο που περιέχει έγγραφα. Έτσι, πριν από την ευρετηρίαση του πρώτου εγγράφου, δημιουργείτε πάντα ένα ευρετήριο με μη αυτόματο τρόπο, δίνοντας τον αριθμό των shards, ο οποίος πιστεύετε ότι είναι επαρκής για έναν όγκο δεδομένων που ευρετηριάζονται:
$ curl -XPUT 'http://localhost:9200/myindex/' -d '{
"settings" : {
"number_of_shards" : 10
}
}'
Προεπιλεγμένη τιμή για number_of_shards
είναι 5. Αυτό σημαίνει ότι το ευρετήριο μπορεί να κλιμακωθεί σε έως και 5 διακομιστές, οι οποίοι συλλέγουν δεδομένα κατά τη διάρκεια της ευρετηρίασης. Για το περιβάλλον παραγωγής, η τιμή των shards θα πρέπει να οριστεί ανάλογα με την αναμενόμενη συχνότητα ευρετηρίασης και το μέγεθος των εγγράφων. Για περιβάλλοντα ανάπτυξης και δοκιμών, συνιστώ να ορίσετε την τιμή στο 1 - γιατί έτσι; Θα εξηγηθεί στην επόμενη παράγραφο αυτού του άρθρου.
Ταξινόμηση των αποτελεσμάτων αναζήτησης κειμένου με σχετικά μικρό αριθμό εγγράφων
Όταν αναζητούμε ένα έγγραφο με μια φράση:
$ curl -XGET 'http://localhost:9200/myindex/my_type/_search' -d
'{
"query": {
"match": {
"title": "The quick brown fox"
}
}
}'
Το Elastic επεξεργάζεται την αναζήτηση κειμένου σε λίγα βήματα, μιλώντας απλά:
- η φράση από την αίτηση μετατρέπεται στην ίδια πανομοιότυπη μορφή με αυτή του εγγράφου που ευρετηριάστηκε, στην περίπτωσή μας θα είναι σύνολο όρων:
["quick", "brown", "fox"]
("το" έχει αφαιρεθεί επειδή είναι ασήμαντο),
- το ευρετήριο περιηγείται για την αναζήτηση των εγγράφων που περιέχουν τουλάχιστον μία από τις λέξεις που αναζητούνται,
- κάθε έγγραφο που ταιριάζει, αξιολογείται ως προς τη συνάφεια με τη φράση αναζήτησης,
- τα αποτελέσματα ταξινομούνται με βάση την υπολογιζόμενη συνάφεια και επιστρέφεται στον χρήστη η πρώτη σελίδα αποτελεσμάτων.
Στο τρίτο βήμα, λαμβάνονται υπόψη οι ακόλουθες τιμές (μεταξύ άλλων):
- πόσες λέξεις από τη φράση αναζήτησης υπάρχουν στο έγγραφο
- πόσο συχνά εμφανίζεται μια συγκεκριμένη λέξη σε ένα έγγραφο (TF - συχνότητα όρων)
- αν και πόσο συχνά οι λέξεις που ταιριάζουν εμφανίζονται σε άλλα έγγραφα (IDF - αντίστροφη συχνότητα εγγράφων) - όσο πιο δημοφιλής είναι η λέξη σε άλλα έγγραφα, τόσο λιγότερο σημαντική είναι.
- πόσο μεγάλο είναι το έγγραφο
Η λειτουργία των IDF είναι σημαντική για εμάς. Το Elastic για λόγους απόδοσης δεν υπολογίζει αυτή την τιμή όσον αφορά κάθε έγγραφο στο ευρετήριο - αντίθετα, κάθε shard (index worker) υπολογίζει το τοπικό του IDF και το χρησιμοποιεί για την ταξινόμηση. Ως εκ τούτου, κατά την αναζήτηση στο ευρετήριο με μικρό αριθμό εγγράφων ενδέχεται να λάβουμε σημαντικά διαφορετικά αποτελέσματα ανάλογα με τον αριθμό των shards σε ένα ευρετήριο και την κατανομή των εγγράφων.
Ας φανταστούμε ότι έχουμε 2 κομμάτια σε ένα ευρετήριο- στο πρώτο υπάρχουν 8 έγγραφα που ευρετηριάζονται με τη λέξη "αλεπού" και στο δεύτερο μόνο 2 έγγραφα με την ίδια λέξη. Ως αποτέλεσμα, η λέξη "αλεπού" θα διαφέρει σημαντικά και στα δύο shards, και αυτό μπορεί να παράγει λανθασμένα αποτελέσματα. Επομένως, για σκοπούς ανάπτυξης θα πρέπει να δημιουργηθεί ένα ευρετήριο που να αποτελείται από ένα μόνο πρωτεύον shard:
$ curl -XPUT 'http://localhost:9200/myindex/' -d
'{"settings" : { "number_of_shards" : 1 } }'
Η προβολή των αποτελεσμάτων των "μακρινών" σελίδων αναζήτησης σκοτώνει το σύμπλεγμα σας
Όπως έχω ξαναγράψει σε προηγούμενες παραγράφους, τα έγγραφα σε ένα ευρετήριο μοιράζονται μεταξύ εντελώς μεμονωμένων διεργασιών ευρετηρίου - shards. Κάθε διεργασία είναι εντελώς ανεξάρτητη και ασχολείται μόνο με τα έγγραφα που της έχουν ανατεθεί.
Όταν κάνουμε αναζήτηση σε ένα ευρετήριο με εκατομμύρια έγγραφα και περιμένουμε να λάβουμε τα 10 κορυφαία αποτελέσματα, κάθε shard πρέπει να επιστρέψει τα 10 καλύτερα αποτελέσματα που ταιριάζουν στο cluster του κόμβος, η οποία ξεκίνησε την έρευνα. Στη συνέχεια, οι απαντήσεις από κάθε τμήμα ενώνονται και επιλέγονται τα 10 κορυφαία αποτελέσματα αναζήτησης (στο σύνολο του ευρετηρίου). Μια τέτοια προσέγγιση επιτρέπει την αποτελεσματική κατανομή της διαδικασίας αναζήτησης μεταξύ πολλών διακομιστών.
Ας φανταστούμε ότι η εφαρμογή μας επιτρέπει την προβολή 50 αποτελεσμάτων ανά σελίδα, χωρίς τους περιορισμούς σχετικά με τον αριθμό των σελίδων που μπορεί να δει ένας χρήστης. Θυμηθείτε ότι το ευρετήριό μας αποτελείται από 10 πρωτεύοντα shards (1 ανά διακομιστή).
Ας δούμε πώς θα είναι η απόκτηση των αποτελεσμάτων αναζήτησης για την 1η και την 100ή σελίδα:
Σελίδα 1 των αποτελεσμάτων αναζήτησης:
- Ο κόμβος που λαμβάνει ένα ερώτημα (ελεγκτής) το μεταβιβάζει σε 10 τμήματα.
- Κάθε κομμάτι επιστρέφει τα 50 έγγραφα που ταιριάζουν καλύτερα με βάση τη συνάφεια.
- Αφού ληφθούν οι απαντήσεις από κάθε τμήμα, ο ελεγκτής συγχωνεύει τα αποτελέσματα (500 έγγραφα).
- Τα αποτελέσματά μας είναι τα 50 κορυφαία έγγραφα από το προηγούμενο βήμα.
Σελίδα αριθ. 100 των αποτελεσμάτων αναζήτησης:
- Ο κόμβος που λαμβάνει ένα ερώτημα (ελεγκτής) το μεταβιβάζει σε 10 τμήματα.
- Κάθε κομμάτι επιστρέφει τα 5000 έγγραφα που ταιριάζουν καλύτερα με βάση τη συνάφεια.
- Αφού λάβει απαντήσεις από κάθε διαχωριστικό τμήμα, ο ελεγκτής συγχωνεύει τα αποτελέσματα (50000 έγγραφα).
- Τα αποτελέσματά μας είναι τα έγγραφα από το προηγούμενο βήμα που τοποθετούνται στις θέσεις 4901 - 5000.
Υποθέτοντας ότι ένα έγγραφο έχει μέγεθος 1KB, στη δεύτερη περίπτωση αυτό σημαίνει ότι ~50MB δεδομένων πρέπει να αποσταλούν και να υποβληθούν σε επεξεργασία στο σύμπλεγμα, προκειμένου να προβληθούν 100 αποτελέσματα για έναν χρήστη.
Δεν είναι δύσκολο να παρατηρήσετε ότι η κυκλοφορία του δικτύου και ο φόρτος του ευρετηρίου αυξάνεται σημαντικά με κάθε διαδοχική σελίδα αποτελεσμάτων. Για το λόγο αυτό δεν συνιστάται η διάθεση των "μακρινών" σελίδων αναζήτησης στο χρήστη. Αν το ευρετήριό μας είναι καλά ρυθμισμένο, τότε ο χρήστης θα πρέπει να βρίσκει το αποτέλεσμα που τον ενδιαφέρει στις πρώτες σελίδες αναζήτησης και θα προστατευτούμε από περιττό φόρτο του cluster μας. Για να αποδείξετε αυτόν τον κανόνα, ελέγξτε, μέχρι ποιον αριθμό σελίδων αποτελεσμάτων αναζήτησης επιτρέπουν την προβολή τους οι πιο δημοφιλείς μηχανές αναζήτησης στο διαδίκτυο.
Αυτό που είναι επίσης ενδιαφέρον είναι η παρατήρηση του χρόνου απόκρισης του προγράμματος περιήγησης για τις διαδοχικές σελίδες αποτελεσμάτων αναζήτησης. Για παράδειγμα, παρακάτω μπορείτε να βρείτε τους χρόνους απόκρισης για μεμονωμένες σελίδες αποτελεσμάτων αναζήτησης στην αναζήτηση Google (ο όρος αναζήτησης ήταν "μηχανή αναζήτησης"):
| Σελίδα αποτελεσμάτων αναζήτησης (10 έγγραφα ανά σελίδα) | Χρόνος απόκρισης |
|——————————————–|—————|
| 1 | 250ms |
| 10 | 290ms |
| 20 | 350ms |
| 30 | 380ms |
| 38 (το τελευταίο διαθέσιμο) | | |
Στο επόμενο μέρος, θα εξετάσω διεξοδικότερα τα προβλήματα σχετικά με την ευρετηρίαση εγγράφων.