Lastoptimalisering på et Highload-prosjekt med ElasticSearch

Hei Habr! Mitt navn er Maxim Vasiliev, jeg jobber som analytiker og prosjektleder hos FINCH. I dag vil jeg fortelle deg hvordan vi ved å bruke ElasticSearch var i stand til å behandle 15 millioner forespørsler på 6 minutter og optimalisere den daglige belastningen på nettstedet til en av våre kunder. Dessverre må vi klare oss uten navn, siden vi har en NDA håper vi at innholdet i artikkelen ikke lider under dette. La oss gå.

Hvordan prosjektet fungerer

På vår backend lager vi tjenester som sikrer funksjonaliteten til våre kunders nettsider og mobilapplikasjoner. Den generelle strukturen kan sees i diagrammet:

Lastoptimalisering på et Highload-prosjekt med ElasticSearch

I prosessen med arbeidet behandler vi et stort antall transaksjoner: kjøp, betalinger, operasjoner med brukersaldo, som vi lagrer mange logger for, samt importerer og eksporterer disse dataene til eksterne systemer.

Det er også omvendte prosesser når vi mottar data fra klienten og overfører dem til brukeren. I tillegg er det fortsatt prosesser for arbeid med betalinger og bonusprogrammer.

Kort bakgrunn

Til å begynne med brukte vi PostgreSQL som eneste datalager. Standardfordelene for en DBMS: tilstedeværelsen av transaksjoner, et utviklet datasamplingsspråk, et bredt spekter av verktøy for integrasjon; kombinert med god ytelse tilfredsstilt våre behov i ganske lang tid.

Vi lagret absolutt all data i Postgres: fra transaksjoner til nyheter. Men antallet brukere vokste, og med det antallet forespørsler.

For forståelse er det årlige antallet økter i 2017 kun på skrivebordssiden 131 millioner. I 2018 - 125 millioner. 2019 igjen 130 millioner. Legg til ytterligere 100-200 millioner fra mobilversjonen av nettstedet og mobilapplikasjonen, og du vil få et stort antall forespørsler.

Med veksten av prosjektet sluttet Postgres å takle belastningen, vi hadde ikke tid - et stort antall forskjellige spørsmål dukket opp, som vi ikke kunne opprette et tilstrekkelig antall indekser for.

Vi innså at det var behov for andre datalagre som ville dekke våre behov og ta belastningen av PostgreSQL. Elasticsearch og MongoDB ble vurdert som mulige alternativer. Sistnevnte tapte på følgende punkter:

  1. Langsom indekseringshastighet ettersom mengden data i indekser vokser. Med Elastic avhenger ikke hastigheten av datamengden.
  2. Ingen fulltekstsøk

Så vi valgte Elastic for oss selv og forberedte oss på overgangen.

Bytt til Elastic

1. Vi startet overgangen fra søketjenesten for salgssted. Vår klient har totalt ca 70 000 salgssteder, og dette krever flere typer søk på siden og i applikasjonen:

  • Tekstsøk etter bynavn
  • Geosøk innenfor en gitt radius fra et tidspunkt. For eksempel hvis brukeren ønsker å se hvilke salgssteder som er nærmest hjemmet hans.
  • Søk etter en gitt firkant – brukeren tegner en firkant på kartet, og alle punktene i denne radiusen vises til ham.
  • Søk med flere filtre. Utsalgssteder skiller seg fra hverandre i sortiment

Apropos organisasjonen, i Postgres har vi en datakilde for både kartet og nyhetene, og i Elastic lager vi Snapshots fra originaldataene. Faktum er at Postgres i utgangspunktet ikke klarte å søke etter alle kriterier. Ikke bare var det mange indekser, de kunne også overlappe hverandre, så Postgres-planleggeren gikk tapt og forsto ikke hvilken indeks som skulle brukes.

2. Neste i rekken var nyhetsseksjonen. Publikasjoner vises på siden hver dag slik at brukeren ikke går seg vill i informasjonsflyten, dataene må sorteres før utstedelse. Dette er hva et søk er for: på siden kan du søke etter tekstmatch, og samtidig koble til ekstra filtre, siden de også er laget gjennom Elastic.

3. Så flyttet vi transaksjonsbehandlingen. Brukere kan kjøpe et bestemt produkt på siden og delta i en premietrekning. Etter slike kjøp behandler vi en stor mengde data, spesielt i helger og ferier. Til sammenligning, hvis antall kjøp på vanlige dager er et sted mellom 1,5-2 millioner, kan tallet på helligdager nå 53 millioner.

Samtidig må dataene behandles på et minimum av tid – brukere liker ikke å vente flere dager på resultater. Det er ingen måte å oppnå slike tidsfrister med Postgres - vi mottok ofte blokkeringer, og mens vi behandlet alle forespørsler, kunne ikke brukere sjekke om de mottok premier eller ikke. Dette er lite hyggelig for bedriften, så vi flyttet behandlingen til Elasticsearch.

periodisitet

Nå er oppdateringer konfigurert hendelsesbasert, i henhold til følgende forhold:

  1. Salgspunkter. Så snart vi mottar data fra en ekstern kilde, starter vi umiddelbart oppdateringen.
  2. Nyheter. Så snart en nyhet er redigert på siden, sendes den automatisk til Elastic.

Her er det igjen verdt å nevne fordelene med Elastic. I Postgres, når du sender en forespørsel, må du vente til den behandler alle postene ærlig. Du kan sende 10 XNUMX poster til Elastic og begynne å jobbe umiddelbart, uten å vente på at postene skal distribueres over alle Shards. Selvfølgelig kan noen Shard eller Replica ikke se dataene med en gang, men alt vil være tilgjengelig veldig snart.

Integreringsmetoder

Det er 2 måter å integrere med Elastic:

  1. Gjennom en innfødt klient over TCP. Den opprinnelige driveren dør gradvis ut: den støttes ikke lenger, den har en veldig upraktisk syntaks. Derfor bruker vi det praktisk talt ikke og prøver å forlate det helt.
  2. Gjennom et HTTP-grensesnitt som kan bruke både JSON-forespørsler og Lucene-syntaks. Den siste er en tekstmotor som bruker Elastic. I denne versjonen får vi muligheten til å batch gjennom JSON-forespørsler over HTTP. Dette er alternativet vi prøver å bruke.

Takket være HTTP-grensesnittet kan vi bruke biblioteker som gir en asynkron implementering av HTTP-klienten. Vi kan dra nytte av Batch og det asynkrone API, som til slutt gir høy ytelse, noe som hjalp mye under dagene med en stor kampanje (mer om dette nedenfor)

Noen tall for sammenligning:

  • Lagrer Postgres bounty-brukere i 20 tråder uten gruppering: 460713 poster på 42 sekunder
  • Elastisk + reaktiv klient for 10 tråder + batch for 1000 elementer: 596749 poster på 11 sekunder
  • Elastisk + reaktiv klient for 10 tråder + batch for 1000 elementer: 23801684 poster på 4 minutter

Nå har vi skrevet en HTTP request manager som bygger JSON som Batch / ikke Batch og sender den gjennom en hvilken som helst HTTP-klient, uavhengig av biblioteket. Du kan også velge å sende forespørsler synkront eller asynkront.

I noen integrasjoner bruker vi fortsatt den offisielle transportklienten, men dette er bare et spørsmål om neste refaktorisering. I dette tilfellet brukes en tilpasset klient bygget på grunnlag av Spring WebClient for behandling.

Lastoptimalisering på et Highload-prosjekt med ElasticSearch

stor forfremmelse

En gang i året arrangerer prosjektet en stor kampanje for brukere - dette er den samme Highload, siden vi på dette tidspunktet jobber med titalls millioner brukere samtidig.

Vanligvis oppstår toppbelastninger i ferier, men denne kampanjen er på et helt annet nivå. I forfjor, på kampanjedagen, solgte vi 27 580 890 varer. Dataene tok mer enn en halvtime å behandle, noe som medførte ulemper for brukerne. Brukerne fikk premier for deltakelse, men det ble klart at prosessen måtte fremskyndes.

I begynnelsen av 2019 bestemte vi oss for at vi trengte ElasticSearch. I et helt år organiserte vi behandlingen av de mottatte dataene i Elastic og utstedelsen av dem i api-en til mobilapplikasjonen og nettstedet. Som et resultat, neste år under kampanjen, behandlet vi 15 131 783 oppføringer på 6 minutter.

Siden vi har mange som ønsker å kjøpe varer og være med på trekning av premier i kampanjer, er dette et midlertidig tiltak. Nå sender vi oppdatert informasjon til Elastic, men i fremtiden planlegger vi å overføre arkivert informasjon for de siste månedene til Postgres som permanent lagring. For ikke å tette den elastiske indeksen, som også har sine begrensninger.

Konklusjon/Konklusjoner

For øyeblikket har vi overført alle tjenestene vi ønsket til Elastic og har stoppet foreløpig. Nå bygger vi en indeks i Elastic på toppen av den vedvarende hovedlagringen i Postgres, som tar på seg brukerbelastningen.

I fremtiden planlegger vi å overføre tjenester hvis vi forstår at dataforespørselen blir for mangfoldig og blir søkt etter et ubegrenset antall kolonner. Dette er ikke lenger en oppgave for Postgres.

Trenger vi fulltekstsøk i funksjonalitet eller om vi har mange forskjellige søkekriterier, så vet vi allerede at dette må oversettes til Elastic.

⌘⌘⌘

Takk for at du leste. Hvis din bedrift også bruker ElasticSearch og har egne implementeringssaker, vennligst informer oss. Blir spennende å vite hvordan andre gjør det :)

Kilde: www.habr.com

Legg til en kommentar