Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Hallo, mijn naam is Evgeniy. Ik werk in de zoekinfrastructuur van Yandex.Market. Ik wil de Habr-gemeenschap vertellen over de innerlijke keuken van de Markt - en ik heb veel te vertellen. Allereerst hoe de Marktzoekopdracht werkt, processen en architectuur. Hoe gaan we om met noodsituaties: wat gebeurt er als één server uitvalt? Wat als er 100 van dergelijke servers zijn?

Ook leer je hoe we nieuwe functionaliteit op meerdere servers tegelijk implementeren. En hoe we complexe diensten direct in productie testen, zonder enige overlast voor de gebruikers. Hoe de marktzoekopdracht in het algemeen werkt, zodat iedereen het naar zijn zin heeft.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Iets over ons: welk probleem wij oplossen

Wanneer u tekst invoert, op parameters naar een product zoekt of prijzen in verschillende winkels vergelijkt, worden alle verzoeken naar de zoekservice verzonden. Zoeken is de grootste dienst op de markt.

We verwerken alle zoekverzoeken: van de sites market.yandex.ru, beru.ru, de Supercheck-service, Yandex.Advisor, mobiele applicaties. We nemen ook productaanbiedingen op in de zoekresultaten op yandex.ru.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Met zoekservice bedoel ik niet alleen de zoekopdracht zelf, maar ook een database met alle aanbiedingen op de Markt. De schaal is als volgt: er worden meer dan een miljard zoekopdrachten per dag verwerkt. En alles moet snel en zonder onderbrekingen werken en altijd het gewenste resultaat opleveren.

Wat is wat: marktarchitectuur

Ik zal kort de huidige architectuur van de Markt beschrijven. Het kan grofweg worden beschreven aan de hand van het onderstaande diagram:
Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt
Laten we zeggen dat een partnerwinkel naar ons toe komt. Hij zegt dat ik speelgoed wil verkopen: deze boze kat met een pieper. En nog een boze kat zonder pieper. En gewoon een kat. Vervolgens moet de winkel aanbiedingen voorbereiden waarnaar de markt zoekt. De winkel genereert een speciale xml met aanbiedingen en communiceert het pad naar deze xml via de affiliate-interface. De indexer downloadt vervolgens periodiek deze xml, controleert op fouten en slaat alle informatie op in een enorme database.

Er zijn veel van dergelijke opgeslagen XML's. Op basis van deze database wordt een zoekindex gemaakt. De index wordt opgeslagen in intern formaat. Nadat de index is gemaakt, uploadt de Layout-service deze naar zoekservers.

Als gevolg hiervan verschijnt er een boze kat met een pieper in de database en verschijnt de index van de kat op de server.

Hoe we naar een kat zoeken, vertel ik je in het gedeelte over zoekarchitectuur.

Architectuur voor marktonderzoek

We leven in een wereld van microservices: elk binnenkomend verzoek markt.yandex.ru veroorzaakt veel subquery's en tientallen services zijn betrokken bij de verwerking ervan. Het diagram toont er slechts enkele:

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt
Vereenvoudigd verzoekverwerkingsschema

Elke dienst heeft iets geweldigs: een eigen balancer met een unieke naam:

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

De balancer geeft ons meer flexibiliteit bij het beheer van de dienst: je kunt bijvoorbeeld servers uitschakelen, wat vaak nodig is voor updates. De balancer ziet dat de server niet beschikbaar is en stuurt verzoeken automatisch door naar andere servers of datacenters. Bij het toevoegen of verwijderen van een server wordt de belasting automatisch herverdeeld tussen de servers.

De unieke naam van de balancer is niet afhankelijk van het datacenter. Wanneer service A een verzoek indient bij B, stuurt balancer B het verzoek standaard door naar het huidige datacenter. Als de dienst niet beschikbaar is of niet bestaat in het huidige datacenter, wordt het verzoek doorgestuurd naar andere datacenters.

Dankzij één enkele FQDN voor alle datacenters kan service A volledig abstraheren van locaties. Zijn verzoek aan dienst B wordt altijd in behandeling genomen. De uitzondering is het geval wanneer de dienst zich in alle datacenters bevindt.

Maar niet alles is zo rooskleurig bij deze balancer: we hebben een extra tussencomponent. De balancer is mogelijk onstabiel en dit probleem wordt opgelost door redundante servers. Er is ook een extra vertraging tussen diensten A en B. Maar in de praktijk is deze minder dan 1 ms en voor de meeste diensten is dit niet kritisch.

Omgaan met het onverwachte: evenwicht en veerkracht van zoekservices

Stel je voor dat er een ineenstorting plaatsvindt: je moet een kat met een pieper vinden, maar de server crasht. Of 100 servers. Hoe eruit te komen? Gaan we de gebruiker echt zonder kat achterlaten?

De situatie is beangstigend, maar we zijn er klaar voor. Ik zal het je in volgorde vertellen.

De zoekinfrastructuur bevindt zich in verschillende datacentra:

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Bij het ontwerpen houden we rekening met de mogelijkheid om één datacenter te sluiten. Het leven zit vol verrassingen - een graafmachine kan bijvoorbeeld een ondergrondse kabel doorsnijden (ja, dat is gebeurd). De capaciteit in de overige datacenters moet voldoende zijn om piekbelasting te kunnen opvangen.

Laten we een enkel datacenter beschouwen. Elk datacenter heeft hetzelfde balancer-bedieningsschema:

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt
Eén balancer bestaat uit minimaal drie fysieke servers. Deze redundantie is gemaakt voor betrouwbaarheid. Balancers draaien op HAProx.

We hebben voor HAProx gekozen vanwege de hoge prestaties, de lage resourcevereisten en de brede functionaliteit. Onze zoeksoftware draait op elke server.

De kans dat één server uitvalt is klein. Maar als u veel servers heeft, wordt de kans groter dat er minstens één uitvalt.

Dit is wat er in werkelijkheid gebeurt: servers crashen. Daarom is het noodzakelijk om voortdurend de status van alle servers te controleren. Als de server niet meer reageert, wordt deze automatisch losgekoppeld van het verkeer. Voor dit doel heeft HAProxy een ingebouwde gezondheidscontrole. Het gaat één keer per seconde naar alle servers met een HTTP-verzoek “/ping”.

Een ander kenmerk van HAProxy: agent-check zorgt ervoor dat u alle servers gelijkmatig kunt belasten. Om dit te doen, maakt HAProxy verbinding met alle servers, en ze retourneren hun gewicht afhankelijk van de huidige belasting van 1 tot 100. Het gewicht wordt berekend op basis van het aantal verzoeken in de wachtrij voor verwerking en de belasting van de processor.

Nu over het vinden van de kat. De zoekresultaten in verzoeken als: /search?text=boos+kat. Om de zoekopdracht snel te laten verlopen, moet de volledige cat-index in het RAM-geheugen passen. Zelfs lezen vanaf de SSD gaat niet snel genoeg.

Er was eens een aanbiedingsdatabase die klein was en het RAM-geheugen van één server was er voldoende voor. Naarmate het aanbod groeide, paste niet alles meer in dit RAM-geheugen en werden de gegevens in twee delen verdeeld: shard 1 en shard 2.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt
Maar dit gebeurt altijd: elke oplossing, zelfs een goede, leidt tot andere problemen.

De balancer ging nog steeds naar een willekeurige server. Maar op de machine waarop het verzoek kwam, was er slechts de helft van de index. De rest stond op andere servers. Daarom moest de server naar een naburige machine gaan. Nadat gegevens van beide servers waren ontvangen, werden de resultaten gecombineerd en opnieuw gerangschikt.

Omdat de balancer de verzoeken gelijkmatig verdeelt, waren alle servers bezig met het herrangschikken en niet alleen met het verzenden van gegevens.

Het probleem deed zich voor als een naburige server niet beschikbaar was. De oplossing was om meerdere servers met verschillende prioriteiten te specificeren als “naburige” server. Eerst werd het verzoek verzonden naar de servers in het huidige rack. Als er geen reactie kwam, werd het verzoek naar alle servers in dit datacenter gestuurd. En ten slotte ging het verzoek naar andere datacenters.
Naarmate het aantal voorstellen groeide, werden de gegevens in vier delen verdeeld. Maar dit was niet de limiet.

Momenteel wordt een configuratie van acht shards gebruikt. Om nog meer geheugen te besparen, is de index bovendien opgedeeld in een zoekgedeelte (dat wordt gebruikt voor het zoeken) en een fragmentgedeelte (dat niet bij het zoeken betrokken is).

Eén server bevat informatie voor slechts één scherf. Om de volledige index te doorzoeken, moet u daarom zoeken op acht servers die verschillende shards bevatten.

Servers zijn gegroepeerd in clusters. Elk cluster bevat acht zoekmachines en één snippetserver.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt
De fragmentserver voert een sleutel-waardedatabase uit met statische gegevens. Ze zijn nodig om documenten af ​​te geven, bijvoorbeeld een beschrijving van een kat met een pieper. De gegevens worden speciaal naar een aparte server overgebracht om het geheugen van zoekservers niet te belasten.

Omdat document-ID's slechts binnen één index uniek zijn, kan er een situatie ontstaan ​​waarin er geen documenten in de fragmenten voorkomen. Nou ja, of dat er voor één ID verschillende inhoud zal zijn. Om de zoekopdracht te laten werken en de resultaten te retourneren, was er daarom behoefte aan consistentie in het hele cluster. Hoe wij de consistentie monitoren, vertel ik hieronder.

De zoekopdracht zelf is als volgt opgebouwd: een zoekopdracht kan op elk van de acht servers terechtkomen. Laten we zeggen dat hij naar server 1 is gekomen. Deze server verwerkt alle argumenten en begrijpt waar en hoe hij moet zoeken. Afhankelijk van het binnenkomende verzoek kan de server aanvullende verzoeken doen aan externe diensten voor de benodigde informatie. Eén verzoek kan worden gevolgd door maximaal tien verzoeken aan externe diensten.

Na het verzamelen van de benodigde informatie begint een zoekopdracht in de aanboddatabase. Om dit te doen, worden er subquery's uitgevoerd naar alle acht servers in het cluster.

Zodra de reacties zijn ontvangen, worden de resultaten gecombineerd. Uiteindelijk kunnen er nog meerdere subquery's naar de fragmentserver nodig zijn om de resultaten te genereren.

Zoekopdrachten binnen het cluster zien er als volgt uit: /shard1?text=boos+kat. Bovendien worden er voortdurend één keer per seconde subquery's van het formulier gemaakt tussen alle servers binnen het cluster: /toestand.

onderzoek /toestand detecteert een situatie waarin de server niet beschikbaar is.

Het controleert ook of de zoekmachineversie en de indexversie op alle servers hetzelfde zijn, anders zullen er inconsistente gegevens binnen het cluster zijn.

Ondanks dat één snippetserver verzoeken van acht zoekmachines verwerkt, wordt de processor zeer licht belast. Daarom dragen we de fragmentgegevens nu over naar een aparte service.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Om gegevens over te dragen, hebben we universele sleutels voor documenten geïntroduceerd. Nu is het onmogelijk dat er een situatie ontstaat waarin inhoud uit een ander document wordt geretourneerd met behulp van één sleutel.

Maar de transitie naar een andere architectuur is nog niet voltooid. Nu willen we af van de dedicated snippet server. En dan helemaal afstappen van de clusterstructuur. Hierdoor kunnen we gemakkelijk blijven opschalen. Een extra bonus is een aanzienlijke ijzerbesparing.

En nu naar enge verhalen met een happy ending. Laten we een aantal gevallen bekijken waarin de server niet beschikbaar is.

Er is iets vreselijks gebeurd: één server is niet beschikbaar

Stel dat één server niet beschikbaar is. Dan kunnen de overige servers in het cluster blijven reageren, maar zijn de zoekresultaten onvolledig.

Via statuscontrole /toestand naburige servers begrijpen dat er één niet beschikbaar is. Om de volledigheid te behouden, worden daarom alle servers in het cluster per aanvraag weergegeven /ping ze beginnen op de balancer te reageren dat ze ook niet beschikbaar zijn. Het blijkt dat alle servers in het cluster zijn overleden (wat niet waar is). Dit is het grootste nadeel van ons clusterplan; daarom willen we er vanaf komen.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Aanvragen die mislukken met een fout, worden opnieuw verzonden door de balancer op andere servers.
De balancer stopt ook met het sturen van gebruikersverkeer naar dode servers, maar blijft de status ervan controleren.

Wanneer de server beschikbaar komt, begint deze te reageren /ping. Zodra normale reacties op pings van dode servers binnenkomen, beginnen balancers gebruikersverkeer daarheen te sturen. Clusterwerking is hersteld, hoera.

Erger nog: veel servers zijn niet beschikbaar

Een aanzienlijk deel van de servers in het datacenter wordt platgelegd. Wat te doen, waar te rennen? De balancer komt weer te hulp. Elke balancer slaat voortdurend het huidige aantal live servers in het geheugen op. Het berekent voortdurend de maximale hoeveelheid verkeer die het huidige datacenter kan verwerken.

Wanneer veel servers in een datacenter uitvallen, realiseert de balancer zich dat dit datacenter niet al het verkeer kan verwerken.

Vervolgens wordt het overtollige verkeer willekeurig verdeeld over andere datacenters. Alles werkt, iedereen is blij.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Hoe wij het doen: releases publiceren

Laten we het nu hebben over hoe we wijzigingen in de service publiceren. Hier zijn we de weg ingeslagen van het vereenvoudigen van processen: het uitrollen van een nieuwe release gebeurt vrijwel volledig geautomatiseerd.
Wanneer een bepaald aantal wijzigingen in het project is verzameld, wordt er automatisch een nieuwe release gemaakt en begint de build ervan.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Vervolgens wordt de service uitgerold om te testen, waarbij de stabiliteit van de werking wordt gecontroleerd.

Tegelijkertijd worden automatische prestatietests gelanceerd. Dit wordt afgehandeld door een speciale dienst. Ik zal er nu niet over praten - de beschrijving ervan is een apart artikel waard.

Als de publicatie tijdens het testen succesvol is, wordt de publicatie van de release in prestable automatisch gestart. Prestable is een speciaal cluster waar normaal gebruikersverkeer naartoe wordt geleid. Als er een fout wordt geretourneerd, doet de balancer een nieuw verzoek tot productie.

In prestable worden responstijden gemeten en vergeleken met de vorige release in productie. Als alles in orde is, maakt iemand verbinding: controleert de grafieken en resultaten van de belastingtests en begint vervolgens met het uitrollen naar productie.

Het beste gaat naar de gebruiker: A/B-testen

Het is niet altijd duidelijk of wijzigingen in een dienst daadwerkelijke voordelen opleveren. Om het nut van veranderingen te meten, bedachten mensen A/B-testen. Ik zal je iets vertellen over hoe het werkt in Yandex.Market Search.

Het begint allemaal met het toevoegen van een nieuwe CGI-parameter die nieuwe functionaliteit mogelijk maakt. Laat onze parameter zijn: market_new_functionality=1. Vervolgens schakelen we in de code deze functionaliteit in als de vlag aanwezig is:

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

Nieuwe functionaliteit wordt uitgerold naar productie.

Om A/B-testen te automatiseren, is er een speciale service die gedetailleerde informatie biedt hier beschreven. Er wordt een experiment gemaakt in de service. Het verkeersaandeel is bijvoorbeeld vastgesteld op 15%. Percentages worden niet ingesteld voor zoekopdrachten, maar voor gebruikers. Ook wordt de duur van het experiment aangegeven, bijvoorbeeld een week.

Er kunnen meerdere experimenten tegelijkertijd worden uitgevoerd. In de instellingen kun je aangeven of kruising met andere experimenten mogelijk is.

Als gevolg hiervan voegt de service automatisch een argument toe market_new_functionality=1 tot 15% van de gebruikers. Het berekent ook automatisch de geselecteerde statistieken. Nadat het experiment is voltooid, kijken analisten naar de resultaten en trekken ze conclusies. Op basis van de bevindingen wordt besloten tot uitrol naar productie of verfijning.

De behendige hand van Market: testen in productie

Het komt vaak voor dat u de werking van een nieuwe functionaliteit in productie moet testen, maar u weet niet zeker hoe deze zich zal gedragen in "gevechts" omstandigheden onder zware belasting.

Er is een oplossing: vlaggen in CGI-parameters kunnen niet alleen worden gebruikt voor A/B-testen, maar ook om nieuwe functionaliteit te testen.

We hebben een tool gemaakt waarmee u direct de configuratie op duizenden servers kunt wijzigen zonder de service aan risico's bloot te stellen. Het heet Stop Tap. Het oorspronkelijke idee was om zonder lay-out snel bepaalde functionaliteit uit te kunnen schakelen. Vervolgens breidde de tool zich uit en werd complexer.

Het servicestroomdiagram wordt hieronder weergegeven:

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

Vlagwaarden worden via de API ingesteld. De beheerdienst slaat deze waarden op in de database. Alle servers gaan één keer per tien seconden naar de database, pompen er vlagwaarden uit en passen deze waarden toe op elk verzoek.

In de Stop-tap kunt u twee soorten waarden instellen:

1) Voorwaardelijke expressies. Toepassen wanneer een van de waarden waar is. Bijvoorbeeld:

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

De waarde "3" wordt toegepast wanneer het verzoek wordt verwerkt op locatie DC1. En de waarde is “4” wanneer het verzoek wordt verwerkt op het tweede cluster voor de beru.ru-site.

2) Onvoorwaardelijke waarden. Standaard toepassen als aan geen van de voorwaarden is voldaan. Bijvoorbeeld:

waarde, waarde!

Als een waarde eindigt met een uitroepteken, krijgt deze een hogere prioriteit.

De CGI-parameterparser parseert de URL. Vervolgens gelden de waarden uit de Stop Tap.

Waarden met de volgende prioriteiten worden toegepast:

  1. Met verhoogde prioriteit van de Stop Tap (uitroepteken).
  2. De waarde uit de aanvraag.
  3. Standaardwaarde van Stop kraan.
  4. Standaardwaarde in code.

Er zijn veel vlaggen die worden aangegeven in voorwaardelijke waarden - ze zijn voldoende voor alle ons bekende scenario's:

  • Datacentrum.
  • Omgeving: productie, testen, schaduw.
  • Locatie: markt, beru.
  • Clusternummer.

Met deze tool kunt u nieuwe functionaliteit inschakelen op een bepaalde groep servers (bijvoorbeeld in slechts één datacenter) en de werking van deze functionaliteit testen zonder enig risico voor de gehele dienst. Zelfs als je ergens een ernstige fout hebt gemaakt, alles begint in te storten en het hele datacenter uitvalt, balancers zullen verzoeken doorsturen naar andere datacenters. Eindgebruikers merken er niets van.

Als u een probleem opmerkt, kunt u de vlag onmiddellijk terugzetten naar de vorige waarde en worden de wijzigingen ongedaan gemaakt.

Deze service heeft ook zijn nadelen: de ontwikkelaars zijn er dol op en proberen vaak alle wijzigingen in de Stop Tap te pushen. Wij proberen misbruik tegen te gaan.

De Stop Tap-aanpak werkt goed als u al over stabiele code beschikt die klaar is om naar productie te worden uitgerold. Tegelijkertijd twijfel je nog steeds en wil je de code controleren in 'gevechts'-omstandigheden.

Stop Tap is echter niet geschikt om te testen tijdens de ontwikkeling. Er is een apart cluster voor ontwikkelaars, het ‘schaduwcluster’.

Geheime testen: Shadow Cluster

Verzoeken van een van de clusters worden gedupliceerd naar het schaduwcluster. Maar de balancer negeert de reacties van dit cluster volledig. Het diagram van de werking ervan wordt hieronder weergegeven.

Hoe Yandex.Market-zoeken werkt en wat er gebeurt als een van de servers uitvalt

We krijgen een testcluster dat zich in echte ‘gevechts’-omstandigheden bevindt. Normaal gebruikersverkeer gaat daarheen. De hardware in beide clusters is hetzelfde, waardoor prestaties en fouten kunnen worden vergeleken.

En omdat de balancer de reacties volledig negeert, zullen eindgebruikers de reacties van het schaduwcluster niet zien. Daarom is het niet eng om een ​​fout te maken.

Bevindingen

Hoe hebben we de marktzoekopdracht opgebouwd?

Om alles soepel te laten verlopen, scheiden we functionaliteit in aparte diensten. Op deze manier kunnen we alleen die componenten schalen die we nodig hebben en de componenten eenvoudiger maken. Het is gemakkelijk om een ​​afzonderlijk onderdeel aan een ander team toe te wijzen en de verantwoordelijkheden om eraan te werken te delen. En aanzienlijke besparingen op ijzer met deze aanpak zijn een duidelijk pluspunt.

Ook het schaduwcluster helpt ons: we kunnen diensten ontwikkelen, deze onderweg testen en de gebruiker niet storen.

Nou ja, testen in de productie natuurlijk. Wilt u de configuratie op duizenden servers wijzigen? Makkelijk, gebruik de Stop Tap. Zo kun je direct een kant-en-klare complexe oplossing uitrollen en bij problemen terugrollen naar een stabiele versie.

Ik hoop dat ik heb kunnen laten zien hoe we de markt snel en stabiel maken met een steeds groter aanbod. Hoe wij serverproblemen oplossen, een groot aantal verzoeken afhandelen, de flexibiliteit van de dienstverlening verbeteren en dit doen zonder werkprocessen te onderbreken.

Bron: www.habr.com

Voeg een reactie