Tere sõbrad! Meie foorumisse panustavad erineva kogemustasemega inimesed - ja see on suurepärane! Aga praegu otsin ma tõelisi Ruby titaane!
Elasticsearch on otsingumootor, mis põhineb usaldusväärsel ja küpsel raamatukogul - Apache Lucene. Tohutu tegevus git'is 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.
Osakeste arvu ei saa muuta
Indekseerime esimese dokumendi, kasutades indeks API:
$ curl -XPUT 'http://localhost:9200/myindex/employee/1' -d '{
"first_name" : "Jane",
"last_name" : "Smith",
"steet_number": 12
}'
Sel hetkel loob Elastic meile indeksi, mille nimi on myindex. Siin ei ole näha indeksile määratud shardide arvu. Shards'i võib mõista kui üksikuid protsesse, mis vastutavad kogu indeksi mingi osa dokumentide indekseerimise, salvestamise ja otsimise eest. Dokumentide indekseerimise käigus otsustab elastic, millises shardis dokumenti leida. See põhineb järgmisel valemil:
shard = hash(document_id) % number_of_primary_shards
Nüüd on selge, et primaarsete osade arvu ei saa muuta dokumente sisaldava indeksi puhul. Seega looge enne esimese dokumendi indekseerimist alati käsitsi indeks, andes indekseeritavate andmete mahu jaoks piisavaks peetavate killude arvu:
$ curl -XPUT 'http://localhost:9200/myindex/' -d '{
"settings" : {
"number_of_shards" : 10
}
}'
Vaikimisi väärtus number_of_shards on 5. See tähendab, et indeksit saab skaleerida kuni 5 serverile, mis koguvad andmeid indekseerimise ajal. Tootmiskeskkonna puhul tuleks killustike väärtus määrata sõltuvalt indekseerimise eeldatavast sagedusest ja dokumentide suurusest. Arendus- ja testkeskkondade puhul soovitan määrata väärtuseks 1 - miks nii? Seda selgitatakse selle artikli järgmises lõigus.
Tekstiotsingu tulemuste sorteerimine suhteliselt väikese arvu dokumentidega
Kui me otsime dokumenti fraasiga:
$ curl -XGET 'http://localhost:9200/myindex/my_type/_search' -d
'{
"query": {
"match": {
"title": "The quick brown fox"
}
}
}'
Elastic töötleb tekstiotsingut paari sammuga, lihtsalt öeldes:
- fraas taotlusest teisendatakse samasse identsesse vormi, milles dokument indekseeriti, meie puhul on see terminite kogum:
["kiire", "pruun", "rebane"] ("the" on eemaldatud, sest see on ebaoluline),
- indeksist otsitakse dokumente, mis sisaldavad vähemalt ühte otsitavast sõnast,
- iga dokumenti, mis vastab, hinnatakse selle poolest, kas see on otsingulause jaoks asjakohane,
- tulemused sorteeritakse arvutatud asjakohasuse järgi ja kasutajale tagastatakse tulemuste esimene lehekülg.
Kolmandas etapis võetakse (muu hulgas) arvesse järgmisi väärtusi:
- kui palju sõnu otsingufraasist on dokumendis
- kui tihti esineb antud sõna dokumendis (TF - termide sagedus).
- kas ja kui sageli vastavad sõnad esinevad teistes dokumentides (IDF - inverse document frequency) - mida populaarsem on sõna teistes dokumentides, seda väiksem on selle tähtsus.
- kui pikk on dokument
IDFi toimimine on meie jaoks oluline. Elastic ei arvuta seda väärtust jõudluse huvides iga dokumendi kohta indeksis - selle asemel arvutab iga shard (indeksitöötaja) oma kohaliku IDFi ja kasutab seda sorteerimiseks. Seetõttu võime indeksiotsingu ajal väikese dokumentide arvu korral saada oluliselt erinevaid tulemusi sõltuvalt indeksis olevate shardide arvust ja dokumentide jaotusest.
Kujutame ette, et meil on indeksis 2 killustikku; esimeses on 8 dokumenti, mis on indekseeritud sõnaga "rebane", ja teises ainult 2 dokumenti, millel on sama sõna. Selle tulemusena erineb sõna "rebane" mõlemas osakonnas oluliselt ja see võib anda ebaõigeid tulemusi. Seetõttu tuleks arenduse eesmärgil luua indeks, mis koosneb ainult ühest primaarsest killustikust:
$ curl -XPUT 'http://localhost:9200/myindex/' -d
'{"settings" : { "number_of_shards" : 1 } }'
"Kaugete" otsingulehtede tulemuste vaatamine tapab teie klastri
Nagu ma olen juba varem kirjutanud, jagatakse indeksis olevaid dokumente täiesti individuaalsete indeksiprotsesside - shardide - vahel. Iga protsess on täiesti sõltumatu ja tegeleb ainult nende dokumentidega, mis on talle määratud.
Kui me otsime miljonite dokumentidega indeksist ja ootame 10 parimat tulemust, peab iga killustik tagastama oma 10 parimat tulemust klastrile. sõlme, mis algatas otsingu. Seejärel liidetakse iga killustiku vastused kokku ja valitakse 10 parimat otsingutulemust (kogu indeksist). Selline lähenemisviis võimaldab tõhusalt jaotada otsinguprotsessi paljude serverite vahel.
Kujutame ette, et meie rakendus võimaldab vaadata 50 tulemust lehekülje kohta, ilma piiranguteta, mis puudutab kasutaja poolt vaadatavate lehekülgede arvu. Pidage meeles, et meie indeks koosneb 10 primaarsest osast (1 iga serveri kohta).
Vaatame, kuidas näeb välja otsingutulemuste omandamine 1. ja 100. lehekülje puhul:
Otsingutulemuste lehekülg nr 1:
- Sõlm, mis võtab päringu vastu (kontroller), edastab selle 10 osakonnale.
- Iga killustik tagastab 50 kõige paremini sobivat dokumenti, mis on sorteeritud asjakohasuse järgi.
- Pärast vastuste saamist igast osakonnast ühendab vastutav töötleja tulemused (500 dokumenti).
- Meie tulemused on eelmise sammu 50 parimat dokumenti.
Otsingutulemuste lehekülg nr 100:
- Sõlm, mis võtab päringu vastu (kontroller), edastab selle 10 osakonnale.
- Iga killustik tagastab 5000 kõige paremini sobivat dokumenti, mis on sorteeritud asjakohasuse järgi.
- Pärast vastuste saamist igast osakonnast ühendab kontroller tulemused (50000 dokumenti).
- Meie tulemused on eelmise sammu dokumendid, mis on paigutatud 4901 - 5000.
Eeldades, et ühe dokumendi suurus on 1 KB, tähendab see teisel juhul, et ühe kasutaja 100 tulemuse vaatamiseks tuleb saata ja töödelda ~50 MB andmeid klastris.
Pole raske märgata, et võrguliikluse ja indeksi koormus suureneb märkimisväärselt iga järgneva tulemuslehega. Seetõttu ei ole soovitatav "kaugemaid" otsingulehti kasutajale kättesaadavaks teha. Kui meie indeks on hästi konfigureeritud, siis peaks kasutaja leidma teda huvitava tulemuse juba esimestel otsingulehekülgedel ja me kaitseme end meie klastri tarbetu koormuse eest. Selle reegli tõestamiseks kontrollige, kuni mitu otsingutulemuste lehekülge lubavad kõige populaarsemad veebiotsingumootorid vaadata.
Huvitav on ka vaatlus brauseri reageerimisaja kohta järjestikuste otsingutulemuste lehekülgede puhul. Näiteks allpool on esitatud Google Searchi üksikute otsingutulemuste lehekülgede vastamisajad (otsingusõna oli "search engine"):
| Otsingutulemuste lehekülg (10 dokumenti lehekülje kohta) | Vastamisaeg |
|——————————————–|—————|
| 1 | 250ms |
| 10 | 290ms |
| 20 | 350ms |
| 30 | 380ms |
| 38 (viimane vaba) | | |
Järgmises osas uurin lähemalt dokumentide indekseerimisega seotud probleeme.