Časté otázky o architektúre a práci VKontakte

História vytvorenia VKontakte je na Wikipédii, povedal to sám Pavel. Zdá sa, že ju už všetci poznajú. O vnútornostiach, architektúre a štruktúre stránky na HighLoad++ Pavel povedal mi to v roku 2010. Odvtedy uniklo veľa serverov, takže informácie aktualizujeme: rozoberieme, vyberieme vnútro, zvážime a pozrieme sa na zariadenie VK z technického hľadiska.

Časté otázky o architektúre a práci VKontakte

Alexej Akulovič (AterCattus) backendový vývojár v tíme VKontakte. Prepis tejto správy je súhrnnou odpoveďou na často kladené otázky o fungovaní platformy, infraštruktúry, serverov a interakcie medzi nimi, ale nie o vývoji, konkrétne o železe. Samostatne o databázach a o tom, čo má VK namiesto toho, o zhromažďovaní protokolov a monitorovaní celého projektu ako celku. Detaily pod strihom.



Už viac ako štyri roky sa venujem všemožným úlohám, ktoré súvisia s backendom.

  • Nahrávanie, ukladanie, spracovanie, distribúcia médií: video, živé vysielanie, zvuk, fotografie, dokumenty.
  • Infraštruktúra, platforma, monitorovanie vývojárov, protokoly, regionálne vyrovnávacie pamäte, CDN, proprietárny protokol RPC.
  • Integrácia s externými službami: push notifikácie, analýza externých odkazov, RSS kanál.
  • Pomáhať kolegom s rôznymi otázkami, ktorých zodpovedanie si vyžaduje ponorenie sa do neznámeho kódu.

Počas tejto doby som mal prsty v mnohých komponentoch stránky. Chcem sa podeliť o túto skúsenosť.

Všeobecná architektúra

Všetko, ako obvykle, začína serverom alebo skupinou serverov, ktoré prijímajú požiadavky.

Predný server

Predný server prijíma požiadavky cez HTTPS, RTMP a WSS.

HTTPS - toto sú požiadavky na hlavnú a mobilnú webovú verziu stránky: vk.com a m.vk.com a ďalších oficiálnych a neoficiálnych klientov nášho API: mobilných klientov, messengerov. Máme recepciu RTMP- návštevnosť pre živé vysielanie so samostatnými prednými servermi a WSS- pripojenia pre Streaming API.

Pre HTTPS a WSS na serveroch sa to oplatí nginx. Pri RTMP vysielaní sme nedávno prešli na vlastné riešenie kive, ale to je nad rámec správy. Kvôli odolnosti voči chybám tieto servery inzerujú spoločné adresy IP a konajú v skupinách, takže ak sa vyskytne problém na jednom zo serverov, požiadavky používateľov sa nestratí. V prípade HTTPS a WSS tieto servery šifrujú prenos, aby prevzali časť zaťaženia CPU na seba.

Nebudeme ďalej hovoriť o WSS a RTMP, ale iba o štandardných HTTPS požiadavkách, ktoré sú zvyčajne spojené s webovým projektom.

backend

Za prednou časťou sú zvyčajne backend servery. Spracúvajú požiadavky, ktoré predný server dostáva od klientov.

To kPHP servery, na ktorom beží HTTP démon, pretože HTTPS je už dešifrované. kPHP je server, ktorý beží na modely predvidlice: spustí hlavný proces, množstvo podradených procesov, odovzdá im počúvacie zásuvky a oni spracujú ich požiadavky. V tomto prípade sa procesy medzi každou požiadavkou od používateľa nereštartujú, ale namiesto reštartu sa ich stav jednoducho resetuje na pôvodný stav s nulovou hodnotou - požiadavka za požiadavkou.

Rozloženie zaťaženia

Všetky naše backendy nie sú veľkým množstvom strojov, ktoré dokážu spracovať akúkoľvek požiadavku. My ich rozdelené do samostatných skupín: všeobecné, mobilné, api, video, staging... Problém na samostatnej skupine počítačov neovplyvní všetky ostatné. V prípade problémov s videom sa používateľ, ktorý počúva hudbu, o problémoch ani nedozvie. Na ktorý backend poslať požiadavku rozhoduje nginx na prednej strane podľa konfigurácie.

Metrické zhromažďovanie a vyvažovanie

Aby sme pochopili, koľko áut musíme mať v každej skupine nespoliehajte sa na QPS. Backendy sú rôzne, majú rôzne požiadavky, každá požiadavka má inú zložitosť výpočtu QPS. Preto my pracujeme s konceptom záťaže na serveri ako celku - na CPU a výkone.

Takýchto serverov máme tisíce. Každý fyzický server prevádzkuje skupinu kPHP na recykláciu všetkých jadier (pretože kPHP je jednovláknový).

Server obsahu

CS alebo Content Server je úložisko. CS je server, ktorý ukladá súbory a tiež spracováva nahrané súbory a všetky druhy synchrónnych úloh na pozadí, ktoré mu prideľuje hlavné webové rozhranie.

Máme desiatky tisíc fyzických serverov, ktoré ukladajú súbory. Používatelia radi nahrávajú súbory a my ich radi ukladáme a zdieľame. Niektoré z týchto serverov sú uzavreté špeciálnymi servermi pu/pp.

pu/pp

Ak ste otvorili kartu siete vo VK, videli ste pu/pp.

Časté otázky o architektúre a práci VKontakte

Čo je pu/pp? Ak zatvárame jeden server za druhým, existujú dve možnosti na nahranie a stiahnutie súboru na server, ktorý bol zatvorený: priamo cez http://cs100500.userapi.com/path alebo cez medziľahlý server - http://pu.vk.com/c100500/path.

Pu je historický názov pre nahrávanie fotografií a pp je proxy pre fotografie. To znamená, že jeden server slúži na nahrávanie fotografií a druhý na nahrávanie. Teraz sa nenačítajú len fotografie, ale zachoval sa aj názov.

Tieto servery ukončiť relácie HTTPSna odstránenie záťaže procesora z úložiska. Keďže používateľské súbory sa spracúvajú na týchto serveroch, čím menej citlivých informácií je na týchto počítačoch uložených, tým lepšie. Napríklad šifrovacie kľúče HTTPS.

Keďže stroje sú uzavreté našimi ďalšími strojmi, môžeme si dovoliť nedávať im „biele“ externé IP adresy a dať "sivý". Týmto spôsobom sme ušetrili na fonde IP a zaručili ochranu strojov pred vonkajším prístupom – jednoducho neexistuje žiadna IP adresa, ktorá by sa do neho dostala.

Odolnosť voči zdieľaným IP adresám. Pokiaľ ide o odolnosť voči chybám, schéma funguje rovnako - niekoľko fyzických serverov má spoločnú fyzickú IP a hardvér pred nimi si vyberá, kam poslať požiadavku. O ďalších možnostiach sa porozprávam neskôr.

Kontroverzným bodom je, že v tomto prípade klient udržiava menej spojení. Ak existuje rovnaká IP pre niekoľko počítačov - s rovnakým hostiteľom: pu.vk.com alebo pp.vk.com, klientsky prehliadač má limit na počet súčasných požiadaviek na jedného hostiteľa. Ale v dobe všadeprítomného HTTP/2 verím, že to už nie je také aktuálne.

Zjavnou nevýhodou schémy je, že musí rozpumpovať všetku dopravu, ktorý ide do úložiska cez iný server. Keďže dopravu pumpujeme cez stroje, nemôžeme zatiaľ pumpovať hustú premávku, napríklad video, pomocou rovnakej schémy. Prenášame ho priamo - samostatné priame pripojenie pre samostatné úložiská špeciálne pre video. Ľahší obsah prenášame cez proxy.

Nie je to tak dávno, čo sme dostali vylepšenú verziu proxy. Teraz vám poviem, ako sa líšia od bežných a prečo je to potrebné.

Slnko

V septembri 2017 spoločnosť Oracle, ktorá predtým kúpila Sun, prepustil obrovské množstvo zamestnancov Sun. Dá sa povedať, že v tomto momente spoločnosť zanikla. Pri výbere názvu nového systému sa naši administrátori rozhodli vzdať hold pamiatke tejto spoločnosti a nový systém pomenovali Sun. Medzi sebou ju jednoducho nazývame „slnká“.

Časté otázky o architektúre a práci VKontakte

pp mal niekoľko problémov. Jedna IP na skupinu - neúčinná vyrovnávacia pamäť. Niekoľko fyzických serverov zdieľa spoločnú IP adresu a neexistuje spôsob, ako kontrolovať, na ktorý server bude požiadavka smerovať. Preto, ak si rôzni používatelia prídu pre rovnaký súbor, potom ak je na týchto serveroch vyrovnávacia pamäť, súbor skončí vo vyrovnávacej pamäti každého servera. Je to veľmi neefektívna schéma, ale nedalo sa nič robiť.

V dôsledku toho - obsah nemôžeme roztrhať, pretože nemôžeme vybrať konkrétny server pre túto skupinu - majú spoločnú IP. Aj z nejakých vnútorných dôvodov máme v regiónoch nebolo možné inštalovať takéto servery. Stáli len v Petrohrade.

So slniečkami sme zmenili systém výberu. Teraz máme anycast smerovanie: dynamické smerovanie, anycast, samokontrolný démon. Každý server má svoju vlastnú IP, ale spoločnú podsieť. Všetko je nakonfigurované tak, že ak jeden server zlyhá, prevádzka sa automaticky rozloží medzi ostatné servery rovnakej skupiny. Teraz je možné vybrať konkrétny server, žiadne nadbytočné ukladanie do vyrovnávacej pamätea spoľahlivosť nebola ovplyvnená.

Podpora hmotnosti. Teraz si môžeme dovoliť inštalovať stroje rôzneho výkonu podľa potreby a tiež v prípade dočasných problémov zmeniť hmotnosti pracovných „sĺnk“ tak, aby sa znížilo ich zaťaženie, aby si „oddýchli“ a začali opäť pracovať.

Zdieľanie podľa ID obsahu. Zábavná vec na shardovaní: obsah zvyčajne striehneme tak, že rôzni používatelia prejdú k rovnakému súboru cez to isté „slnko“, takže majú spoločnú vyrovnávaciu pamäť.

Nedávno sme spustili aplikáciu „Clover“. Toto je online kvíz v živom vysielaní, kde moderátor kladie otázky a používatelia odpovedajú v reálnom čase, pričom si vyberajú možnosti. Aplikácia má chat, kde môžu používatelia chatovať. Môže sa súčasne pripojiť k vysielaniu viac ako 100 tisíc ľudí. Všetci píšu správy, ktoré sa posielajú všetkým účastníkom, a spolu so správou prichádza aj avatar. Ak za jeden avatar príde 100 XNUMX ľudí za jedno „slnko“, môže sa niekedy prevaliť za mrakom.

Aby sme vydržali návaly žiadostí o rovnaký súbor, pri určitom type obsahu zapneme hlúpu schému, ktorá rozšíri súbory medzi všetky dostupné „slnká“ v regióne.

Slnko zvnútra

Reverzný proxy na nginx, vyrovnávacia pamäť buď v RAM alebo na rýchlych diskoch Optane/NVMe. Príklad: http://sun4-2.userapi.com/c100500/path — odkaz na „slnko“, ktoré sa nachádza vo štvrtej oblasti, druhej skupine serverov. Zatvorí súbor cesty, ktorý fyzicky leží na serveri 100500.

Cache

Do našej architektonickej schémy pridávame ešte jeden uzol – prostredie ukladania do vyrovnávacej pamäte.

Časté otázky o architektúre a práci VKontakte

Nižšie je schéma rozloženia regionálne kešky, je ich asi 20. Toto sú miesta, kde sa nachádzajú kešky a „slnká“, ktoré môžu cez seba vyrovnávať návštevnosť.

Časté otázky o architektúre a práci VKontakte

Ide o ukladanie multimediálneho obsahu do vyrovnávacej pamäte, neukladajú sa tu žiadne používateľské dáta – iba hudba, video, fotografie.

Aby sme určili región používateľa, my zbierame predpony siete BGP oznámené v regiónoch. V prípade núdzového nastavenia musíme tiež analyzovať databázu geoip, ak sme nemohli nájsť IP podľa prefixov. Región určujeme podľa IP užívateľa. V kóde sa môžeme pozrieť na jeden alebo viac regiónov používateľa – tie body, ku ktorým má geograficky najbližšie.

Ako to funguje?

Počítame obľúbenosť súborov podľa regiónu. Existuje číslo regionálnej vyrovnávacej pamäte, kde sa používateľ nachádza, a identifikátor súboru – tento pár berieme a pri každom stiahnutí zvyšujeme hodnotenie.

Zároveň démoni - služby v regiónoch - z času na čas prichádzajú do API a hovoria: „Som taký a taký cache, dajte mi zoznam najpopulárnejších súborov v mojom regióne, ktoré ešte nie sú na mne. “ Rozhranie API poskytuje množstvo súborov zoradených podľa hodnotenia, démon ich stiahne, prenesie do oblastí a odtiaľ doručí súbory. Toto je zásadný rozdiel medzi pu/pp a Sun z vyrovnávacej pamäte: súbor okamžite odovzdajú, aj keď tento súbor nie je vo vyrovnávacej pamäti, a vyrovnávacia pamäť si súbor najprv stiahne a potom ho začne vracať.

V tomto prípade dostaneme obsah bližšie k používateľom a rozloženie zaťaženia siete. Napríklad iba z moskovskej vyrovnávacej pamäte distribuujeme viac ako 1 Tbit/s počas špičiek.

Ale sú tu problémy - cache servery nie sú gumené. Pre super populárny obsah niekedy nie je dostatok siete pre samostatný server. Naše vyrovnávacie servery majú rýchlosť 40 – 50 Gbit/s, no existuje obsah, ktorý takýto kanál úplne upcháva. Smerujeme k implementácii ukladania viac ako jednej kópie obľúbených súborov v regióne. Dúfam, že to zrealizujeme do konca roka.

Pozreli sme sa na všeobecnú architektúru.

  • Predné servery, ktoré prijímajú požiadavky.
  • Backendy, ktoré spracúvajú požiadavky.
  • Úložné priestory, ktoré sú uzavreté dvoma typmi proxy.
  • Regionálne kešky.

Čo v tomto diagrame chýba? Samozrejmosťou sú databázy, do ktorých dáta ukladáme.

Databázy alebo motory

Nazývame ich nie databázy, ale motory – Engines, pretože databázy vo všeobecne akceptovanom zmysle prakticky nemáme.

Časté otázky o architektúre a práci VKontakte

Toto je nevyhnutné opatrenie. Stalo sa to preto, lebo v rokoch 2008-2009, keď mal VK prudký nárast popularity, projekt fungoval výlučne na MySQL a Memcache a vyskytli sa problémy. MySQL milovalo pády a poškodzovanie súborov, po ktorých sa už neobnovovalo, a Memcache postupne klesala na výkone a musela sa reštartovať.

Ukázalo sa, že čoraz populárnejší projekt mal trvalé úložisko, ktoré poškodzuje dáta, a vyrovnávaciu pamäť, ktorá spomaľuje. V takýchto podmienkach je ťažké vyvinúť rastúci projekt. Bolo rozhodnuté pokúsiť sa prepísať kritické veci, na ktoré bol projekt zameraný, na našich vlastných bicykloch.

Riešenie bolo úspešné. Bola na to príležitosť, ako aj krajná nevyhnutnosť, pretože iné spôsoby škálovania v tom čase neexistovali. Nebolo veľa databáz, NoSQL ešte neexistoval, existovali len MySQL, Memcache, PostrgreSQL – a to je všetko.

Univerzálna prevádzka. Vývoj viedol náš tím vývojárov v jazyku C a všetko sa robilo konzistentným spôsobom. Bez ohľadu na engine mali všetky približne rovnaký formát súboru zapísaný na disk, rovnaké spúšťacie parametre, spracovávali signály rovnakým spôsobom a správali sa približne rovnako v prípade okrajových situácií a problémov. S rastom motorov je pre administrátorov pohodlné obsluhovať systém - neexistuje žiadna zoologická záhrada, ktorú by bolo potrebné udržiavať a každú novú databázu tretích strán sa musia naučiť ovládať, čo umožnilo rýchlo a pohodlne zvýšiť ich počet.

Typy motorov

Tím napísal pomerne veľa motorov. Tu sú len niektoré z nich: priateľ, rady, obrázok, ipdb, písmená, zoznamy, denníky, memcached, meowdb, správy, nostradamus, fotografia, zoznamy skladieb, pmemcached, pieskovisko, vyhľadávanie, úložisko, páči sa mi, úlohy, …

Pre každú úlohu, ktorá vyžaduje špecifickú dátovú štruktúru alebo spracováva atypické požiadavky, C tím napíše nový engine. Prečo nie.

Máme samostatný motor memcached, ktorá je podobná obyčajnej, no s kopou dobrôt, a ktorá nespomaľuje. Nie ClickHouse, ale tiež funguje. K dispozícii samostatne pmemcached - je perzistentný memcached, ktorý dokáže ukladať dáta aj na disk, navyše sa zmestí do RAM, aby o dáta pri reštarte neprišiel. Pre jednotlivé úlohy existujú rôzne enginy: fronty, zoznamy, sady – všetko, čo náš projekt vyžaduje.

Zhluky

Z hľadiska kódu nie je potrebné považovať motory alebo databázy za procesy, entity alebo inštancie. Kód pracuje špecificky s klastrami, so skupinami motorov - jeden typ na klaster. Povedzme, že existuje klaster memcached – je to len skupina strojov.

Kód vôbec nemusí poznať fyzické umiestnenie, veľkosť alebo počet serverov. Prejde do klastra pomocou určitého identifikátora.

Aby to fungovalo, musíte pridať ešte jednu entitu, ktorá sa nachádza medzi kódom a motormi - zastupovanie.

RPC proxy

Proxy spojovacieho autobusu, na ktorej beží takmer celá stránka. Zároveň máme žiadny objav služby — namiesto toho existuje konfigurácia tohto proxy, ktorá pozná umiestnenie všetkých klastrov a všetkých zlomkov tohto klastra. Toto robia správcovia.

Programátorov vôbec nezaujíma, koľko, kde a čo to stojí - jednoducho idú do klastra. To nám veľa umožňuje. Pri prijatí požiadavky proxy presmeruje požiadavku, pričom vie, kam - to sám určí.

Časté otázky o architektúre a práci VKontakte

V tomto prípade je proxy bodom ochrany pred zlyhaním služby. Ak sa niektorý motor spomalí alebo zrúti, proxy to pochopí a podľa toho zareaguje na stranu klienta. To vám umožní odstrániť časový limit - kód nečaká na reakciu motora, ale chápe, že nefunguje a musí sa správať nejako inak. Kód musí byť pripravený na to, že databázy nie vždy fungujú.

Konkrétne implementácie

Niekedy predsa len naozaj chceme mať nejaké neštandardné riešenie ako motor. Zároveň bolo rozhodnuté nepoužívať náš hotový rpc-proxy, vytvorený špeciálne pre naše motory, ale vytvoriť samostatný proxy pre túto úlohu.

Pre MySQL, ktorý tu a tam stále máme, používame db-proxy a pre ClickHouse - Kittenhouse.

Vo všeobecnosti to funguje takto. Existuje určitý server, na ktorom beží kPHP, Go, Python - vo všeobecnosti akýkoľvek kód, ktorý môže používať náš protokol RPC. Kód beží lokálne na RPC proxy – každý server, na ktorom sa kód nachádza, má svoj vlastný lokálny proxy. Na požiadanie proxy pochopí, kam má ísť.

Časté otázky o architektúre a práci VKontakte

Ak chce jeden engine prejsť k druhému, aj keď je to sused, ide cez proxy, pretože sused môže byť v inom dátovom centre. Motor by sa nemal spoliehať na to, že pozná polohu niečoho iného ako seba samého – to je naše štandardné riešenie. Ale samozrejme su vynimky :)

Príklad schémy TL, podľa ktorej fungujú všetky motory.

memcache.not_found                                = memcache.Value;
memcache.strvalue	value:string flags:int = memcache.Value;
memcache.addOrIncr key:string flags:int delay:int value:long = memcache.Value;

tasks.task
    fields_mask:#
    flags:int
    tag:%(Vector int)
    data:string
    id:fields_mask.0?long
    retries:fields_mask.1?int
    scheduled_time:fields_mask.2?int
    deadline:fields_mask.3?int
    = tasks.Task;
 
tasks.addTask type_name:string queue_id:%(Vector int) task:%tasks.Task = Long;

Toto je binárny protokol, ktorého najbližší analóg je protobuf. Schéma predpisuje voliteľné polia, komplexné typy - rozšírenia vstavaných skalárov a dotazy. Všetko funguje podľa tohto protokolu.

RPC cez TL cez TCP/UDP... UDP?

Máme protokol RPC na vykonávanie požiadaviek motora, ktorý beží nad schémou TL. Toto všetko funguje cez pripojenie TCP/UDP. TCP je pochopiteľné, ale prečo často potrebujeme UDP?

UDP pomáha vyhnúť sa problémom s veľkým počtom spojení medzi servermi. Ak má každý server proxy RPC a vo všeobecnosti môže ísť do akéhokoľvek nástroja, potom existujú desiatky tisíc pripojení TCP na server. Existuje náklad, ale je to zbytočné. V prípade UDP tento problém neexistuje.

Žiadne nadbytočné TCP handshake. Toto je typický problém: pri spustení nového motora alebo nového servera sa vytvorí veľa spojení TCP naraz. V prípade malých odľahčených požiadaviek, napríklad užitočného zaťaženia UDP, je všetka komunikácia medzi kódom a motorom dva UDP pakety: jeden letí jedným smerom, druhý druhým. Jedna spiatočná cesta - a kód dostal odpoveď od motora bez podania ruky.

Áno, všetko to jednoducho funguje s veľmi malým percentom straty paketov. Protokol ma podporu retransmitov a timeoutov, ale ak stratime vela, dostaneme takmer TCP, co nie je rentabilne. Nevozíme UDP cez oceány.

Máme tisíce takýchto serverov a schéma je rovnaká: na každom fyzickom serveri je nainštalovaný balík motorov. Väčšinou sú jednovláknové, aby bežali čo najrýchlejšie bez blokovania, a sú rozdelené ako jednovláknové riešenia. Zároveň nemáme nič spoľahlivejšie ako tieto motory a veľká pozornosť sa venuje trvalému ukladaniu dát.

Trvalé ukladanie dát

Motory píšu binlogy. Binlog je súbor, na konci ktorého je pridaná udalosť pre zmenu stavu alebo údajov. V rôznych riešeniach sa to nazýva inak: binárny log, WAL, AOF, ale princíp je rovnaký.

Aby motor pri opätovnom naštartovaní nečítal celý binlog na dlhé roky, motory zapisujú momentky - aktuálny stav. Ak je to potrebné, najprv z neho prečítajú a potom dokončia čítanie z binlogu. Všetky binlogy sú napísané v rovnakom binárnom formáte - podľa schémy TL, aby ich správcovia mohli spravovať rovnako pomocou svojich nástrojov. O momentky nie je taká núdza. Existuje všeobecná hlavička, ktorá označuje, koho snímka je int, kúzlo enginu a ktoré telo nie je pre nikoho dôležité. Toto je problém s motorom, ktorý zaznamenal snímku.

Rýchlo popíšem princíp fungovania. Existuje server, na ktorom beží motor. Otvorí nový prázdny binlog na zápis a napíše doň udalosť na zmenu.

Časté otázky o architektúre a práci VKontakte

V určitom momente sa buď sám rozhodne urobiť snímku, alebo dostane signál. Server vytvorí nový súbor, zapíše doň celý jeho stav, na koniec súboru pripojí aktuálnu veľkosť binlogu – offset – a pokračuje v písaní ďalej. Nový binlog sa nevytvorí.

Časté otázky o architektúre a práci VKontakte

V určitom okamihu, keď sa motor reštartuje, bude na disku binlog aj snímka. Motor načíta celú snímku a v určitom bode zvýši svoj stav.

Časté otázky o architektúre a práci VKontakte

Číta pozíciu, ktorá bola v čase vytvorenia snímky, a veľkosť binlogu.

Časté otázky o architektúre a práci VKontakte

Prečíta koniec binlogu, aby zistil aktuálny stav a pokračuje v písaní ďalších udalostí. Toto je jednoduchá schéma, podľa ktorej fungujú všetky naše motory.

Replikácia údajov

Výsledkom je replikácia údajov v našom na základe výpisu — do binlogu nepíšeme žiadne zmeny stránky, ale menovite žiadosti o zmenu. Veľmi podobné tomu, čo prichádza cez sieť, len mierne upravené.

Rovnaká schéma sa používa nielen na replikáciu, ale aj na vytváranie záloh. Máme engine – masterwriter, ktorý zapisuje do binlogu. Na akomkoľvek inom mieste, kde to správcovia nastavili, sa tento binlog skopíruje a je to – máme zálohu.

Časté otázky o architektúre a práci VKontakte

V prípade potreby čítacia replikaAby sa znížilo zaťaženie CPU čítaním, jednoducho sa spustí čítacie jadro, ktoré prečíta koniec binlogu a vykoná tieto príkazy lokálne.

Oneskorenie je tu veľmi malé a je možné zistiť, ako veľmi replika zaostáva za predlohou.

Zdieľanie údajov v serveri proxy RPC

Ako funguje sharding? Ako server proxy pochopí, do ktorého klastrového fragmentu sa má odoslať? Kód nehovorí: „Pošlite po 15 úlomkov!“ - Nie, to robí splnomocnenec.

Najjednoduchšia schéma je firstint — prvé číslo v žiadosti.

get(photo100_500) => 100 % N.

Toto je príklad jednoduchého textového protokolu memcached, ale, samozrejme, dotazy môžu byť zložité a štruktúrované. V príklade sa použije prvé číslo v dotaze a zvyšok po vydelení veľkosťou klastra.

To je užitočné, keď chceme mať dátovú lokalitu jednej entity. Povedzme, že 100 je ID používateľa alebo skupiny a chceme, aby všetky údaje jednej entity boli na jednom zlomku pre zložité dotazy.

Ak nám nezáleží na tom, ako sú požiadavky rozložené v klastri, existuje ďalšia možnosť - hašovanie celého fragmentu.

hash(photo100_500) => 3539886280 % N

Získame tiež hash, zvyšok delenia a číslo zlomku.

Obe tieto možnosti fungujú iba vtedy, ak sme pripravení na to, že keď zväčšíme veľkosť klastra, rozdelíme ho alebo zväčšíme niekoľkonásobne. Napríklad, mali sme 16 úlomkov, nemáme dosť, chceme viac - môžeme bezpečne získať 32 bez prestojov. Ak chceme zvýšiť nie násobky, dôjde k výpadkom, pretože nebudeme môcť presne rozdeliť všetko bez strát. Tieto možnosti sú užitočné, ale nie vždy.

Ak potrebujeme pridať alebo odstrániť ľubovoľný počet serverov, používame Dôsledné hašovanie na prsteň a la Ketama. Zároveň však úplne stratíme lokalitu údajov, požiadavku musíme zlúčiť do klastra, aby každý kus vrátil svoju malú odpoveď, a potom zlúčiť odpovede do proxy.

Existujú superšpecifické požiadavky. Vyzerá to takto: Proxy RPC prijme požiadavku, určí, do ktorého klastra ísť, a určí zlomok. Potom existujú buď predlohy zápisu, alebo, ak má klaster podporu repliky, odošle sa na požiadanie do repliky. Toto všetko robí proxy.

Časté otázky o architektúre a práci VKontakte

Denníky

Protokoly zapisujeme niekoľkými spôsobmi. Najzrejmejší a najjednoduchší je zapisovať protokoly do memcache.

ring-buffer: prefix.idx = line

Je tam predpona kľúča – názov logu, riadok a tam je veľkosť tohto logu – počet riadkov. Zoberieme náhodné číslo od 0 do počtu riadkov mínus 1. Kľúč v memcache je predpona spojená s týmto náhodným číslom. Do hodnoty uložíme riadok denníka a aktuálny čas.

Keď je potrebné prečítať protokoly, vykonáme Multi Get všetky kľúče, zoradené podľa času, a tým získať produkčný denník v reálnom čase. Schéma sa používa, keď potrebujete niečo odladiť vo výrobe v reálnom čase, bez toho, aby ste čokoľvek porušili, bez zastavenia alebo povolenia prevádzky na iné stroje, ale tento protokol netrvá dlho.

Pre spoľahlivé skladovanie guľatiny máme motor guľatina-motor. To je presne dôvod, prečo bol vytvorený a je široko používaný v obrovskom množstve klastrov. Najväčší klaster, o ktorom viem, uchováva 600 TB zabalených protokolov.

Motor je veľmi starý, sú tam klastre, ktoré majú už 6-7 rokov. Sú s tým problémy, ktoré sa snažíme riešiť, napríklad ClickHouse sme začali aktívne využívať na ukladanie protokolov.

Zbieranie protokolov v ClickHouse

Tento diagram ukazuje, ako vstupujeme do našich motorov.

Časté otázky o architektúre a práci VKontakte

Existuje kód, ktorý ide lokálne cez RPC do RPC-proxy a ten rozumie, kam má ísť do motora. Ak chceme v ClickHouse zapisovať protokoly, musíme v tejto schéme zmeniť dve časti:

  • vymeňte nejaký motor za ClickHouse;
  • nahraďte RPC proxy, ktorý nemá prístup k ClickHouse, nejakým riešením, ktoré môže, a cez RPC.

Engine je jednoduchý – nahradíme ho serverom alebo klastrom serverov s ClickHouse.

A ísť do ClickHouse, urobili sme KittenHouse. Ak pôjdeme priamo z KittenHouse do ClickHouse, nezvládne to. Aj bez požiadaviek sa sčíta z HTTP pripojení obrovského množstva strojov. Aby schéma fungovala, na serveri s ClickHouse je aktivovaný lokálny reverzný proxy, ktorý je napísaný tak, aby zniesol požadované objemy spojov. Dokáže tiež pomerne spoľahlivo ukladať dáta do seba.

Časté otázky o architektúre a práci VKontakte

Niekedy nechceme implementovať schému RPC v neštandardných riešeniach, napríklad v nginx. Preto má KittenHouse možnosť prijímať protokoly cez UDP.

Časté otázky o architektúre a práci VKontakte

Ak odosielateľ a príjemca protokolov pracujú na rovnakom počítači, potom je pravdepodobnosť straty paketu UDP v rámci lokálneho hostiteľa pomerne nízka. Ako kompromis medzi potrebou implementácie RPC v riešení tretej strany a spoľahlivosťou používame jednoducho odosielanie UDP. K tejto schéme sa vrátime neskôr.

monitorovanie

Máme dva typy protokolov: protokoly zhromaždené administrátormi na ich serveroch a protokoly napísané vývojármi z kódu. Zodpovedajú dvom typom metrík: systém a produkt.

Systémové metriky

Funguje na všetkých našich serveroch netdata, ktorá zbiera štatistiky a odosiela ich na Grafitový uhlík. Preto sa ako úložný systém používa ClickHouse a nie napríklad Whisper. V prípade potreby si môžete priamo prečítať z ClickHouse alebo použiť grafana pre metriky, grafy a prehľady. Ako vývojári máme dostatočný prístup k Netdata a Grafane.

Metriky produktu

Pre pohodlie sme napísali veľa vecí. Existuje napríklad sada bežných funkcií, ktoré vám umožňujú zapisovať Counts, UniqueCounts hodnoty do štatistík, ktoré sa posielajú niekam ďalej.

statlogsCountEvent   ( ‘stat_name’,            $key1, $key2, …)
statlogsUniqueCount ( ‘stat_name’, $uid,    $key1, $key2, …)
statlogsValuetEvent  ( ‘stat_name’, $value, $key1, $key2, …)

$stats = statlogsStatData($params)

Následne môžeme použiť triediace a zoskupovacie filtre a robiť všetko, čo od štatistík chceme – zostavovať grafy, konfigurovať Watchdogs.

Píšeme veľmi veľa metrík počet udalostí je od 600 miliárd do 1 bilióna za deň. Chceme si ich však zachovať aspoň pár rokovpochopiť trendy v metrikách. Dať to všetko dokopy je veľký problém, ktorý sme zatiaľ nevyriešili. Poviem vám, ako to funguje posledných pár rokov.

Máme funkcie, ktoré píšu tieto metriky do miestnej memcacheznížiť počet vstupov. Raz za krátky čas spustený lokálne stats-daemon zbiera všetky záznamy. Potom démon zlúči metriky do dvoch vrstiev serverov zberači guľatiny, ktorý agreguje štatistiky z kopy našich strojov, aby vrstva za nimi neodumrela.

Časté otázky o architektúre a práci VKontakte

V prípade potreby môžeme písať priamo na zberačov guľatiny.

Časté otázky o architektúre a práci VKontakte

Ale zápis z kódu priamo do kolektorov, obídenie stas-daemom, je zle škálovateľné riešenie, pretože zvyšuje zaťaženie kolektora. Riešenie je vhodné iba vtedy, ak z nejakého dôvodu nemôžeme na stroji vyvolať démona memcache stats-daemon, alebo sa zrútil a išli sme priamo.

Ďalej zberatelia protokolov zlúčia štatistiky do mňauDB - toto je naša databáza, v ktorej je možné ukladať aj metriky.

Časté otázky o architektúre a práci VKontakte

Potom môžeme z kódu urobiť binárne výbery „blízko SQL“.

Časté otázky o architektúre a práci VKontakte

Experiment

V lete 2018 sme mali interný hackathon a prišiel nápad skúsiť nahradiť červenú časť diagramu niečím, čo by mohlo ukladať metriky v ClickHouse. Máme logy na ClickHouse - prečo to neskúsiť?

Časté otázky o architektúre a práci VKontakte

Mali sme schému, ktorá zapisovala denníky cez KittenHouse.

Časté otázky o architektúre a práci VKontakte

Rozhodli sme sa pridajte do diagramu ďalší „*Dom“., ktorý dostane presne metriky vo formáte, ako ich náš kód zapisuje cez UDP. Potom ich tento *House premení na vložky, ako polená, čomu KittenHouse rozumie. Tieto protokoly dokáže perfektne doručiť do ClickHouse, ktorý by ich mal vedieť prečítať.

Časté otázky o architektúre a práci VKontakte

Schéma s databázou memcache, stats-daemon a logs-collectors je nahradená touto schémou.

Časté otázky o architektúre a práci VKontakte

Schéma s databázou memcache, stats-daemon a logs-collectors je nahradená touto schémou.

  • Tu je odoslanie z kódu, ktorý je napísaný lokálne v StatsHouse.
  • StatsHouse zapisuje metriky UDP, už skonvertované na vložky SQL, do KittenHouse v dávkach.
  • KittenHouse ich pošle do ClickHouse.
  • Ak ich chceme čítať, potom ich čítame obídením StatsHouse – priamo z ClickHouse pomocou bežného SQL.

Je to ešte stále? experiment, ale páči sa nám, ako to dopadne. Ak vyriešime problémy so schémou, možno na ňu prejdeme úplne. Osobne v to dúfam.

Schéma nešetrí železom. Je potrebných menej serverov, nie sú potrebné miestne štatistické démony a zberače protokolov, ale ClickHouse vyžaduje väčší server, ako sú v súčasnej schéme. Je potrebných menej serverov, ale musia byť drahšie a výkonnejšie.

Nasadiť

Najprv sa pozrime na nasadenie PHP. Vyvíjame sa v ísť: použitie GitLab и TeamCity na nasadenie. Vývojové vetvy sa zlúčia do hlavnej vetvy, z mastera na testovanie sa zlúčia do stagingu a zo stagingu do výroby.

Pred nasadením sa vezme aktuálna produkčná vetva a predchádzajúca a zohľadnia sa v nich diff súbory - zmeny: vytvorené, odstránené, zmenené. Táto zmena je zaznamenaná v binlogu špeciálneho nástroja copyfast, ktorý dokáže rýchlo replikovať zmeny v celej našej serverovej flotile. To, čo sa tu používa, nie je kopírovanie priamo, ale replikácia klebiet, keď jeden server posiela zmeny svojim najbližším susedom, tie svojim susedom atď. To vám umožní aktualizovať kód v desiatkach a jednotkách sekúnd v rámci celej flotily. Keď zmena dosiahne lokálnu repliku, aplikuje tieto záplaty na svoju lokálny súborový systém. Vrátenie späť sa tiež vykonáva podľa rovnakej schémy.

Veľa nasadzujeme aj kPHP a má to na sebe aj vlastný vývoj ísť podľa vyššie uvedeného diagramu. Od tohto Binárny server HTTP, potom nemôžeme vytvoriť diff - binárny súbor vydania váži stovky MB. Preto je tu ďalšia možnosť - verzia je zapísaná binlog copyfast. S každou zostavou sa zvyšuje a počas rollbacku sa tiež zvyšuje. Verzia replikované na servery. Miestni copyfastovia vidia, že do binlogu vstúpila nová verzia, a rovnakou replikáciou klebiet si berú najnovšiu verziu binárneho súboru pre seba, bez toho, aby unavili náš hlavný server, ale opatrne rozložili záťaž po sieti. Čo nasleduje pôvabné opätovné spustenie pre novú verziu.

Pre naše motory, ktoré sú tiež v podstate binárne, je schéma veľmi podobná:

  • git master vetva;
  • binárne v deb;
  • verzia je zapísaná do binlog copyfast;
  • replikované na servery;
  • server vytiahne nový .dep;
  • dpkg -i;
  • elegantné opätovné spustenie na novú verziu.

Rozdiel je v tom, že náš binárny súbor je zabalený v archívoch deb, a pri ich odčerpávaní dpkg -i sú umiestnené v systéme. Prečo je kPHP nasadený ako binárny a motory sú nasadené ako dpkg? Stalo sa to tak. Funguje to - nedotýkajte sa toho.

Užitočné odkazy:

Alexey Akulovich je jedným z tých, ktorí ako súčasť programového výboru pomáhajú PHP Rusko 17. mája sa stane najväčšou udalosťou pre vývojárov PHP za posledné obdobie. Pozrite sa, aký skvelý počítač máme, aký reproduktory (dvaja z nich vyvíjajú jadro PHP!) – zdá sa, že ak píšete PHP, nemôžete minúť.

Zdroj: hab.com

Pridať komentár