Lastoptimering på ett Highload-projekt med ElasticSearch

Hej, Habr! Jag heter Maxim Vasiliev, jag arbetar som analytiker och projektledare på FINCH. Idag skulle jag vilja berätta hur vi med ElasticSearch kunde bearbeta 15 miljoner förfrågningar på 6 minuter och optimera den dagliga belastningen på webbplatsen för en av våra kunder. Tyvärr kommer vi att behöva klara oss utan namn, eftersom vi har en NDA hoppas vi att innehållet i artikeln inte kommer att drabbas av detta. Nu går vi.

Hur projektet fungerar

På vår backend skapar vi tjänster som säkerställer funktionaliteten hos våra kunders webbplatser och mobilapplikationer. Den allmänna strukturen kan ses i diagrammet:

Lastoptimering på ett Highload-projekt med ElasticSearch

Under arbetets gång behandlar vi ett stort antal transaktioner: inköp, betalningar, transaktioner med användarsaldon, för vilka vi lagrar många loggar, och importerar och exporterar även dessa data till externa system.

Det finns också omvända processer när vi tar emot data från klienten och överför den till användaren. Utöver det finns även processer för att arbeta med betalningar och bonusprogram.

Kort bakgrund

Till en början använde vi PostgreSQL som vår enda datalagring. Dess fördelar är standard för ett DBMS: närvaron av transaktioner, ett utvecklat språk för datahämtning, ett brett utbud av verktyg för integration; i kombination med bra prestanda tillfredsställde våra behov under en ganska lång tid.

Vi lagrade absolut all data i Postgres: från transaktioner till nyheter. Men antalet användare växte, och med det antalet förfrågningar.

För att förstå, det årliga antalet sessioner under 2017 bara på skrivbordswebbplatsen var 131 miljoner. 2018 - 125 miljoner. 2019 igen 130 miljoner. Lägg till ytterligare 100-200 miljoner från mobilversionen av webbplatsen och mobilapplikationen, och du kommer att få ett kolossalt antal förfrågningar.

När projektet växte kunde Postgres inte längre klara av belastningen; vi kunde inte hänga med - ett stort antal olika frågor dök upp, för vilka vi inte kunde skapa ett tillräckligt antal index.

Vi insåg att det fanns ett behov av andra datalager som skulle möta våra behov och ta belastningen av PostgreSQL. Elasticsearch och MongoDB ansågs vara möjliga alternativ. Den senare förlorade på följande punkter:

  1. Långsam indexeringshastighet när datavolymen i index växer. Med Elastic beror hastigheten inte på mängden data.
  2. Ingen fulltextsökning

Så vi valde Elastic för oss själva och förberedde oss för övergången.

Byt till Elastic

1. Vi startade övergången med en söktjänst på försäljningsställen. Vår kund har totalt cirka 70 000 försäljningsställen och samtidigt krävs flera typer av sökning på hemsidan och i applikationen:

  • Textsökning efter ortsnamn
  • Geosökning inom en given radie från en viss punkt. Till exempel om en användare vill se vilka försäljningsställen som ligger närmast hans bostad.
  • Sök efter en given ruta - användaren skisserar en ruta på kartan och alla punkter i denna radie visas för honom.
  • Sök med ytterligare filter. Försäljningsställen skiljer sig från varandra i sortiment

På tal om organisationen, i Postgres har vi en datakälla för både kartan och nyheterna, och i Elastic gör vi Snapshots från originaldata. Faktum är att Postgres till en början inte klarade av att söka efter alla kriterier. Inte bara fanns det många index, de kunde också överlappa varandra, så Postgres-schemaläggaren gick förlorad och förstod inte vilket index som skulle användas.

2. Näst på tur var nyhetssektionen. Publikationer dyker upp på sajten varje dag för att användaren inte ska gå vilse i informationsflödet, uppgifterna måste sorteras innan de ges ut. Detta är vad en sökning är till för: på sajten kan du söka efter textmatchning, och samtidigt ansluta ytterligare filter, eftersom de också görs genom Elastic.

3. Sedan flyttade vi transaktionsbearbetning. Användare kan köpa en specifik produkt på sajten och delta i en prisdragning. Efter sådana köp behandlar vi en stor mängd data, särskilt på helger och helgdagar. Som jämförelse, om antalet inköp under normala dagar är någonstans runt 1,5-2 miljoner, kan siffran på helgdagar nå 53 miljoner.

Samtidigt måste data bearbetas på ett minimum av tid—användare gillar inte att vänta flera dagar på resultat. Det finns inget sätt att uppnå sådana deadlines genom Postgres - vi fick ofta blockeringar, och medan vi behandlade alla förfrågningar kunde användare inte kontrollera om de fick priser eller inte. Detta är inte särskilt trevligt för företag, så vi flyttade bearbetningen till Elasticsearch.

Periodicitet

Nu konfigureras uppdateringar händelsebaserade, enligt följande villkor:

  1. Försäljningsställen. Så fort vi får data från en extern källa lanserar vi omedelbart en uppdatering.
  2. Nyheter. Så fort någon nyhet redigeras på sajten skickas den automatiskt till Elastic.

Här är det återigen värt att nämna fördelarna med Elastic. I Postgres, när du skickar en förfrågan, måste du vänta tills den ärligt behandlar alla poster. Du kan skicka 10 tusen skivor till Elastic och börja arbeta direkt, utan att vänta på att skivorna ska distribueras till alla Shards. Naturligtvis kan vissa Shard eller Replica inte se data direkt, men mycket snart kommer allt att vara tillgängligt.

Integrationsmetoder

Det finns två sätt att integrera med Elastic:

  1. Via en inbyggd klient via TCP. Den inbyggda drivrutinen håller på att dö ut: den stöds inte längre och dess syntax är mycket obekväm. Därför använder vi det praktiskt taget inte och försöker överge det helt.
  2. Via ett HTTP-gränssnitt där du kan använda både JSON-förfrågningar och Lucene-syntax. Den sista är textmotorn som Elastic använder. I det här alternativet får vi möjligheten att batcha via JSON-förfrågningar över HTTP. Det här är alternativet vi försöker använda.

Tack vare HTTP-gränssnittet kan vi använda bibliotek som tillhandahåller en asynkron implementering av HTTP-klienten. Vi kan dra nytta av Batch och det asynkrona API:t, vilket i slutändan ger hög prestanda, vilket hjälpte mycket under dagarna av en stor kampanj (mer om detta nedan)

Några siffror för jämförelse:

  • Spara användare som fått priser i Postgres i 20 trådar utan grupperingar: 460713 poster på 42 sekunder
  • Elastisk + reaktiv klient för 10 trådar + batch för 1000 element: 596749 poster på 11 sekunder
  • Elastisk + reaktiv klient för 10 trådar + batch för 1000 element: 23801684 rekord på 4 minuter

Nu har vi skrivit en HTTP request manager som bygger JSON som Batch/non-Batch och skickar den via valfri HTTP-klient, oavsett bibliotek. Du kan också välja att skicka förfrågningar synkront eller asynkront.

I vissa integrationer använder vi fortfarande den officiella transportklienten, men det här är bara en fråga om omedelbar refaktorering. I det här fallet används en egen klient, byggd på Spring WebClient, för bearbetning.

Lastoptimering på ett Highload-projekt med ElasticSearch

Stor marknadsföring

En gång om året är projektet värd för en stor kampanj för användare - detta är samma Highload, eftersom vi vid denna tidpunkt arbetar med tiotals miljoner användare samtidigt.

Vanligtvis inträffar toppbelastningar under helgdagar, men denna kampanj är på en helt annan nivå. Förra året, på kampanjdagen, sålde vi 27 580 890 enheter varor. Datan tog mer än en halvtimme att bearbeta, vilket orsakade besvär för användarna. Användare fick priser för deltagande, men det stod klart att processen behövde påskyndas.

I början av 2019 beslutade vi att ElasticSearch behövdes. Under ett helt år organiserade vi bearbetningen av mottagen data i Elastic och dess utdata till mobilapplikationens och webbplatsens API. Som ett resultat, nästa år under marknadsföringen vi bearbetade 15 131 783 inlägg på 6 minuter.

Eftersom vi har många som vill köpa produkten och delta i utlottningen av våra kampanjer är detta en tillfällig åtgärd. Nu skickar vi aktuell information till Elastic, men i framtiden planerar vi att överföra arkiverad information för de senaste månaderna till Postgres som permanent lagring. För att inte täppa igen Elastic index, som också har sina begränsningar.

Slutsats/slutsatser

För tillfället har vi överfört alla tjänster vi ville ha till Elastic och har pausat för nu. Nu bygger vi ett index i Elastic ovanpå den huvudsakliga persistenta lagringen i Postgres, som tar på sig användarbelastningen.

I framtiden planerar vi att överföra tjänster om vi förstår att dataförfrågan blir för mångsidig och söks efter ett obegränsat antal kolumner. Detta är inte längre en uppgift för Postgres.

Om vi ​​behöver fulltextsökning i funktionaliteten eller om vi har många olika sökkriterier så vet vi redan att detta behöver översättas till Elastic.

⌘⌘⌘

Tack för att du läser. Om ditt företag också använder ElasticSearch och har egna implementeringsfall, berätta gärna för oss. Ska bli intressant att veta hur andra gör :)

Källa: will.com

Lägg en kommentar