Hej venner! Der er folk med forskellige niveauer af erfaring, der bidrager til vores fora - og det er dejligt! Men lige nu leder jeg efter ægte Ruby-titaner!
Elasticsearch er en søgemaskine, der er baseret på et pålideligt og modent bibliotek - Apache Lucene. Kæmpe aktivitet i git projekt repository and the implementation in such projects as GitHub, SoundCloud, Stack Overflow and LinkedIn bear testimony to its great popularity. The part “Elastic” says it all about the nature of the system, whose capabilities are enormous: from a simple file search on a small scale, through knowledge discovery, to big data analysis in real time.What makes Elastic a more powerful than the competition is the set of default configurations and behaviors, which allow to create a cluster and start adding documents to the index in a couple of minutes. Elastic will configure a cluster for you, will define an index and define the types of fields for the first document obtained, and when you add another server, it will automatically deal with dividing index data between servers.Unfortunately, the above mentioned automation makes it unclear to us what the default settings implicate, and it often turns out to be misleading. This article starts a series where I will be dealing with the most popular gotchas, which you might encounter during the process of Elastic-based app creation.
Antallet af skår kan ikke ændres
Lad os indeksere det første dokument ved hjælp af indeks API:
$ curl -XPUT 'http://localhost:9200/myindex/employee/1' -d '{
"fornavn" : "Jane",
"efternavn": "Smith",
"steet_number": 12
}'
I dette øjeblik opretter Elastic et indeks til os med titlen myindex. Det, der ikke er synligt her, er antallet af shards, der er tildelt indekset. Shards kan forstås som individuelle processer, der er ansvarlige for indeksering, lagring og søgning af en del af dokumenterne i et helt indeks. I løbet af dokumentindekseringsprocessen beslutter elastic, i hvilken shard et dokument skal findes. Det er baseret på følgende formel:
shard = hash(document_id) % number_of_primary_shards
Det er nu klart, at antallet af primære shards ikke kan ændres for et indeks, der indeholder dokumenter. Så før du indekserer det første dokument, skal du altid oprette et indeks manuelt og angive det antal shards, som du mener er tilstrækkeligt til en mængde indekserede data:
$ curl -XPUT 'http://localhost:9200/myindex/' -d '{
"indstillinger" : {
"antal_af_skår" : 10
}
}'
Standardværdi for antal_af_skår er 5. Det betyder, at indekset kan skaleres til op til 5 servere, som indsamler data under indekseringen. For produktionsmiljøet bør værdien af shards indstilles afhængigt af den forventede indekseringsfrekvens og dokumenternes størrelse. Til udviklings- og testmiljøer anbefaler jeg at sætte værdien til 1 - hvorfor? Det vil blive forklaret i næste afsnit af denne artikel.
Sortering af tekstsøgeresultater med et relativt lille antal dokumenter
Når vi søger efter et dokument med en sætning:
$ curl -XGET 'http://localhost:9200/myindex/my_type/_search' -d
'{
"query": {
"match": {
"title": "Den hurtige brune ræv"
}
}
}'
Elastic behandler tekstsøgning i få trin, ganske enkelt:
- sætningen fra anmodningen konverteres til den samme identiske form, som dokumentet blev indekseret i, i vores tilfælde vil det være et sæt termer:
["hurtig", "brun", "ræv"]. ("the" er fjernet, fordi det er ubetydeligt),
- indekset gennemsøges for at finde de dokumenter, der indeholder mindst et af de søgte ord,
- Hvert dokument, der er et match, vurderes i forhold til, om det er relevant for søgefrasen,
- Resultaterne sorteres efter den beregnede relevans, og den første side med resultater returneres til brugeren.
I det tredje trin tages der bl.a. hensyn til følgende værdier:
- hvor mange ord fra søgefrasen der er i dokumentet
- hvor ofte et givet ord forekommer i et dokument (TF - termfrekvens)
- om og hvor ofte de matchende ord forekommer i andre dokumenter (IDF - invers dokumentfrekvens) - jo mere populært ordet er i andre dokumenter, jo mindre vigtigt er det
- Hvor langt er dokumentet?
IDF's funktion er vigtig for os. Af hensyn til ydeevnen beregner Elastic ikke denne værdi for hvert dokument i indekset - i stedet beregner hver shard (indeksarbejder) sin lokale IDF og bruger den til sortering. Derfor kan vi under indekssøgningen med et lavt antal dokumenter opnå væsentligt forskellige resultater afhængigt af antallet af shards i et indeks og dokumentfordelingen.
Lad os forestille os, at vi har to skår i et indeks; i det første er der 8 dokumenter indekseret med ordet "ræv", og i det andet er der kun 2 dokumenter med det samme ord. Som følge heraf vil ordet "ræv" være meget forskelligt i begge dele, og det kan give forkerte resultater. Derfor bør der til udviklingsformål oprettes et indeks, der kun består af én primær shard:
$ curl -XPUT 'http://localhost:9200/myindex/' -d
'{"settings" : {"number_of_shards" : 1 } }'
Visning af resultaterne af "fjerne" søgesider dræber din klynge
Som jeg har skrevet i tidligere afsnit, deles dokumenterne i et indeks mellem helt individuelle indeksprocesser - shards. Hver proces er helt uafhængig og beskæftiger sig kun med de dokumenter, som er tildelt den.
Når vi søger i et indeks med millioner af dokumenter og venter på at få top 10-resultater, skal hver shard returnere sine 10 bedst matchede resultater til klyngens Knudepunktsom indledte søgningen. Derefter samles svarene fra hver shard, og de 10 bedste søgeresultater vælges (inden for hele indekset). En sådan tilgang gør det muligt at fordele søgeprocessen effektivt mellem mange servere.
Lad os forestille os, at vores app giver mulighed for at se 50 resultater pr. side uden begrænsninger i antallet af sider, som en bruger kan se. Husk, at vores indeks består af 10 primære shards (1 pr. server).
Lad os se, hvordan erhvervelsen af søgeresultater vil se ud for den 1. og den 100. side:
Side nr. 1 af søgeresultaterne:
- Den node, der modtager en forespørgsel (controller), sender den videre til 10 shards.
- Hver del returnerer sine 50 bedst matchende dokumenter sorteret efter relevans.
- Når svarene er modtaget fra hver del, fletter controlleren resultaterne (500 dokumenter).
- Vores resultater er de 50 bedste dokumenter fra det foregående trin.
Side nr. 100 af søgeresultaterne:
- Den node, der modtager en forespørgsel (controller), sender den videre til 10 shards.
- Hver del returnerer sine 5000 bedst matchende dokumenter sorteret efter relevans.
- Når controlleren har modtaget svar fra alle dele, fletter den resultaterne (50000 dokumenter).
- Vores resultater er dokumenterne fra det foregående trin, der er placeret 4901 - 5000.
Hvis vi antager, at et dokument er 1 KB stort, betyder det i det andet tilfælde, at ~50 MB data skal sendes og behandles rundt i klyngen for at kunne se 100 resultater for en bruger.
Det er ikke svært at se, at netværkstrafikken og indeksbelastningen stiger markant for hver enkelt resultatside. Derfor anbefales det ikke at gøre de "fjerne" søgesider tilgængelige for brugeren. Hvis vores indeks er godt konfigureret, bør brugeren finde det resultat, han er interesseret i, på de første søgesider, og vi beskytter os selv mod unødvendig belastning af vores klynge. For at bevise denne regel kan du tjekke, op til hvor mange sider med søgeresultater de mest populære websøgemaskiner tillader visning.
Hvad der også er interessant, er observationen af browserens svartid for successive søgeresultatsider. Nedenfor kan du f.eks. se svartider for individuelle sider med søgeresultater i Google Search (søgeordet var "søgemaskine"):
| Søgeresultatside (10 dokumenter pr. side) Svartid
|——————————————–|—————|
| 1 250 ms
| 10 290 ms
| 20 350 ms
| 30 380 ms
| 38 (den sidste tilgængelige)
I næste del vil jeg se nærmere på problemerne med dokumentindeksering.