Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Sveiki, mano vardas Jevgenijus. Dirbu Yandex.Market paieškos infrastruktūroje. Noriu papasakoti Habrų bendruomenei apie vidinę turgaus virtuvę – ir turiu daug ką pasakyti. Visų pirma, kaip veikia Market paieška, procesai ir architektūra. Kaip elgiamės kritinėse situacijose: kas nutiks, jei vienas serveris suges? O jei tokių serverių yra 100?

Taip pat sužinosite, kaip vienu metu įdiegiame naujas funkcijas daugybėje serverių. Ir kaip mes išbandome sudėtingas paslaugas tiesiogiai gamyboje, nesukeldami naudotojams nepatogumų. Apskritai, kaip veikia Market paieška, kad visi gerai praleistų laiką.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Šiek tiek apie mus: kokią problemą sprendžiame

Įvedus tekstą, ieškant prekės pagal parametrus ar palyginus kainas skirtingose ​​parduotuvėse, visos užklausos siunčiamos į paieškos paslaugą. Paieška yra didžiausia paslauga rinkoje.

Apdorojame visas paieškos užklausas: iš svetainių market.yandex.ru, beru.ru, „Supercheck“ paslaugos, „Yandex.Advisor“, mobiliųjų programų. Taip pat į yandex.ru paieškos rezultatus įtraukiame produktų pasiūlymus.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Paieškos paslauga turiu omenyje ne tik pačią paiešką, bet ir duomenų bazę su visais rinkoje esančiais pasiūlymais. Mastas yra toks: per dieną apdorojama daugiau nei milijardas paieškos užklausų. Ir viskas turėtų veikti greitai, be pertrūkių ir visada duoti norimą rezultatą.

Kas yra kas: rinkos architektūra

Trumpai apibūdinsiu dabartinę Turgaus architektūrą. Tai galima apytiksliai apibūdinti žemiau esančia diagrama:
Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda
Tarkime, pas mus ateina partnerių parduotuvė. Jis sako, kad noriu parduoti žaislą: šitą piktą katę su squeaker. Ir dar vienas piktas katinas be girgždėjimo. Ir tik katė. Tada parduotuvė turi paruošti pasiūlymus, kurių ieško Rinka. Parduotuvė sugeneruoja specialų xml su pasiūlymais ir perduoda kelią į šį xml per filialo sąsają. Tada indeksuotojas periodiškai atsisiunčia šį xml, patikrina, ar nėra klaidų, ir išsaugo visą informaciją į didžiulę duomenų bazę.

Yra daug tokių išsaugotų xml. Iš šios duomenų bazės sukuriamas paieškos indeksas. Indeksas saugomas vidiniu formatu. Sukūrus indeksą, Layout paslauga įkelia jį į paieškos serverius.

Dėl to duomenų bazėje atsiranda pikta katė su squeaker, o katės indeksas pasirodo serveryje.

Papasakosiu, kaip mes ieškome katės, dalyje apie paieškos architektūrą.

Rinkos paieškos architektūra

Mes gyvename mikropaslaugų pasaulyje: kiekviena gaunama užklausa market.yandex.ru sukelia daug antrinių užklausų, o jas apdorojant dalyvauja dešimtys paslaugų. Diagramoje parodyta tik keletas:

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda
Supaprastinta užklausų apdorojimo schema

Kiekviena paslauga turi nuostabų dalyką – savo balansuotoją unikaliu pavadinimu:

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Balansuoklis suteikia mums daugiau lankstumo valdant paslaugą: galite, pavyzdžiui, išjungti serverius, o tai dažnai reikalinga naujinimams. Balansuotojas mato, kad serveris nepasiekiamas, ir automatiškai peradresuoja užklausas į kitus serverius ar duomenų centrus. Pridedant arba pašalinant serverį, apkrova automatiškai perskirstoma tarp serverių.

Unikalus balansyro pavadinimas nepriklauso nuo duomenų centro. Kai paslauga A pateikia užklausą B, tada pagal numatytuosius nustatymus balansuotojas B nukreipia užklausą į dabartinį duomenų centrą. Jei paslauga nepasiekiama arba jos nėra dabartiniame duomenų centre, užklausa nukreipiama į kitus duomenų centrus.

Vienas FQDN visiems duomenų centrams leidžia paslaugai A visiškai abstrahuotis nuo vietų. Jo prašymas paslaugai B visada bus nagrinėjamas. Išimtis yra atvejis, kai paslauga teikiama visuose duomenų centruose.

Tačiau su šiuo balansuotoju ne viskas taip rožiškai: turime papildomą tarpinį komponentą. Balansuotojas gali būti nestabilus, ir šią problemą išsprendžia pertekliniai serveriai. Taip pat yra papildomas delsimas tarp paslaugų A ir B. Tačiau praktiškai tai yra mažiau nei 1 ms ir daugumai paslaugų tai nėra labai svarbu.

Kaip elgtis su netikėtumais: paieškos paslaugų balansas ir atsparumas

Įsivaizduokite, kad yra žlugimas: reikia rasti katę su girgždėjimu, bet serveris sugenda. Arba 100 serverių. Kaip išeiti? Ar tikrai paliksime vartotoją be katės?

Situacija baisi, bet esame tam pasiruošę. Pasakysiu eilės tvarka.

Paieškos infrastruktūra yra keliuose duomenų centruose:

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Projektuodami įtraukiame galimybę išjungti vieną duomenų centrą. Gyvenimas kupinas netikėtumų – pavyzdžiui, ekskavatorius gali nupjauti požeminį kabelį (taip, taip ir atsitiko). Likusių duomenų centrų talpos turėtų pakakti, kad atlaikytų didžiausią apkrovą.

Panagrinėkime vieną duomenų centrą. Kiekvienas duomenų centras turi tą pačią balansavimo schemą:

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda
Vienas balansuotojas yra mažiausiai trys fiziniai serveriai. Šis perteklius sukurtas siekiant patikimumo. Balansuotojai veikia HAProx.

HAProx pasirinkome dėl didelio našumo, mažų išteklių poreikio ir plataus funkcionalumo. Mūsų paieškos programinė įranga veikia kiekviename serveryje.

Tikimybė, kad vienas serveris suges, yra maža. Bet jei turite daug serverių, padidėja tikimybė, kad bent vienas suges.

Taip atsitinka realybėje: serveriai sugenda. Todėl būtina nuolat stebėti visų serverių būseną. Jei serveris nustoja reaguoti, jis automatiškai atjungiamas nuo srauto. Šiuo tikslu HAProxy turi įmontuotą sveikatos patikrinimą. Jis siunčiamas į visus serverius kartą per sekundę su HTTP užklausa „/ping“.

Kita HAProxy savybė: agento tikrinimas leidžia tolygiai įkelti visus serverius. Norėdami tai padaryti, HAProxy prisijungia prie visų serverių ir jie grąžina savo svorį priklausomai nuo esamos apkrovos nuo 1 iki 100. Svoris apskaičiuojamas pagal užklausų skaičių eilėje apdorojimui ir procesoriaus apkrovą.

Dabar apie katės radimą. Paieškos rezultatai tokiose užklausose kaip: /search?text=piktas+katinas. Kad paieška būtų greita, visas kačių indeksas turi tilpti į RAM. Net skaitymas iš SSD nėra pakankamai greitas.

Kažkada pasiūlymų duomenų bazė buvo maža, jai užteko vieno serverio RAM. Didėjant pasiūlymų bazei, viskas nebetilpo į šią RAM, o duomenys buvo padalinti į dvi dalis: shard 1 ir shard 2.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda
Tačiau taip nutinka visada: bet koks sprendimas, net ir geras, sukelia kitų problemų.

Balansuotojas vis tiek nuėjo į bet kurį serverį. Tačiau mašinoje, kurioje buvo pateiktas prašymas, buvo tik pusė indekso. Likusi dalis buvo kituose serveriuose. Todėl serveris turėjo pereiti prie kažkokios kaimyninės mašinos. Gavus duomenis iš abiejų serverių, rezultatai buvo sujungti ir perrikiuoti.

Kadangi balansavimo priemonė užklausas paskirsto tolygiai, visi serveriai buvo įtraukti ne tik į duomenų siuntimą, o į reitingavimą.

Problema kilo, jei kaimyninis serveris buvo nepasiekiamas. Sprendimas buvo nurodyti kelis serverius su skirtingais prioritetais kaip „kaimyninį“ serverį. Pirma, užklausa buvo išsiųsta serveriams dabartiniame stove. Jei atsakymo nebuvo, užklausa buvo išsiųsta į visus šio duomenų centro serverius. Ir galiausiai užklausa nukeliavo į kitus duomenų centrus.
Didėjant pasiūlymų skaičiui, duomenys buvo suskirstyti į keturias dalis. Tačiau tai nebuvo riba.

Šiuo metu naudojama aštuonių skeveldrų konfigūracija. Be to, norint sutaupyti dar daugiau atminties, indeksas buvo padalintas į paieškos dalį (kuri naudojama paieškai) ir fragmento dalį (kuri nedalyvauja paieškoje).

Viename serveryje yra tik vienos skeveldros informacija. Todėl norėdami ieškoti viso indekso, turite ieškoti aštuoniuose serveriuose, kuriuose yra skirtingų fragmentų.

Serveriai yra sugrupuoti į grupes. Kiekviename klasteryje yra aštuoni paieškos varikliai ir vienas fragmentų serveris.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda
Fragmentų serveris paleidžia raktų reikšmių duomenų bazę su statiniais duomenimis. Jų reikia norint išduoti dokumentus, pavyzdžiui, katės su squeaker aprašymu. Duomenys specialiai perkeliami į atskirą serverį, kad neapkrautų paieškos serverių atminties.

Kadangi dokumentų ID yra unikalūs tik viename indekse, gali susidaryti situacija, kai fragmentuose nėra dokumentų. Na, arba kad vienam ID bus kitoks turinys. Todėl norint, kad paieška veiktų ir rezultatai būtų grąžinti, reikėjo nuoseklumo visame klasteryje. Toliau papasakosiu, kaip stebime nuoseklumą.

Pačios paieškos struktūra yra tokia: paieškos užklausa gali būti pateikta bet kuriame iš aštuonių serverių. Tarkime, jis atėjo į serverį 1. Šis serveris apdoroja visus argumentus ir supranta, ko ir kaip reikia ieškoti. Priklausomai nuo gaunamos užklausos, serveris gali pateikti papildomų užklausų išorinėms tarnyboms dėl reikalingos informacijos. Po vienos užklausos gali būti pateikta iki dešimties užklausų išorinėms tarnyboms.

Surinkus reikiamą informaciją, pradedama paieška pasiūlymų duomenų bazėje. Norėdami tai padaryti, antrinės užklausos pateikiamos visiems aštuoniems klasterio serveriams.

Gavus atsakymus, rezultatai sujungiami. Galų gale, norint sugeneruoti rezultatus, gali prireikti dar kelių fragmentų serverio antrinių užklausų.

Paieškos užklausos klasteryje atrodo taip: /shard1?text=piktas+katinas. Be to, tarp visų klasterio serverių nuolat atliekamos formos papildomos užklausos kartą per sekundę: /statusas.

Prašymas /statusas aptinka situaciją, kai serveris nepasiekiamas.

Ji taip pat kontroliuoja, kad paieškos variklio versija ir indekso versija būtų vienoda visuose serveriuose, kitaip klasteryje bus nenuoseklūs duomenys.

Nepaisant to, kad vienas fragmentų serveris apdoroja aštuonių paieškos sistemų užklausas, jo procesorius apkraunamas labai mažai. Todėl dabar fragmento duomenis perkeliame į atskirą paslaugą.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Duomenims perduoti pristatėme universalius dokumentų raktus. Dabar neįmanoma situacija, kai turinys iš kito dokumento grąžinamas naudojant vieną raktą.

Tačiau perėjimas prie kitos architektūros dar nebaigtas. Dabar norime atsikratyti tam skirto fragmento serverio. Ir tada visiškai atsitraukite nuo klasterio struktūros. Tai leis mums ir toliau lengvai didinti mastelį. Papildoma premija yra didelis geležies sutaupymas.

O dabar prie baisių istorijų su laiminga pabaiga. Panagrinėkime kelis serverio nepasiekiamumo atvejus.

Atsitiko kažkas baisaus: vienas serveris nepasiekiamas

Tarkime, kad vienas serveris nepasiekiamas. Tada likę klasteryje esantys serveriai gali toliau reaguoti, tačiau paieškos rezultatai bus neišsamūs.

Per būsenos patikrinimą /statusas kaimyniniai serveriai supranta, kad vienas nepasiekiamas. Todėl, siekiant išlaikyti išsamumą, visi serveriai klasteryje pagal užklausą /ping jie pradeda atsakyti balansuotojui, kad jie taip pat nepasiekiami. Pasirodo, visi klasterio serveriai mirė (tai netiesa). Tai yra pagrindinis mūsų klasterio schemos trūkumas – štai kodėl norime nuo jo atsiriboti.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Užklausas, kurios nepavyksta dėl klaidos, balansavimo priemonė iš naujo siunčia kituose serveriuose.
Balansuotojas taip pat nustoja siųsti vartotojų srautą į neveikiančius serverius, bet toliau tikrina jų būseną.

Kai serveris tampa prieinamas, jis pradeda reaguoti /ping. Kai tik pradeda gauti įprasti atsakymai į ping iš negyvų serverių, balansuotojai pradeda ten siųsti vartotojų srautą. Klasterio veikimas atkurtas, hurra.

Dar blogiau: daugelis serverių nepasiekiami

Nemaža dalis duomenų centre esančių serverių yra iškirsti. Ką daryti, kur bėgti? Balansuotojas vėl ateina į pagalbą. Kiekvienas balansuotojas nuolat saugo atmintyje esamą tiesioginių serverių skaičių. Ji nuolat skaičiuoja didžiausią srautą, kurį gali apdoroti dabartinis duomenų centras.

Kai sugenda daug serverių duomenų centre, balansuotojas supranta, kad šis duomenų centras negali apdoroti viso srauto.

Tada perteklinis srautas pradedamas atsitiktinai paskirstyti kitiems duomenų centrams. Viskas veikia, visi patenkinti.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Kaip tai darome: leidinių leidyba

Dabar pakalbėkime apie tai, kaip skelbiame paslaugos pakeitimus. Čia mes pasirinkome procesų supaprastinimo kelią: naujo leidimo išleidimas yra beveik visiškai automatizuotas.
Kai projekte sukaupiamas tam tikras skaičius pakeitimų, automatiškai sukuriamas naujas leidimas ir pradedamas jo kūrimas.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Tada paslauga iškeliama į testavimą, kur patikrinamas veikimo stabilumas.

Tuo pačiu metu pradedamas automatinis veikimo testavimas. Tai atlieka speciali tarnyba. Dabar apie tai nekalbėsiu - jo aprašymas vertas atskiro straipsnio.

Jei bandymo metu paskelbimas sėkmingas, leidimas paskelbiamas prestable formatu automatiškai pradedamas. Prestable yra specialus klasteris, į kurį nukreipiamas įprastas vartotojų srautas. Jei jis grąžina klaidą, balansuotojas pateikia pakartotinę užklausą gamybai.

Prestable atveju atsako laikas matuojamas ir lyginamas su ankstesniu gamybos leidimu. Jei viskas gerai, tada žmogus prisijungia: patikrina apkrovos testavimo grafikus ir rezultatus ir tada pradeda riedėti į gamybą.

Viskas, kas geriausia, atitenka vartotojui: A/B testavimas

Ne visada akivaizdu, ar paslaugos pakeitimai duos realios naudos. Norėdami įvertinti pakeitimų naudingumą, žmonės sugalvojo A/B testavimą. Aš jums šiek tiek papasakosiu, kaip tai veikia „Yandex.Market“ paieškoje.

Viskas prasideda pridėjus naują CGI parametrą, kuris įgalina naujas funkcijas. Tegul mūsų parametras yra: market_new_functionality=1. Tada kode įjungiame šią funkciją, jei yra vėliavėlė:

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

Naujos funkcijos pristatomos į gamybą.

Norint automatizuoti A/B testavimą, yra speciali paslauga, kuri detalizuoja aprašyta čia. Paslaugoje sukuriamas eksperimentas. Srauto dalis nustatoma, pavyzdžiui, 15 proc. Procentai nustatomi ne užklausoms, o vartotojams. Taip pat nurodoma eksperimento trukmė, pavyzdžiui, savaitė.

Vienu metu galima atlikti kelis eksperimentus. Nustatymuose galite nurodyti, ar galimas susikirtimas su kitais eksperimentais.

Dėl to paslauga automatiškai prideda argumentą market_new_functionality=1 iki 15% vartotojų. Taip pat automatiškai apskaičiuojama pasirinkta metrika. Baigę eksperimentą, analitikai žiūri į rezultatus ir daro išvadas. Remiantis išvadomis, priimamas sprendimas pradėti gaminti arba tobulinti.

Gudri rinkos ranka: bandymai gamyboje

Dažnai atsitinka taip, kad jums reikia išbandyti naujos funkcijos veikimą gamyboje, tačiau nesate tikri, kaip jis elgsis „kovinėmis“ sąlygomis esant didelei apkrovai.

Yra sprendimas: vėliavėlės CGI parametruose gali būti naudojamos ne tik A/B testavimui, bet ir naujo funkcionalumo testavimui.

Sukūrėme įrankį, kuris leidžia akimirksniu pakeisti konfigūraciją tūkstančiuose serverių, nesukeliant pavojaus paslaugai. Jis vadinamas Stop Tap. Pradinė idėja buvo galimybė greitai išjungti kai kurias funkcijas be išdėstymo. Tada įrankis išsiplėtė ir tapo sudėtingesnis.

Aptarnavimo eigos schema pateikta žemiau:

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Vėliavos reikšmės nustatomos per API. Valdymo paslauga saugo šias reikšmes duomenų bazėje. Visi serveriai eina į duomenų bazę kartą per dešimt sekundžių, išpumpuoja vėliavėlių reikšmes ir taiko šias reikšmes kiekvienai užklausai.

Stop bakstelėjime galite nustatyti dviejų tipų reikšmes:

1) Sąlyginės išraiškos. Taikyti, kai viena iš reikšmių yra teisinga. Pavyzdžiui:

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

Reikšmė „3“ bus taikoma, kai užklausa bus apdorojama vietoje DC1. Ir reikšmė yra „4“, kai užklausa apdorojama antrajame beru.ru svetainės klasteryje.

2) Besąlyginės reikšmės. Taikyti pagal numatytuosius nustatymus, jei netenkinama nė viena iš sąlygų. Pavyzdžiui:

vertė, vertė!

Jei reikšmė baigiasi šauktuku, jai suteikiamas didesnis prioritetas.

CGI parametrų analizatorius analizuoja URL. Tada pritaikomos „Stop Tap“ reikšmės.

Taikomos vertybės su šiais prioritetais:

  1. Su padidintu prioritetu iš Stop Tap (šauktukas).
  2. Užklausos vertė.
  3. Numatytoji reikšmė iš Stop bakstelėjimo.
  4. Numatytoji reikšmė kode.

Yra daug vėliavėlių, kurios nurodomos sąlyginėse reikšmėse - jų pakanka visiems mums žinomiems scenarijams:

  • Duomenų centras.
  • Aplinka: gamyba, bandymai, šešėlis.
  • Vieta: turgus, beru.
  • Klasterio numeris.

Naudodami šį įrankį galite įjungti naujas funkcijas tam tikroje serverių grupėje (pavyzdžiui, tik viename duomenų centre) ir išbandyti šios funkcijos veikimą be jokios ypatingos rizikos visai paslaugai. Net jei kur nors padarėte rimtą klaidą, viskas pradėjo kristi ir visas duomenų centras sugriuvo, balansuotojai nukreips užklausas į kitus duomenų centrus. Galutiniai vartotojai nieko nepastebės.

Jei pastebėsite problemą, galite iš karto grąžinti vėliavėlę į ankstesnę vertę ir pakeitimai bus atšaukti.

Ši paslauga turi ir minusų: kūrėjai ją labai mėgsta ir dažnai visus pakeitimus stengiasi įstumti į Stop Tap. Mes stengiamės kovoti su piktnaudžiavimu.

„Stop Tap“ metodas gerai veikia, kai jau turite stabilų kodą, paruoštą pradėti gaminti. Tuo pačiu metu jūs vis dar turite abejonių ir norite patikrinti kodą „kovinėmis“ sąlygomis.

Tačiau „Stop Tap“ netinka bandymams kūrimo metu. Kūrėjams yra atskiras klasteris, vadinamas „šešėlių grupe“.

Slaptas bandymas: šešėlių grupė

Užklausos iš vienos iš grupių dubliuojamos šešėlinėje grupėje. Tačiau balansuotojas visiškai nepaiso atsakymų iš šios grupės. Jo veikimo schema pateikta žemiau.

Kaip veikia „Yandex.Market“ paieška ir kas atsitiks, jei vienas iš serverių sugenda

Gauname bandymų grupę, kuri yra tikromis „kovinėmis“ sąlygomis. Ten vyksta įprastas vartotojų srautas. Abiejų grupių aparatinė įranga yra ta pati, todėl galima palyginti našumą ir klaidas.

Kadangi balansavimo priemonė visiškai nepaiso atsakymų, galutiniai vartotojai nematys atsakymų iš šešėlinės grupės. Todėl suklysti nėra baisu.

išvados

Taigi, kaip sukūrėme Market paiešką?

Kad viskas vyktų sklandžiai, funkcionalumą išskirstome į atskiras paslaugas. Tokiu būdu galime pakeisti tik tuos komponentus, kurių mums reikia, ir padaryti komponentus paprastesnius. Lengva priskirti atskirą komponentą kitai komandai ir pasidalyti atsakomybe už darbą su juo. Ir didelis geležies sutaupymas naudojant šį metodą yra akivaizdus pliusas.

Mums padeda ir šešėlių klasteris: galime kurti paslaugas, jas testuoti proceso metu ir netrukdyti vartotojui.

Na, žinoma, bandymai gamyboje. Reikia pakeisti konfigūraciją tūkstančiuose serverių? Lengva, naudokite „Stop Tap“. Tokiu būdu galite iš karto įdiegti paruoštą sudėtingą sprendimą ir grįžti prie stabilios versijos, jei kiltų problemų.

Tikiuosi, kad galėjau parodyti, kaip mes darome rinką greitą ir stabilią su nuolat augančia pasiūlymų baze. Kaip mes sprendžiame serverio problemas, sprendžiame daugybę užklausų, geriname paslaugos lankstumą ir tai darome nenutraukdami darbo procesų.

Šaltinis: www.habr.com

Добавить комментарий