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 repositoorium ning selle suurest populaarsusest annavad tunnistust selle rakendamine sellistes projektides nagu GitHub, SoundCloud, Stack Overflow ja LinkedIn. Osa "Elastic" ütleb kõik süsteemi olemuse kohta, mille võimalused on tohutud: alates lihtsast failiotsingust väikeses mahus kuni teadmiste leidmise ja suurte andmete analüüsini reaalajas." Mis teeb Elasticist konkurentidest võimsama, on vaikimisi konfiguratsioonide ja käitumise kogum, mis võimaldab luua klastri ja alustada dokumentide lisamist indeksisse paari minutiga. Elastic konfigureerib teie eest klastri, määrab indeksi ja määrab esimese saadud dokumendi jaoks välja tüübid ning kui lisate teise serveri, tegeleb ta automaatselt indeksi andmete jagamisega serverite vahel. kahjuks teeb eelmainitud automatiseerimine meile ebaselgeks, mida vaikimisi seaded tähendavad ja see osutub sageli eksitavaks. See artikkel alustab sarja, kus ma hakkan tegelema kõige populaarsemate gotchadega, millega võib Elastic-põhise rakenduse loomise käigus kokku puutuda.
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.