Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Tere, minu nimi on Evgeniy. Töötan Yandex.Marketi otsinguinfrastruktuuris. Ma tahan rääkida Habri kogukonnale turu siseköögist – ja mul on palju rääkida. Kõigepealt turuotsingu toimimisest, protsessidest ja arhitektuurist. Kuidas toimime eriolukordades: mis juhtub, kui üks server läheb alla? Mis siis, kui selliseid servereid on 100?

Samuti saate teada, kuidas rakendame uusi funktsioone korraga paljudes serverites. Ja kuidas testime keerulisi teenuseid otse tootmises, tekitamata kasutajatele ebamugavusi. Üldiselt turuotsing toimib nii, et kõigil oleks hea olla.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Natuke meist: millist probleemi me lahendame

Kui sisestate teksti, otsite toodet parameetrite järgi või võrdlete hindu erinevates kauplustes, saadetakse kõik päringud otsinguteenusele. Otsing on turu suurim teenus.

Töötleme kõiki otsingupäringuid: saitidelt market.yandex.ru, beru.ru, teenusest Supercheck, Yandex.Advisorist, mobiilirakendustest. Lisame tootepakkumised ka yandex.ru otsingutulemustesse.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Otsinguteenuse all ei pea ma silmas mitte ainult otsingut ennast, vaid ka andmebaasi kõigi turul olevate pakkumistega. Skaala on järgmine: päevas töödeldakse üle miljardi otsingupäringu. Ja kõik peaks töötama kiiresti, ilma katkestusteta ja andma alati soovitud tulemuse.

Mis on mis: turuarhitektuur

Kirjeldan lühidalt Turu praegust arhitektuuri. Seda saab ligikaudu kirjeldada alloleva diagrammiga:
Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub
Oletame, et meie juurde tuleb partnerpood. Ta ütleb, et tahan mänguasja maha müüa: seda kurja kassi kriuksumisega. Ja veel üks vihane kass ilma piiksuta. Ja lihtsalt kass. Seejärel peab pood koostama pakkumised, mida Turg otsib. Pood genereerib pakkumistega spetsiaalse xml-i ja edastab sidusettevõtte liidese kaudu tee sellesse xml-i. Seejärel laadib indekseerija selle xml-i perioodiliselt alla, kontrollib vigu ja salvestab kogu teabe tohutusse andmebaasi.

Selliseid salvestatud xml-e on palju. Sellest andmebaasist luuakse otsinguregister. Indeks salvestatakse sisevormingus. Pärast indeksi loomist laadib paigutusteenus selle üles otsinguserveritesse.

Selle tulemusena ilmub andmebaasi vihane kass kriuksuva ja serverisse ilmub kassi register.

Ma räägin teile, kuidas me kassi otsime otsinguarhitektuuri osas.

Turuotsingu arhitektuur

Me elame mikroteenuste maailmas: iga sissetulev päring market.yandex.ru põhjustab palju alampäringuid ja nende töötlemisega on seotud kümneid teenuseid. Diagramm näitab vaid mõnda:

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub
Lihtsustatud taotluste töötlemise skeem

Igal teenusel on imeline asi - oma tasakaalustaja ainulaadse nimega:

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Tasakaalustaja annab meile teenuse haldamisel suurema paindlikkuse: saate näiteks serverid välja lülitada, mis on sageli uuenduste jaoks vajalik. Tasakaalustaja näeb, et server pole saadaval ja suunab päringud automaatselt ümber teistele serveritele või andmekeskustele. Serveri lisamisel või eemaldamisel jaotatakse koormus automaatselt serverite vahel ümber.

Tasakaalustaja unikaalne nimi ei sõltu andmekeskusest. Kui teenus A esitab päringu B-le, suunab tasakaalustaja B päringu vaikimisi praegusesse andmekeskusesse. Kui teenus pole saadaval või seda praeguses andmekeskuses ei eksisteeri, suunatakse päring ümber teistesse andmekeskustesse.

Üks FQDN kõigi andmekeskuste jaoks võimaldab teenusel A asukohtadest täielikult eemalduda. Tema taotlust teenusele B käsitletakse alati. Erandiks on juhtum, kui teenus asub kõigis andmekeskustes.

Kuid selle tasakaalustajaga pole kõik nii roosiline: meil on täiendav vahekomponent. Tasakaalustaja võib olla ebastabiilne ja selle probleemi lahendavad üleliigsed serverid. Teenuste A ja B vahel on ka täiendav viivitus. Praktikas on see aga alla 1 ms ja enamiku teenuste puhul pole see kriitiline.

Toimetulek ootamatustega: otsinguteenuste tasakaalustamine ja vastupidavus

Kujutage ette, et toimub kokkuvarisemine: peate leidma kriuksuva kassi, kuid server jookseb kokku. Või 100 serverit. Kuidas välja saada? Kas me tõesti jätame kasutaja kassita?

Olukord on hirmutav, kuid me oleme selleks valmis. Ma ütlen teile järjekorras.

Otsinguinfrastruktuur asub mitmes andmekeskuses:

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Kaasame projekteerimisel ühe andmekeskuse sulgemise võimaluse. Elu on täis üllatusi – näiteks võib ekskavaator läbi lõigata maakaabli (jah, nii juhtus). Ülejäänud andmekeskuste võimsus peaks tippkoormusele vastu pidama.

Vaatleme ühte andmekeskust. Igal andmekeskusel on sama tasakaalustaja tööskeem:

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub
Üks tasakaalustaja on vähemalt kolm füüsilist serverit. See koondamine on tehtud töökindluse tagamiseks. Tasakaalustajad töötavad HAProxiga.

Valisime HAProxi selle suure jõudluse, madala ressursivajaduse ja laia funktsionaalsuse tõttu. Meie otsingutarkvara töötab igas serveris.

Ühe serveri rikke tõenäosus on väike. Kuid kui teil on palju servereid, suureneb tõenäosus, et vähemalt üks läheb alla.

See juhtub tegelikkuses: serverid jooksevad kokku. Seetõttu on vaja pidevalt jälgida kõigi serverite olekut. Kui server lõpetab reageerimise, katkestatakse see automaatselt liiklusest. Selleks on HAProxyl sisseehitatud tervisekontroll. See läheb kõikidesse serveritesse kord sekundis HTTP-päringuga "/ping".

Teine HAProxy funktsioon: agent-check võimaldab laadida kõiki servereid ühtlaselt. Selleks loob HAProxy ühenduse kõigi serveritega ja need tagastavad oma kaalu sõltuvalt hetkekoormusest 1 kuni 100. Kaal arvutatakse töötlemise järjekorras olevate päringute arvu ja protsessori koormuse alusel.

Nüüd kassi leidmisest. Otsingutulemused selliste päringutega nagu: /search?text=vihane+kass. Et otsing oleks kiire, peab kogu kassindeks mahtuma RAM-i. Isegi SSD-lt lugemine ei ole piisavalt kiire.

Kunagi oli pakkumiste andmebaas väike ja selle jaoks piisas ühe serveri RAM-ist. Pakkumise baasi kasvades ei mahtunud kõik sellesse RAM-i enam ära ning andmed jagunesid kaheks: shard 1 ja shard 2.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub
Kuid seda juhtub alati: iga lahendus, isegi hea, tekitab muid probleeme.

Tasakaalustaja läks ikka suvalisse serverisse. Kuid masinal, kuhu taotlus tuli, oli ainult pool indeksist. Ülejäänu oli teistes serverites. Seetõttu pidi server minema mõne naabermasina juurde. Pärast mõlemalt serverilt andmete saamist tulemused kombineeriti ja järjestati ümber.

Kuna tasakaalustaja jagab päringuid ühtlaselt, tegelesid kõik serverid ümberpaigutamise, mitte ainult andmete saatmisega.

Probleem ilmnes siis, kui naaberserver polnud saadaval. Lahenduseks oli mitme erineva prioriteediga serveri määramine “naaberserveriks”. Esiteks saadeti päring praeguses riiulis olevatele serveritele. Kui vastust ei tulnud, saadeti päring kõigile selle andmekeskuse serveritele. Ja lõpuks läks taotlus teistele andmekeskustele.
Ettepanekute arvu kasvades jagunesid andmed neljaks osaks. Kuid see ei olnud piir.

Praegu kasutatakse kaheksast killust koosnevat konfiguratsiooni. Lisaks, et veelgi rohkem mälu kokku hoida, jagati register otsingu osaks (mida kasutatakse otsimiseks) ja jupi osaks (mis ei osale otsingus).

Üks server sisaldab teavet ainult ühe killu kohta. Seetõttu peate täieliku registri otsimiseks otsima kaheksast serverist, mis sisaldavad erinevaid kilde.

Serverid on rühmitatud klastritesse. Iga klaster sisaldab kaheksat otsingumootorit ja ühte katkendiserverit.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub
Jupiserver käitab staatiliste andmetega võtmeväärtuste andmebaasi. Neid on vaja dokumentide väljastamiseks, näiteks kriuksuva kassi kirjelduse väljastamiseks. Andmed edastatakse spetsiaalselt eraldi serverisse, et mitte koormata otsinguserverite mälu.

Kuna dokumendi ID-d on unikaalsed ainult ühe indeksi piires, võib tekkida olukord, kus juppides pole dokumente. Noh, või et ühe ID jaoks on erinev sisu. Seetõttu oli otsingu toimimiseks ja tulemuste tagastamiseks vaja kogu klastri järjepidevust. Allpool räägin teile, kuidas me järjepidevust jälgime.

Otsing ise on üles ehitatud järgmiselt: otsingupäring võib tulla ükskõik millisesse kaheksast serverist. Oletame, et ta tuli serverisse 1. See server töötleb kõiki argumente ja saab aru, mida ja kuidas otsida. Sõltuvalt sissetulevast päringust saab server teha välisteenustele täiendavaid päringuid vajaliku teabe saamiseks. Ühele päringule võib järgneda kuni kümme päringut välisteenustele.

Pärast vajaliku teabe kogumist algab otsing pakkumiste andmebaasis. Selleks tehakse alampäringud klastri kõigisse kaheksasse serverisse.

Kui vastused on saadud, kombineeritakse tulemused. Lõpuks võib tulemuste genereerimiseks vaja minna veel mitut alampäringut koodilõigu serverisse.

Klastris olevad otsingupäringud näevad välja järgmised: /shard1?text=vihane+kass. Lisaks tehakse klastri kõigi serverite vahel pidevalt vormi alampäringuid kord sekundis: /staatus.

Päring /staatus tuvastab olukorra, kus server pole saadaval.

Samuti juhib see seda, et otsingumootori versioon ja indeksi versioon oleksid kõikides serverites samad, vastasel juhul on klastris vastuolulised andmed.

Vaatamata sellele, et üks jupiserver töötleb kaheksa otsingumootori päringuid, on selle protsessor väga kergelt koormatud. Seetõttu kanname nüüd katkendandmete üle eraldi teenusesse.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Andmete edastamiseks võtsime kasutusele universaalsed võtmed dokumentide jaoks. Nüüd on võimatu olukord, kus teise dokumendi sisu tagastatakse ühe võtmega.

Kuid üleminek teisele arhitektuurile pole veel lõppenud. Nüüd tahame spetsiaalsest katkendiserverist lahti saada. Ja seejärel eemalduge klastri struktuurist täielikult. See võimaldab meil hõlpsalt skaleerimist jätkata. Lisaboonuseks on märkimisväärne raua kokkuhoid.

Ja nüüd õnneliku lõpuga hirmulugude juurde. Vaatleme mitut serveri kättesaamatuse juhtumit.

Juhtus midagi kohutavat: üks server pole saadaval

Oletame, et üks server pole saadaval. Seejärel saavad klastri ülejäänud serverid jätkata vastamist, kuid otsingutulemused on puudulikud.

Olekukontrolli kaudu /staatus naaberserverid saavad aru, et see pole saadaval. Seetõttu täielikkuse säilitamiseks kõik klastri serverid päringu kohta /ping nad hakkavad tasakaalustajale vastama, et nad pole samuti kättesaadavad. Selgub, et kõik klastri serverid surid (mis pole tõsi). See on meie kobarskeemi peamine puudus – sellepärast tahame sellest eemale saada.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Taotlused, mis ebaõnnestuvad veaga, saadab tasakaalustaja uuesti teistes serverites.
Tasakaalustaja lõpetab ka kasutajate liikluse saatmise surnud serveritele, kuid jätkab nende oleku kontrollimist.

Kui server muutub kättesaadavaks, hakkab see reageerima /ping. Niipea kui tavalised vastused surnud serveritelt pingidele hakkavad saabuma, hakkavad tasakaalustajad sinna kasutajaliiklust saatma. Klastri töö on taastatud, hurraa.

Veelgi hullem: paljud serverid pole saadaval

Märkimisväärne osa andmekeskuse serveritest kärbitakse. Mida teha, kuhu joosta? Tasakaalustaja tuleb taas appi. Iga tasakaalustaja salvestab pidevalt mällu aktiivsete serverite arvu. See arvutab pidevalt maksimaalset liiklust, mida praegune andmekeskus suudab töödelda.

Kui andmekeskuse paljud serverid kaovad, mõistab tasakaalustaja, et see andmekeskus ei suuda kogu liiklust töödelda.

Seejärel hakatakse liigset liiklust juhuslikult teistesse andmekeskustesse jaotama. Kõik töötab, kõik on rahul.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Kuidas me seda teeme: väljaannete avaldamine

Nüüd räägime sellest, kuidas me teenuses tehtud muudatusi avaldame. Siin oleme valinud protsesside lihtsustamise tee: uue versiooni väljalaskmine on peaaegu täielikult automatiseeritud.
Kui projekti on kogunenud teatud arv muudatusi, luuakse automaatselt uus väljalase ja selle ehitamine algab.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Seejärel viiakse teenus välja testimisele, kus kontrollitakse töö stabiilsust.

Samal ajal käivitatakse automaatne jõudluse testimine. Sellega tegeleb eriteenistus. Ma ei räägi sellest praegu - selle kirjeldus väärib eraldi artiklit.

Kui testimises avaldamine õnnestub, alustatakse automaatselt väljalase avaldamist eelstabiilsuses. Prestable on spetsiaalne klaster, kuhu suunatakse tavaline kasutajaliiklus. Kui see tagastab vea, teeb tasakaalustaja uuesti taotluse tootmisele.

Eelstabiilses režiimis mõõdetakse reageerimisaegu ja võrreldakse neid eelmise tootmisväljaandega. Kui kõik on korras, siis inimene ühendab: kontrollib koormustestimise graafikuid ja tulemusi ning hakkab siis tootmisse rullima.

Kõik parim läheb kasutajale: A/B testimine

Alati pole selge, kas teenuse muudatused toovad tegelikku kasu. Muudatuste kasulikkuse mõõtmiseks mõtlesid inimesed välja A/B testimise. Ma räägin teile veidi, kuidas see Yandex.Marketi otsingus töötab.

Kõik algab uue CGI parameetri lisamisega, mis võimaldab uusi funktsioone. Olgu meie parameeter: market_new_functionality=1. Seejärel lubame koodis selle funktsiooni, kui lipp on olemas:

If (cgi.experiments.market_new_functionality) {
// enable new functionality
}

Uued funktsioonid võetakse tootmisse.

A/B-testimise automatiseerimiseks on spetsiaalne teenus, mis pakub üksikasjalikku teavet siin kirjeldatud. Teenuses luuakse eksperiment. Liiklusosaks on määratud näiteks 15%. Protsendid määratakse mitte päringute, vaid kasutajate jaoks. Näidatud on ka katse kestus, näiteks nädal.

Korraga saab läbi viia mitu katset. Seadistustes saate määrata, kas ristumine teiste katsetega on võimalik.

Selle tulemusena lisab teenus automaatselt argumendi market_new_functionality=1 kuni 15% kasutajatest. Samuti arvutab see automaatselt valitud mõõdikud. Pärast katse lõppu vaatavad analüütikud tulemusi ja teevad järeldused. Tulemuste põhjal tehakse otsus tootmisse või täiustamisse kasutusele võtta.

Turu osav käsi: katsetamine tootmises

Tihti juhtub, et peate katsetama uue funktsionaalsuse toimimist tootmises, kuid te pole kindel, kuidas see suure koormuse korral "lahingutingimustes" käitub.

Lahendus on olemas: CGI parameetrites olevaid lippe saab kasutada mitte ainult A/B testimiseks, vaid ka uute funktsionaalsuste testimiseks.

Tegime tööriista, mis võimaldab teil tuhandete serverite konfiguratsiooni koheselt muuta, ilma et see teenust ohustaks. Seda nimetatakse Stop Tap. Algne idee oli, et saaks mõne funktsiooni kiiresti keelata ilma paigutuseta. Seejärel tööriist laienes ja muutus keerukamaks.

Teenuse vooskeem on esitatud allpool:

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Lipu väärtused määratakse API kaudu. Haldusteenus salvestab need väärtused andmebaasi. Kõik serverid lähevad andmebaasi kord kümne sekundi jooksul, pumbavad välja lipuväärtused ja rakendavad neid väärtusi igale päringule.

Stop-kraanil saate määrata kahte tüüpi väärtusi.

1) Tingimuslikud avaldised. Rakendage, kui üks väärtustest on tõene. Näiteks:

{
	"condition":"IS_DC1",
	"value":"3",
}, 
{
	"condition": "CLUSTER==2 and IS_BERU", 
	"value": "4!" 
}

Väärtust "3" rakendatakse siis, kui taotlust töödeldakse asukohas DC1. Ja väärtus on "4", kui taotlust töödeldakse saidi beru.ru teises klastris.

2) Tingimusteta väärtused. Kui ükski tingimus ei ole täidetud, rakendage vaikimisi. Näiteks:

väärtus, väärtus!

Kui väärtus lõpeb hüüumärgiga, antakse sellele kõrgem prioriteet.

CGI parameetri parser sõelub URL-i. Seejärel rakendab Stop Tap väärtused.

Rakendatakse järgmiste prioriteetidega väärtusi:

  1. Suurendatud prioriteediga stoppkraanist (hüüumärk).
  2. Väärtus päringust.
  3. Vaikeväärtus valikust Stop tap.
  4. Vaikeväärtus koodis.

Tingimuslikes väärtustes näidatud lippe on palju - neist piisab kõigi meile teadaolevate stsenaariumide jaoks:

  • Andmekeskus.
  • Keskkond: tootmine, testimine, vari.
  • Toimumiskoht: turg, beru.
  • Klastri number.

Selle tööriista abil saate teatud serverite rühmas (näiteks ainult ühes andmekeskuses) lubada uusi funktsioone ja testida selle funktsionaalsuse toimimist ilma, et see kogu teenusele erilist ohtu kujutaks. Isegi kui tegite kuskil tõsise vea, hakkas kõik kukkuma ja kogu andmekeskus läks alla, suunavad tasakaalustajad päringud teistesse andmekeskustesse. Lõppkasutajad ei märka midagi.

Kui märkate probleemi, saate viivitamatult taastada lipu eelmise väärtuse ja muudatused tühistatakse.

Sellel teenusel on ka oma varjuküljed: arendajad armastavad seda väga ja püüavad sageli kõik muudatused Stop Tapisse suruda. Püüame võidelda väärkasutusega.

Stop Tap-lähenemine toimib hästi, kui teil on juba stabiilne kood tootmiseks kasutamiseks valmis. Samal ajal on teil endiselt kahtlusi ja soovite koodi kontrollida "lahingutingimustes".

Stop Tap ei sobi aga arenduse ajal testimiseks. Arendajatele on eraldi klaster, mida nimetatakse varjuklastriks.

Salajane testimine: varjuklaster

Ühe klastri päringud dubleeritakse variklastrisse. Kuid tasakaalustaja ignoreerib täielikult selle klastri vastuseid. Selle toimimise skeem on esitatud allpool.

Kuidas Yandex.Marketi otsing töötab ja mis juhtub, kui üks serveritest ebaõnnestub

Saame testklastri, mis on tõelistes "lahingutingimustes". Sinna läheb tavaline kasutajaliiklus. Mõlema klastri riistvara on sama, nii et jõudlust ja vigu saab võrrelda.

Ja kuna tasakaalustaja ignoreerib vastuseid täielikult, ei näe lõppkasutajad varjuklastri vastuseid. Seetõttu pole eksimine hirmutav.

Järeldused

Niisiis, kuidas me turuotsingu üles ehitasime?

Et kõik sujuks, eraldame funktsionaalsused eraldi teenusteks. Nii saame skaleerida ainult neid komponente, mida vajame, ja muuta komponendid lihtsamaks. Eraldi komponenti on lihtne teisele meeskonnale määrata ja sellega töötamise kohustusi jagada. Ja märkimisväärne raua kokkuhoid selle lähenemisviisiga on ilmne pluss.

Samuti aitab meid variklaster: saame teenuseid arendada, neid protsessi käigus testida ja kasutajat mitte häirida.

Noh, muidugi katsetamine tootmises. Kas soovite muuta tuhandete serverite konfiguratsiooni? Lihtne, kasutage Stop Tap. Nii saate valmis komplekslahenduse koheselt kasutusele võtta ja probleemide ilmnemisel tagasi stabiilsele versioonile tagasi kerida.

Loodan, et suutsin näidata, kuidas me muudame turu kiireks ja stabiilseks üha kasvava pakkumiste baasiga. Kuidas lahendame serveriprobleeme, tegeleme suure hulga päringutega, parandame teenuse paindlikkust ja teeme seda tööprotsesse katkestamata.

Allikas: www.habr.com

Lisa kommentaar