Hej, Habr! Jag heter Maxim Vasiliev, och jag arbetar som analytiker och projektledare pÄ FINCH. Idag skulle jag vilja berÀtta hur vi med hjÀlp av ElasticSearch lyckades bearbeta 15 miljoner förfrÄgningar pÄ 6 minuter och optimera de dagliga belastningarna pÄ en av vÄra kunders webbplatser. TyvÀrr fÄr vi klara oss utan namn, eftersom vi har ett NDA, men vi hoppas att innehÄllet i artikeln inte pÄverkas av detta. LÄt oss börja.
Hur projektet Àr uppbyggt
I vÄr backend skapar vi tjÀnster som sÀkerstÀller funktionaliteten pÄ vÄra kunders webbplatser och mobilapplikationer. Den allmÀnna strukturen kan ses i schemat:

Under arbetets gÄng hanterar vi ett stort antal transaktioner: köp, utbetalningar, anvÀndarbalanser, för vilka vi sparar mycket loggar, samt importerar och exporterar dessa data till externa system.
Det finns ocksÄ omvÀnda processer, nÀr vi fÄr data frÄn kunden och överför dem till anvÀndarna. Dessutom finns det processer för att hantera betalningar och bonusprogram.
Kort bakgrund
Ursprungligen anvÀnde vi PostgreSQL som den enda datalagringen. Dess standardfördelar för databashanteringssystem: support för transaktioner, en avancerad datavalssprÄk och ett brett utbud av integrationsverktyg, kombinerat med god prestanda, tillfredsstÀllde vÄra behov under lÄng tid.
Vi lagrade alla data i Postgres: frÄn transaktioner till nyheter. Men antalet anvÀndare vÀxte, och dÀrmed antalet förfrÄgningar.
För att ge en uppfattning, det Ă„rliga antalet sessioner 2017 var endast pĂ„ den stationĂ€ra webbplatsen â 131 miljoner. Under 2018 â 125 miljoner. 2019 igen 130 miljoner. LĂ€gg till ytterligare 100-200 miljoner frĂ„n den mobila versionen av webbplatsen och mobilapplikationen, sĂ„ fĂ„r ni ett enormt antal förfrĂ„gningar.
Med projektets tillvĂ€xt slutade Postgres att klara av belastningen, vi hĂ€ngde inte med â en stor mĂ€ngd olika förfrĂ„gningar dök upp, för vilka vi inte kunde skapa tillrĂ€ckligt mĂ„nga index.
Vi insÄg att vi behövde andra datalagringslösningar som kunde tillgodose vÄra behov och avlasta PostgreSQL. Vi övervÀgde Elasticsearch och MongoDB som möjliga alternativ. Den senare förlorade pÄ följande punkter:
- LÄngsam indexeringshastighet med ökande datavolymer i indexen. Hos Elastic beror hastigheten inte pÄ datamÀngden.
- Ingen fulltextsökning
SÄ vi valde Elastic och förberedde oss för övergÄngen.
ĂvergĂ„ng till Elastic
1. Vi började övergÄngen med söktjÀnsten för försÀljningsstÀllen. VÄr kund har totalt cirka 70 000 försÀljningsstÀllen och det krÀvs flera typer av sökningar pÄ webbplatsen och i appen:
- Textuell sökning efter namn pÄ tÀtorten
- Geosökning inom ett visst radie frÄn en punkt. Till exempel, om anvÀndaren vill se vilka försÀljningsstÀllen som ligger nÀrmast hen.
- Sökning inom ett angivet omrĂ„de â anvĂ€ndaren ritar upp ett omrĂ„de pĂ„ kartan, och alla punkter inom den radien visas.
- Sökning med ytterligare filter. FörsÀljningsstÀllena skiljer sig Ät i sitt sortiment.
Om vi pratar om organisationen, sÄ har vi en datakÀlla i Postgres bÄde för kartan och nyheterna, medan snapshot:ar görs av originaldata i Elastic. PoÀngen Àr att Postgres frÄn början inte klarade av att söka enligt alla kriterier. Det fanns mÄnga index som kunde krocka med varandra, vilket gjorde att Postgres planlÀggare blev förvirrad och inte visste vilket index som skulle anvÀndas.
2. NÀsta steg var nyhetsavsnittet. PÄ webbplatsen publiceras nya artiklar varje dag, och för att anvÀndaren inte ska tappa trÄden i informationsflödet behöver data sorteras innan de presenteras. DÀrför behövs sökningen: pÄ webbplatsen kan man söka efter textmatchning, och dessutom koppla in ytterligare filter, eftersom dessa ocksÄ Àr implementerade genom Elastic.
3. Sedan flyttade vi över behandlingen av transaktioner. AnvÀndare kan köpa specifika produkter pÄ webbplatsen och delta i tÀvlingar. Efter sÄdana köp bearbetar vi en stor mÀngd data, sÀrskilt under helger och högtider. För jÀmförelse, om antalet köp under vanliga dagar ligger runt 1,5-2 miljoner, kan siffran under helger nÄ upp till 53 miljoner.
Data mĂ„ste behandlas pĂ„ minimal tid â anvĂ€ndare tycker inte om att vĂ€nta flera dagar pĂ„ resultatet. Genom Postgres gĂ„r sĂ„dana tider helt enkelt inte att uppnĂ„ â vi fick ofta lĂ„sningar, och medan vi bearbetade alla förfrĂ„gningar kunde anvĂ€ndarna inte kontrollera om de hade vunnit priser eller inte. Det Ă€r inte sĂ€rskilt trevligt för företag, dĂ€rför flyttade vi behandlingen till Elasticsearch.
Frekvens
Nu Àr uppdateringarna instÀllda att ske automatiskt under följande villkor:
- FörsÀljningsstÀllen. SÄ snart vi fÄr data frÄn en extern kÀlla börjar vi direkt en uppdatering.
- Nyheter. SÄ snart en nyhet redigeras pÄ webbplatsen skickas den automatiskt till Elastic.
HÀr bör vi Äterigen nÀmna fördelarna med Elastic. I Postgres mÄste man vÀnta pÄ att alla poster hanteras vid varje förfrÄgan. I Elastic kan man skicka 10 000 poster och börja arbeta med en gÄng, utan att vÀnta pÄ att posterna sprids över alla Shards. Visst kan en viss Shard eller Replica kanske inte se data direkt, men det blir snart tillgÀngligt.
Integrationsmetoder
Det finns 2 sÀtt att integrera med Elastic:
- Via inbyggd klient över TCP. Den inbyggda drivrutinen försvinner gradvis: den fÄr inget stöd lÀngre och har en mycket obekvÀm syntax. DÀrför anvÀnder vi den knappt och försöker helt överge den.
- Via HTTP-grÀnssnittet, dÀr bÄde JSON-förfrÄgningar och Lucene-syntax kan anvÀndas. Det sistnÀmnda Àr en textmotor som anvÀnds av Elastic. I sÄ fall fÄr vi möjlighet till Batch via JSON-förfrÄgningar över HTTP. Det Àr just den hÀr metoden vi försöker anvÀnda.
Tack vare HTTP-grÀnssnittet kan vi anvÀnda bibliotek som erbjuder asynkron implementering av HTTP-klienten. Vi kan dra nytta av Batch och asynkront API, vilket slutligen ger hög prestanda, vilket har varit till stor hjÀlp under dagar med stora kampanjer (mer om detta nedan)
Lite siffror för jÀmförelse:
- Sparande av anvÀndare som fick priser i Postgres med 20 strömmar utan gruppering: 460713 poster pÄ 42 sekunder
- Elastic + reaktiv klient med 10 strömmar + batch pÄ 1000 element: 596749 poster pÄ 11 sekunder
- Elastic + reaktiv klient med 10 strömmar + batch pÄ 1000 element: 23801684 poster pÄ 4 minuter
Nu har vi skrivit en HTTP-förfrÄgningshanterare som bygger JSON, som Batch/inte Batch och skickar via vilken HTTP-klient som helst oavsett bibliotek. Det gÄr ocksÄ att vÀlja att skicka förfrÄgningar synkront eller asynkront.
I vissa integrationer anvÀnder vi fortfarande den officiella transportklienten, men det Àr bara en frÄga om nÀra refaktorisering. För bearbetning anvÀnds en egen klient baserad pÄ Spring WebClient.

Större kampanj
En gĂ„ng om Ă„ret hĂ„lls en stor kampanj för anvĂ€ndare pĂ„ projektet â det Ă€r just den stora belastningen, eftersom vi dĂ„ arbetar med tiotals miljoner anvĂ€ndare samtidigt.
Vanligtvis sker belastningstoppar under helgdagar, men denna kampanj Àr av en helt annan nivÄ. För tvÄ Är sedan sÄlde vi 27 580 890 enheter av varan pÄ kampanjdagen. Data behandlades i mer Àn en halvtimme, vilket orsakade problem för anvÀndarna. AnvÀndarna fick priser för att delta, men det blev tydligt att processen behövde snabba upp.
I början av 2019 beslutade vi att vi behövde ElasticSearch. Under ett helt Är organiserade vi bearbetningen av de mottagna uppgifterna i Elastic och deras utdelning via API:er till mobilapplikationen och webbplatsen. Resultatet blev att vi under nÀsta Är under kampanjen bearbetade 15 131 783 poster pÄ 6 minuter.
Eftersom vi har ett stort antal personer som vill köpa varor och delta i lotterier i kampanjerna, Àr detta en tillfÀllig ÄtgÀrd. Just nu skickar vi aktuell information till Elastic, men vi planerar att i framtiden flytta arkivinformation frÄn tidigare mÄnader till Postgres som en permanent lagringslösning. Detta för att undvika att överbelasta Elastic-indexet, som ocksÄ har sina begrÀnsningar.
Slutsats/Resultat
För nÀrvarande har vi flyttat alla tjÀnster vi ville ha till Elastic och vi har gjort en paus hÀr. Just nu bygger vi en index ovanför huvudlagringslösningen i Postgres, som tar emot anvÀndarbelastningen.
I framtiden planerar vi att flytta tjÀnster om vi mÀrker att databehovet blir alltför mÄngfaldigt och söks över ett obegrÀnsat antal kolumner. Det Àr redan en uppgift som inte lÀmpar sig för Postgres.
Om vi behöver en fulltextsökning i funktionaliteten eller om vi fÄr mÄnga olika sökkriterier vet vi redan att det mÄste överföras till Elastic.
âââ
Tack för att ni lĂ€ste. Om ni ocksĂ„ anvĂ€nder ElasticSearch i ert företag och har egna implementeringsfall, berĂ€tta gĂ€rna. Det skulle vara intressant att veta hur andra gör đ
KĂ€lla: habr.com
