Optimizarea încărcării pe un proiect Highload cu ElasticSearch

Hei Habr! Numele meu este Maxim Vasiliev, lucrez ca analist și manager de proiect la FINCH. Astăzi aș vrea să vă spun cum, folosind ElasticSearch, am reușit să procesăm 15 milioane de solicitări în 6 minute și să optimizăm încărcările zilnice pe site-ul unuia dintre clienții noștri. Din păcate, va trebui să ne descurcăm fără nume, întrucât avem un NDA, sperăm că conținutul articolului nu va avea de suferit din cauza asta. Să mergem.

Cum funcționează proiectul

Pe backend-ul nostru, creăm servicii care asigură performanța site-urilor web și a aplicației mobile ale clienților noștri. Structura generală poate fi văzută în diagramă:

Optimizarea încărcării pe un proiect Highload cu ElasticSearch

În procesul de lucru, procesăm un număr mare de tranzacții: achiziții, plăți, operațiuni cu soldurile utilizatorilor, pentru care stocăm o mulțime de jurnale, precum și importăm și exportăm aceste date către sisteme externe.

Există și procese inverse atunci când primim date de la client și le transferăm utilizatorului. În plus, există încă procese de lucru cu plăți și programe de bonus.

Scurt context

Inițial, am folosit PostgreSQL ca singur depozit de date. Avantajele sale standard pentru un SGBD: prezența tranzacțiilor, un limbaj dezvoltat de eșantionare a datelor, o gamă largă de instrumente pentru integrare; combinate cu performanțe bune ne-au satisfăcut nevoile pentru o perioadă destul de lungă de timp.

Am stocat absolut toate datele în Postgres: de la tranzacții la știri. Dar numărul utilizatorilor a crescut și, odată cu acesta, și numărul de solicitări.

Pentru înțelegere, numărul anual de sesiuni în 2017 doar pe site-ul desktop este de 131 milioane. În 2018 - 125 milioane. 2019 din nou 130 milioane. Adăugați încă 100-200 milioane din versiunea mobilă a site-ului și aplicația mobilă și dvs. va primi un număr mare de cereri.

Odată cu creșterea proiectului, Postgres a încetat să facă față sarcinii, nu am avut timp - a apărut un număr mare de interogări diverse, pentru care nu am putut crea un număr suficient de indici.

Am înțeles că era nevoie de alte depozite de date care să ne satisfacă nevoile și să scadă de la PostgreSQL. Elasticsearch și MongoDB au fost considerate opțiuni posibile. Acesta din urmă a pierdut pe următoarele puncte:

  1. Viteză lentă de indexare pe măsură ce crește cantitatea de date din indici. Cu Elastic, viteza nu depinde de cantitatea de date.
  2. Fără căutare în text complet

Așa că am ales Elastic pentru noi și ne-am pregătit pentru tranziție.

Trecerea la elastic

1. Am început trecerea de la serviciul de căutare punct de vânzare. Clientul nostru are în total aproximativ 70 de puncte de vânzare, iar acest lucru necesită mai multe tipuri de căutări pe site și în aplicație:

  • Căutare text după numele orașului
  • Căutare geografică într-o rază dată de la un punct. De exemplu, dacă utilizatorul dorește să vadă care puncte de vânzare sunt cele mai apropiate de casa lui.
  • Căutați după un pătrat dat - utilizatorul desenează un pătrat pe hartă și i se arată toate punctele din această rază.
  • Căutați după filtre suplimentare. Punctele de vânzare diferă între ele în sortiment

Dacă vorbim despre organizație, atunci în Postgres avem o sursă de date atât pentru hartă, cât și pentru știri, iar în Elastic Snapshot-urile sunt preluate din datele originale. Cert este că inițial Postgres nu a putut face față căutării după toate criteriile. Nu numai că erau mulți indecși, dar se puteau și suprapune, așa că programatorul Postgres s-a pierdut și nu a înțeles ce index să folosească.

2. Următoarea pe rând a fost secțiunea de știri. Publicațiile apar zilnic pe site pentru ca utilizatorul să nu se piardă în fluxul de informații, datele trebuie sortate înainte de emitere. Pentru asta se folosește căutarea: puteți căuta site-ul după potrivirea textului și, în același timp, puteți conecta filtre suplimentare, deoarece acestea sunt realizate și prin Elastic.

3. Apoi am mutat procesarea tranzacției. Utilizatorii pot cumpăra un anumit produs de pe site și pot participa la o tragere la sorți. După astfel de achiziții, procesăm o cantitate mare de date, în special în weekend și sărbători. Spre comparație, dacă în zilele obișnuite numărul de cumpărături este undeva între 1,5-2 milioane, atunci de sărbători cifra poate ajunge la 53 de milioane.

În același timp, datele trebuie prelucrate în cel mai scurt timp posibil - utilizatorilor nu le place să aștepte rezultatul câteva zile. Nu există nicio modalitate de a atinge astfel de termene prin Postgres - am primit adesea blocări și, în timp ce procesam toate solicitările, utilizatorii nu puteau verifica dacă au primit sau nu premii. Acest lucru nu este foarte plăcut pentru afaceri, așa că am mutat procesarea la Elasticsearch.

periodicitate

Acum actualizările sunt configurate pe bază de evenimente, conform următoarelor condiții:

  1. Puncte de vânzare. De îndată ce primim date de la o sursă externă, începem imediat actualizarea.
  2. Știri. De îndată ce orice știre este editată pe site, aceasta este trimisă automat către Elastic.

Din nou, merită menționat avantajele Elastic. În Postgres, atunci când trimiteți o solicitare, trebuie să așteptați până când procesează sincer toate înregistrările. Puteți trimite 10 de înregistrări către Elastic și puteți începe să lucrați imediat, fără a aștepta ca înregistrările să fie distribuite în toate fragmentele. Desigur, este posibil ca unele fragmente sau replică să nu vadă datele imediat, dar totul va fi disponibil foarte curând.

Metode de integrare

Există 2 moduri de integrare cu Elastic:

  1. Printr-un client nativ peste TCP. Driverul nativ se stinge treptat: nu mai este suportat, are o sintaxă foarte incomodă. Prin urmare, practic nu îl folosim și încercăm să îl abandonăm complet.
  2. Printr-o interfață HTTP care poate folosi atât cererile JSON, cât și sintaxa Lucene. Ultimul este un motor de text care folosește Elastic. În această versiune, obținem capacitatea de a procesa loturi prin solicitări JSON prin HTTP. Aceasta este opțiunea pe care încercăm să o folosim.

Datorită interfeței HTTP, putem folosi biblioteci care oferă o implementare asincronă a clientului HTTP. Putem profita de Batch și de API-ul asincron, care are ca rezultat o performanță ridicată, care a ajutat foarte mult în zilele marii promoții (mai multe despre asta mai jos)

Câteva numere pentru comparație:

  • Salvarea utilizatorilor Bounty Postgres în 20 de fire fără grupare: 460713 înregistrări în 42 de secunde
  • Elastic + client reactiv pentru 10 fire + lot pentru 1000 de elemente: 596749 înregistrări în 11 secunde
  • Elastic + client reactiv pentru 10 fire + lot pentru 1000 de elemente: 23801684 intrări în 4 minute

Acum am scris un manager de cereri HTTP care construiește JSON ca Batch / nu Batch și îl trimite prin orice client HTTP, indiferent de bibliotecă. De asemenea, puteți alege să trimiteți cereri sincron sau asincron.

În unele integrări, folosim în continuare clientul oficial de transport, dar aceasta este doar o chestiune de următoarea refactorizare. În acest caz, pentru procesare este utilizat un client personalizat construit pe baza Spring WebClient.

Optimizarea încărcării pe un proiect Highload cu ElasticSearch

mare promovare

O dată pe an, proiectul găzduiește o mare promovare pentru utilizatori - acesta este același Highload, deoarece în acest moment lucrăm cu zeci de milioane de utilizatori în același timp.

De obicei, vârfurile de încărcare apar în perioada sărbătorilor, dar această promoție este la un cu totul alt nivel. Cu un an înainte, în ziua promoției, am vândut 27 de unități de marfă. Datele au fost prelucrate mai bine de o jumătate de oră, ceea ce a creat neplăceri utilizatorilor. Utilizatorii au primit premii pentru participare, dar a devenit clar că procesul trebuia accelerat.

La începutul anului 2019, am decis că avem nevoie de ElasticSearch. Timp de un an întreg, am organizat procesarea datelor primite în Elastic și emiterea lor în api-ul aplicației mobile și al site-ului. Drept urmare, anul următor în timpul campaniei, am procesat 15 de intrări în 131 minute.

Deoarece avem o mulțime de oameni care doresc să cumpere bunuri și să participe la extragerea premiilor în promoții, aceasta este o măsură temporară. Acum trimitem informații actualizate către Elastic, dar în viitor intenționăm să transferăm informațiile arhivate din ultimele luni către Postgres ca stocare permanentă. Pentru a nu înfunda indicele elastic, care are și limitările sale.

Concluzie/Concluzii

Momentan, am transferat toate serviciile pe care le-am dorit la Elastic și am întrerupt acest lucru pentru moment. Acum construim un index în Elastic pe deasupra stocării persistente principale din Postgres, care preia sarcina utilizatorului.

În viitor, intenționăm să transferăm servicii dacă înțelegem că cererea de date devine prea diversă și este căutată pentru un număr nelimitat de coloane. Aceasta nu mai este o sarcină pentru Postgres.

Dacă avem nevoie de căutare full-text în funcționalitate sau dacă avem o mulțime de criterii de căutare diferite, atunci știm deja că acest lucru trebuie tradus în Elastic.

⌘⌘⌘

Multumesc pentru lectura. Dacă compania dvs. folosește și ElasticSearch și are propriile cazuri de implementare, atunci spuneți-ne. Va fi interesant de știut cum sunt alții 🙂

Sursa: www.habr.com

Adauga un comentariu