Često postavljana pitanja o arhitekturi i radu VKontaktea

Istorija stvaranja VKontaktea nalazi se na Wikipediji; ispričao ju je sam Pavel. Čini se da je svi već poznaju. O unutrašnjosti, arhitekturi i strukturi stranice na HighLoad++ Pavel rekao mi je još 2010. Mnogi serveri su od tada procurili, pa ćemo ažurirati informacije: secirati ćemo ih, izvaditi unutrašnjost, izvagati i pogledati VK uređaj sa tehničke tačke gledišta.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Alexey Akulovich (AterCattus) backend programer u VKontakte timu. Transkript ovog izvještaja je zbirni odgovor na često postavljana pitanja o radu platforme, infrastrukture, servera i interakciji između njih, ali ne io razvoju, tj. o gvožđu. Odvojeno, o bazama podataka i onome što VK ima umjesto toga, o prikupljanju logova i praćenju cijelog projekta u cjelini. Detalji ispod reza.



Više od četiri godine bavim se raznim poslovima vezanim za backend.

  • Učitavanje, pohranjivanje, obrada, distribucija medija: video, live streaming, audio, fotografije, dokumenti.
  • Infrastruktura, platforma, nadzor programera, logovi, regionalni kešovi, CDN, vlasnički RPC protokol.
  • Integracija sa eksternim servisima: push notifikacije, raščlanjivanje eksternih linkova, RSS feed.
  • Pomaganje kolegama u raznim pitanjima, za čije odgovore je potrebno zaroniti u nepoznati kod.

Za to vrijeme imao sam ruku u mnogim komponentama stranice. Želim podijeliti ovo iskustvo.

Opća arhitektura

Sve, kao i obično, počinje sa serverom ili grupom servera koji prihvataju zahteve.

Prednji server

Prednji server prihvata zahtjeve putem HTTPS-a, RTMP-a i WSS-a.

HTTPS - ovo su zahtjevi za glavnu i mobilnu web verziju stranice: vk.com i m.vk.com, te ostale službene i nezvanične klijente našeg API-ja: mobilne klijente, messengere. Imamo prijem RTMP-promet za live prenose sa odvojenim front serverima i WSS- veze za Streaming API.

Za HTTPS i WSS na serverima vrijedi nginx. Za RTMP emitovanje, nedavno smo prešli na vlastito rješenje kive, ali to je van okvira izvještaja. Radi tolerancije grešaka, ovi serveri oglašavaju zajedničke IP adrese i djeluju u grupama, tako da ako dođe do problema na jednom od servera, zahtjevi korisnika se ne izgube. Za HTTPS i WSS, ti isti serveri šifriraju promet kako bi preuzeli dio opterećenja CPU-a na sebe.

Nećemo dalje govoriti o WSS i RTMP-u, već samo o standardnim HTTPS zahtjevima, koji se obično povezuju s web projektom.

backend

Iza fronta se obično nalaze backend serveri. Oni obrađuju zahtjeve koje prednji server prima od klijenata.

ovo kPHP serveri, na kojem je pokrenut HTTP demon, jer je HTTPS već dešifrovan. kPHP je server koji radi na modeli predvilica: pokreće glavni proces, gomilu podređenih procesa, prosljeđuje im slušalice i oni obrađuju njihove zahtjeve. U ovom slučaju, procesi se ne pokreću ponovo između svakog zahtjeva od korisnika, već jednostavno vraćaju svoje stanje u prvobitno stanje nulte vrijednosti - zahtjev za zahtjevom, umjesto ponovnog pokretanja.

Raspodela opterećenja

Svi naši backendovi nisu ogroman skup mašina koje mogu obraditi bilo koji zahtjev. Mi njih podijeljeni u posebne grupe: general, mobile, api, video, staging... Problem na posebnoj grupi mašina neće uticati na sve ostale. U slučaju problema sa videom, korisnik koji sluša muziku neće ni znati za probleme. Na koji backend poslati zahtjev odlučuje nginx na prednjoj strani prema konfiguraciji.

Metrička zbirka i rebalans

Da bismo shvatili koliko automobila trebamo imati u svakoj grupi, mi nemojte se oslanjati na QPS. Backendovi su različiti, imaju različite zahtjeve, svaki zahtjev ima različitu složenost izračunavanja QPS-a. Zato mi poslujemo konceptom opterećenja na serveru u cjelini - na CPU-u i perf.

Imamo hiljade takvih servera. Svaki fizički server pokreće kPHP grupu da reciklira sva jezgra (jer je kPHP jednonitni).

Content Server

CS ili Content Server je skladište. CS je server koji pohranjuje datoteke i također obrađuje otpremljene datoteke i sve vrste pozadinskih sinhronih zadataka koje mu dodijeli glavni web frontend.

Imamo desetine hiljada fizičkih servera koji pohranjuju datoteke. Korisnici vole da postavljaju fajlove, a mi ih volimo pohranjivati ​​i dijeliti. Neki od ovih servera su zatvoreni posebnim pu/pp serverima.

pu/pp

Ako ste otvorili karticu mreže u VK-u, vidjeli ste pu/pp.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Šta je pu/pp? Ako zatvorimo jedan server za drugim, postoje dvije opcije za učitavanje i preuzimanje datoteke na server koji je zatvoren: direktno kroz http://cs100500.userapi.com/path ili preko srednjeg servera - http://pu.vk.com/c100500/path.

Pu je istorijski naziv za otpremanje fotografija, a pp je foto proxy. Odnosno, jedan server je za postavljanje fotografija, a drugi za postavljanje. Sada se ne samo učitavaju fotografije, već je i ime sačuvano.

Ovi serveri prekinuti HTTPS sesijeda uklonite opterećenje procesora iz memorije. Takođe, pošto se korisnički fajlovi obrađuju na ovim serverima, što su manje osetljive informacije uskladištene na ovim mašinama, to bolje. Na primjer, HTTPS ključevi za šifriranje.

Pošto su mašine zatvorene od strane naših drugih mašina, možemo sebi priuštiti da im ne damo „bele“ eksterne IP adrese, i dati "sivo". Na ovaj način smo uštedjeli na IP bazenu i garantirali zaštitu mašina od vanjskog pristupa - jednostavno nema IP-a za ulazak u njega.

Otpornost na dijeljene IP adrese. Što se tiče tolerancije grešaka, shema funkcionira isto - nekoliko fizičkih servera ima zajednički fizički IP, a hardver ispred njih bira gdje će poslati zahtjev. O drugim opcijama ću kasnije.

Kontroverzna stvar je da u ovom slučaju klijent zadržava manje konekcija. Ako postoji isti IP za više mašina - sa istim hostom: pu.vk.com ili pp.vk.com, pretraživač klijenta ima ograničenje na broj istovremenih zahteva prema jednom hostu. Ali u vrijeme sveprisutnog HTTP/2, vjerujem da to više nije toliko relevantno.

Očigledan nedostatak šeme je da mora pumpa sav saobraćaj, koji ide u skladište, preko drugog servera. Pošto pumpamo saobraćaj kroz mašine, još uvek ne možemo pumpati gust saobraćaj, na primer, video, koristeći istu šemu. Mi ga prenosimo direktno - odvojena direktna veza za odvojene skladišta posebno za video. Lakši sadržaj prenosimo preko proxyja.

Nedavno smo dobili poboljšanu verziju proxyja. Sada ću vam reći po čemu se razlikuju od običnih i zašto je to potrebno.

sunce

U septembru 2017. Oracle, koji je prethodno kupio Sun, otpustio ogroman broj zaposlenih u Sunu. Možemo reći da je u ovom trenutku kompanija prestala da postoji. Prilikom odabira imena za novi sistem naši administratori su odlučili da odaju počast sjećanju na ovu kompaniju i novi sistem nazvali Sunce. Među sobom je jednostavno nazivamo „suncima“.

Često postavljana pitanja o arhitekturi i radu VKontaktea

pp je imao nekoliko problema. Jedna IP adresa po grupi - neefikasna keš memorija. Nekoliko fizičkih servera dijeli zajedničku IP adresu i ne postoji način da se kontrolira na koji server će zahtjev ići. Stoga, ako različiti korisnici dođu po istu datoteku, onda ako postoji keš na ovim serverima, datoteka završava u kešu svakog servera. Ovo je vrlo neefikasna šema, ali ništa se nije moglo učiniti.

posljedično - ne možemo dijeliti sadržaj, jer ne možemo odabrati određeni server za ovu grupu - oni imaju zajednički IP. Također iz nekih unutrašnjih razloga imamo nije bilo moguće instalirati takve servere u regionima. Stajali su samo u Sankt Peterburgu.

Sa suncem smo promenili sistem selekcije. Sada imamo anycast rutiranje: dinamičko rutiranje, anycast, demon samoprovjere. Svaki server ima svoju individualnu IP adresu, ali zajedničku podmrežu. Sve je konfigurisano na način da ako jedan server otkaže, saobraćaj se automatski širi na druge servere iste grupe. Sada je moguće odabrati određeni server, nema suvišnog keširanja, a na pouzdanost to nije utjecalo.

Podrška težine. Sada možemo priuštiti da po potrebi ugrađujemo mašine različite snage, a takođe, u slučaju privremenih problema, mijenjamo težine radnih „sunčanika“ kako bismo smanjili opterećenje na njih, kako bi se „odmarali“ i ponovo počeli s radom.

Dijeljenje prema ID-u sadržaja. Smiješna stvar u vezi s dijeljenjem: obično dijelimo sadržaj tako da različiti korisnici idu na istu datoteku kroz isto "sunce" tako da imaju zajedničku keš memoriju.

Nedavno smo pokrenuli aplikaciju “Clover”. Ovo je online kviz u direktnom prenosu, gdje voditelj postavlja pitanja, a korisnici odgovaraju u realnom vremenu, birajući opcije. Aplikacija ima chat u kojem korisnici mogu razgovarati. Može se istovremeno povezati na emitiranje više od 100 hiljada ljudi. Svi pišu poruke koje se šalju svim učesnicima, a uz poruku dolazi i avatar. Ako 100 hiljada ljudi dođe po jedan avatar na jednom „suncu“, onda se ponekad može otkotrljati iza oblaka.

Da bismo izdržali navale zahtjeva za istim fajlom, za određenu vrstu sadržaja uključujemo glupu šemu koja širi fajlove po svim dostupnim „suncima“ u regionu.

Sunce iznutra

Obrnuti proxy na nginx, keš ili u RAM-u ili na brzim Optane/NVMe diskovima. primjer: http://sun4-2.userapi.com/c100500/path — link ka „suncu“, koje se nalazi u četvrtom regionu, drugoj grupi servera. Zatvara datoteku putanje koja se fizički nalazi na serveru 100500.

cache

Našoj arhitektonskoj šemi dodajemo još jedan čvor - okruženje za keširanje.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ispod je dijagram izgleda regionalne keš memorije, ima ih oko 20-ak. To su mjesta na kojima se nalaze kešovi i "sunca" koji mogu sami keširati promet.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ovo je keširanje multimedijalnog sadržaja; ovdje se ne pohranjuju nikakvi korisnički podaci - samo muzika, video, fotografije.

Da bismo odredili regiju korisnika, mi prikupljamo BGP mrežne prefikse najavljene u regijama. U slučaju zamjene, također moramo analizirati geoip bazu podataka ako ne možemo pronaći IP po prefiksima. Regiju određujemo po IP-u korisnika. U kodu možemo pogledati jednu ili više regija korisnika - onih tačaka kojima je geografski najbliži.

Как это работает?

Brojimo popularnost fajlova po regionima. Postoji broj regionalne keš memorije u kojoj se korisnik nalazi, i identifikator datoteke - uzimamo ovaj par i povećavamo ocjenu sa svakim preuzimanjem.

U isto vrijeme, demoni - servisi u regijama - s vremena na vrijeme dolaze u API i kažu: „Ja sam takav i takav keš, dajte mi listu najpopularnijih datoteka u mom regionu koji još nisu kod mene. ” API isporučuje gomilu fajlova sortiranih po rejtingu, demon ih preuzima, prenosi u regione i isporučuje fajlove odatle. Ovo je fundamentalna razlika između pu/pp i Sun od keša: oni odmah daju datoteku kroz sebe, čak i ako ovaj fajl nije u keš memoriji, a keš prvo preuzima datoteku na sebe, a zatim počinje da je vraća.

U ovom slučaju dobijamo sadržaj bliži korisnicima i širenje mrežnog opterećenja. Na primjer, samo iz moskovske keš memorije distribuiramo više od 1 Tbit/s tokom vršnih sati.

Ali ima problema - keš serveri nisu gumeni. Za super popularan sadržaj, ponekad nema dovoljno mreže za poseban server. Naši keš serveri su 40-50 Gbit/s, ali postoji sadržaj koji potpuno začepljuje takav kanal. Idemo ka implementaciji skladištenja više od jedne kopije popularnih fajlova u regionu. Nadam se da ćemo to realizovati do kraja godine.

Pogledali smo opštu arhitekturu.

  • Prednji serveri koji prihvataju zahteve.
  • Backendovi koji obrađuju zahtjeve.
  • Skladišta koja su zatvorena sa dvije vrste proksija.
  • Regionalne predmemorije.

Šta nedostaje ovom dijagramu? Naravno, baze podataka u koje pohranjujemo podatke.

Baze podataka ili mašine

Nazivamo ih ne bazama podataka, već mašinama - Enginesima, jer baze podataka u opšteprihvaćenom smislu praktično nemamo.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ovo je neophodna mjera. To se dogodilo zato što je 2008-2009, kada je VK imao eksplozivan rast popularnosti, projekat je u potpunosti radio na MySQL-u i Memcache-u i bilo je problema. MySQL je volio rušiti i korumpirati fajlove, nakon čega se nije mogao oporaviti, a Memcache je postepeno degradirao u performansama i morao se ponovo pokrenuti.

Ispostavilo se da je sve popularniji projekat imao trajnu pohranu, koja kvari podatke, i keš memoriju koja usporava. U takvim uslovima teško je razviti projekat koji raste. Odlučeno je da pokušamo prepisati kritične stvari na koje je projekt bio fokusiran na vlastite bicikle.

Rješenje je bilo uspješno. Postojala je prilika da se to učini, ali i krajnja potreba, jer drugi načini skaliranja u to vrijeme nisu postojali. Nije bilo gomile baza podataka, NoSQL još nije postojao, postojali su samo MySQL, Memcache, PostrgreSQL - i to je to.

Univerzalni rad. Razvoj je vodio naš tim C programera i sve je urađeno na dosljedan način. Bez obzira na motor, svi su imali približno isti format datoteke zapisan na disk, iste parametre pokretanja, obrađivali signale na isti način i ponašali se približno isto u slučaju rubnih situacija i problema. Sa rastom motora, administratorima je zgodno da upravljaju sistemom - nema zoološkog vrta koji treba održavati, i moraju ponovo naučiti kako da upravljaju svakom novom bazom podataka treće strane, što je omogućilo brzo i praktično povećanje njihov broj.

Vrste motora

Tim je napisao dosta motora. Evo samo nekih od njih: prijatelj, savjeti, slika, ipdb, slova, liste, zapisi, memcached, meowdb, vijesti, nostradamus, fotografija, playliste, pmemcached, sandbox, pretraga, pohrana, lajkovi, zadaci,…

Za svaki zadatak koji zahtijeva specifičnu strukturu podataka ili obrađuje netipične zahtjeve, C tim piše novi mehanizam. Zašto ne.

Imamo poseban motor memcached, koji je sličan običnom, ali sa gomilom poslastica i koji ne usporava. Nije ClickHouse, ali također radi. Dostupan zasebno pmemcached Je persistent memcached, koji takođe može pohraniti podatke na disk, više nego što stane u RAM, kako ne bi izgubio podatke prilikom ponovnog pokretanja. Postoje različiti motori za pojedinačne zadatke: redovi, liste, setovi - sve što je potrebno našem projektu.

Klasteri

Iz perspektive koda, nema potrebe razmišljati o mašinama ili bazama podataka kao o procesima, entitetima ili instancama. Kod radi posebno sa klasterima, sa grupama motora - jedan tip po klasteru. Recimo da postoji memcached klaster - to je samo grupa mašina.

Kod uopće ne mora znati fizičku lokaciju, veličinu ili broj servera. On ide u klaster koristeći određeni identifikator.

Da bi ovo funkcioniralo, morate dodati još jedan entitet koji se nalazi između koda i motora - proxy.

RPC proxy

Proxy povezujući autobus, na kojoj radi gotovo cijela stranica. U isto vrijeme imamo nema otkrivanja usluge — umjesto toga, postoji konfiguracija za ovaj proxy, koja zna lokaciju svih klastera i svih dijelova ovog klastera. Ovo rade administratori.

Programere uopšte nije briga koliko, gde i šta košta - oni samo idu u klaster. Ovo nam omogućava mnogo. Prilikom prijema zahtjeva, proxy preusmjerava zahtjev, znajući gdje - to sam utvrđuje.

Često postavljana pitanja o arhitekturi i radu VKontaktea

U ovom slučaju, proxy je točka zaštite od neuspjeha usluge. Ako neki motor uspori ili se sruši, onda proxy to razumije i u skladu s tim odgovara na strani klijenta. Ovo vam omogućava da uklonite timeout - kod ne čeka da motor odgovori, već razumije da ne radi i da se mora ponašati nekako drugačije. Kod mora biti pripremljen za činjenicu da baze podataka ne rade uvijek.

Specifične implementacije

Ponekad i dalje zaista želimo imati neko nestandardno rješenje kao motor. Istovremeno, odlučeno je da se ne koristi naš gotov rpc-proxy, kreiran posebno za naše motore, već da se napravi poseban proxy za zadatak.

Za MySQL, koji još uvijek imamo tu i tamo, koristimo db-proxy, a za ClickHouse - Kittenhouse.

Općenito funkcionira ovako. Postoji određeni server, on pokreće kPHP, Go, Python - općenito, bilo koji kod koji može koristiti naš RPC protokol. Kôd se izvodi lokalno na RPC proxy-u - svaki server na kojem se nalazi kod pokreće svoj lokalni proxy. Na zahtjev, punomoćnik razumije gdje treba ići.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ako jedan motor želi ići na drugi, čak i ako je susjed, on ide kroz proxy, jer susjed može biti u drugom podatkovnom centru. Motor se ne bi trebao oslanjati na to da zna lokaciju bilo čega osim sebe - ovo je naše standardno rješenje. Ali naravno ima izuzetaka :)

Primjer TL-šeme prema kojoj svi motori rade.

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;

Ovo je binarni protokol, čiji je najbliži analog protobuf. Šema predopisuje neobavezna polja, složene tipove - ekstenzije ugrađenih skalara i upite. Sve radi po ovom protokolu.

RPC preko TL preko TCP/UDP... UDP?

Imamo RPC protokol za izvršavanje zahtjeva motora koji radi na vrhu TL šeme. Sve ovo radi preko TCP/UDP veze. TCP je razumljiv, ali zašto nam je često potreban UDP?

UDP pomaže izbjeći problem velikog broja veza između servera. Ako svaki server ima RPC proxy i, općenito, može ići na bilo koji motor, tada postoje desetine hiljada TCP veza po serveru. Postoji opterećenje, ali je beskorisno. U slučaju UDP-a ovaj problem ne postoji.

Nema suvišnog TCP rukovanja. Ovo je tipičan problem: kada se pokrene novi motor ili novi server, mnoge TCP veze se uspostavljaju odjednom. Za male lagane zahtjeve, na primjer, UDP nosivost, sva komunikacija između koda i motora je dva UDP paketa: jedan leti u jednom pravcu, drugi u drugom. Jedno povratno putovanje - i kod je dobio odgovor od motora bez rukovanja.

Da, sve radi sa vrlo malim procentom gubitka paketa. Protokol ima podršku za retransmite i tajm-aute, ali ako izgubimo mnogo, dobićemo skoro TCP, što nije isplativo. Ne prenosimo UDP preko okeana.

Imamo hiljade takvih servera, a shema je ista: na svakom fizičkom serveru je instaliran paket motora. Uglavnom su jednonitni kako bi se pokrenuli što je brže moguće bez blokiranja, a podijeljeni su kao jednonitna rješenja. U isto vrijeme, nemamo ništa pouzdanije od ovih motora, a dosta pažnje se poklanja trajnom skladištenju podataka.

Trajno skladištenje podataka

Motori pišu binlogove. Binlog je datoteka na čijem kraju se dodaje događaj za promjenu stanja ili podataka. U različitim rješenjima naziva se drugačije: binarni dnevnik, KIT, AOF, ali princip je isti.

Da bi spriječili da motor ponovo čita cijeli binlog dugi niz godina prilikom ponovnog pokretanja, motori pišu snimci - trenutno stanje. Ako je potrebno, prvo čitaju iz njega, a zatim završavaju čitanje iz binlog-a. Svi binlogovi su napisani u istom binarnom formatu - prema TL šemi, tako da ih administratori mogu jednako administrirati svojim alatima. Ne postoji takva potreba za snimcima. Postoji generalno zaglavlje koje pokazuje čiji je snimak int, magija motora i koje tijelo nikome nije važno. Ovo je problem sa motorom koji je snimio snimak.

Brzo ću opisati princip rada. Postoji server na kojem motor radi. On otvara novi prazan binlog za pisanje i upisuje događaj za promjenu u njega.

Često postavljana pitanja o arhitekturi i radu VKontaktea

U nekom trenutku, on ili odluči sam snimiti snimak, ili dobije signal. Server kreira novu datoteku, upisuje njeno cijelo stanje u nju, dodaje trenutnu veličinu binlog-a - offset - na kraj datoteke i nastavlja dalje pisati. Novi binlog nije kreiran.

Često postavljana pitanja o arhitekturi i radu VKontaktea

U nekom trenutku, kada se motor ponovo pokrene, na disku će biti i binlog i snimak. Motor čita cijeli snimak i podiže svoje stanje u određenom trenutku.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Čita poziciju koja je bila u vrijeme kada je snimak napravljen i veličinu binlog-a.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Čita kraj binlog-a da dobije trenutno stanje i nastavlja pisati dalje događaje. Ovo je jednostavna shema, svi naši motori rade prema njoj.

Replikacija podataka

Kao rezultat toga, replikacija podataka u našoj na osnovu izjava — u binlog upisujemo ne bilo kakve promjene stranice, već naime zahtjevi za promjenu. Vrlo slično onome što dolazi preko mreže, samo malo izmijenjeno.

Ista shema se koristi ne samo za replikaciju, već i za replikaciju za kreiranje rezervnih kopija. Imamo motor - majstor pisanja koji piše u binlog. Na bilo koje drugo mjesto gdje su ga administratori postavili, ovaj binlog se kopira i to je to - imamo rezervnu kopiju.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ako je potrebno čitanje replikeDa bi se smanjilo opterećenje CPU-a čitanjem, jednostavno se pokreće motor čitanja, koji čita kraj binlog-a i izvršava ove komande lokalno.

Zaostajanje je ovdje vrlo malo, a moguće je saznati koliko replika zaostaje za majstorom.

Dijeljenje podataka u RPC proxy

Kako funkcionira sharding? Kako proxy razumije koji dio klastera treba poslati? Kod ne kaže: "Pošalji po 15 komada!" - ne, ovo radi punomoćnik.

Najjednostavnija shema je firstint — prvi broj u zahtjevu.

get(photo100_500) => 100 % N.

Ovo je primjer jednostavnog memcached tekstualnog protokola, ali, naravno, upiti mogu biti složeni i strukturirani. Primjer uzima prvi broj u upitu i ostatak kada se podijeli veličinom klastera.

Ovo je korisno kada želimo da imamo lokalitet podataka jednog entiteta. Recimo da je 100 ID korisnika ili grupe i želimo da svi podaci jednog entiteta budu na jednom dijelu za složene upite.

Ako nas nije briga kako se zahtjevi šire po klasteru, postoji još jedna opcija - heširanje cijelog šarda.

hash(photo100_500) => 3539886280 % N

Dobijamo i hash, ostatak dijeljenja i broj dionice.

Obje ove opcije rade samo ako smo spremni na činjenicu da ćemo ga, kada povećamo veličinu klastera, podijeliti ili povećati višestruko. Na primjer, imali smo 16 komada, nemamo dovoljno, želimo više - možemo sigurno dobiti 32 bez zastoja. Ako želimo da povećamo ne višestruko, doći će do zastoja, jer nećemo moći sve precizno podijeliti bez gubitaka. Ove opcije su korisne, ali ne uvijek.

Ako trebamo dodati ili ukloniti proizvoljan broj servera, koristimo se Konzistentno heširanje na ringu a la Ketama. Ali u isto vrijeme, potpuno gubimo lokalnost podataka; moramo spojiti zahtjev s klasterom tako da svaki dio vraća svoj mali odgovor, a zatim spojiti odgovore na proxy.

Postoje super-specifični zahtjevi. To izgleda ovako: RPC proxy prima zahtjev, određuje na koji klaster ići i određuje šard. Zatim postoje ili masteri pisanja, ili, ako klaster ima podršku za repliku, šalje replici na zahtjev. Proxy radi sve ovo.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Dnevnici

Dnevnike pišemo na nekoliko načina. Najočigledniji i najjednostavniji je pisati dnevnike u memcache.

ring-buffer: prefix.idx = line

Postoji ključni prefiks - naziv dnevnika, linija, a postoji i veličina ovog dnevnika - broj redova. Uzimamo slučajni broj od 0 do broja redova minus 1. Ključ u memcache-u je prefiks povezan sa ovim slučajnim brojem. Pohranjujemo liniju dnevnika i trenutno vrijeme u vrijednost.

Kada je potrebno očitati dnevnike, vršimo Multi Get sve ključeve, poređane po vremenu, i na taj način dobijemo evidenciju proizvodnje u realnom vremenu. Šema se koristi kada treba da otklonite greške u nečemu u produkciji u realnom vremenu, bez prekidanja bilo čega, bez zaustavljanja ili dozvoljavanja saobraćaja drugim mašinama, ali ovaj dnevnik ne traje dugo.

Za pouzdano skladištenje trupaca imamo motor trupci-motor. Upravo zbog toga je stvoren i široko se koristi u velikom broju klastera. Najveći klaster koji znam skladišti 600 TB upakovanih trupaca.

Motor je jako star, ima klastera koji su stari već 6-7 godina. Postoje problemi s tim koje pokušavamo riješiti, na primjer, počeli smo aktivno koristiti ClickHouse za pohranjivanje dnevnika.

Prikupljanje dnevnika u ClickHouseu

Ovaj dijagram pokazuje kako ulazimo u naše motore.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Postoji kod koji ide lokalno preko RPC-a do RPC-proxy-a i razumije gdje da ide do motora. Ako želimo pisati dnevnike u ClickHouse, moramo promijeniti dva dijela u ovoj šemi:

  • zamijenite neki motor sa ClickHouse;
  • zamijenite RPC proxy, koji ne može pristupiti ClickHouse-u, nekim rješenjem koje može i putem RPC-a.

Motor je jednostavan - zamjenjujemo ga serverom ili klasterom servera s ClickHouseom.

I da odemo na ClickHouse, jesmo Kitten House. Ako idemo direktno iz KittenHouse-a u ClickHouse, neće se nositi. Čak i bez zahtjeva, dodaje se iz HTTP konekcija ogromnog broja mašina. Da bi shema radila, na serveru sa ClickHouse lokalni obrnuti proxy je podignut, koji je napisan na način da može izdržati potrebne količine veza. Takođe može relativno pouzdano baferovati podatke unutar sebe.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ponekad ne želimo implementirati RPC šemu u nestandardna rješenja, na primjer, u nginx. Stoga KittenHouse ima mogućnost primanja dnevnika putem UDP-a.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ako pošiljalac i primalac evidencije rade na istoj mašini, onda je verovatnoća gubitka UDP paketa unutar lokalnog hosta prilično niska. Kao kompromis između potrebe za implementacijom RPC-a u rješenju treće strane i pouzdanosti, jednostavno koristimo UDP slanje. Kasnije ćemo se vratiti na ovu šemu.

Monitoring

Imamo dvije vrste dnevnika: one koje prikupljaju administratori na svojim serverima i one koje pišu programeri iz koda. Oni odgovaraju dvije vrste metrike: sistem i proizvod.

Sistemske metrike

Radi na svim našim serverima netdata, koji prikuplja statistiku i šalje je Graphite Carbon. Stoga se ClickHouse koristi kao sistem skladištenja, a ne Whisper, na primjer. Ako je potrebno, možete direktno čitati iz ClickHouse-a ili koristiti grafana za metrike, grafikone i izvještaje. Kao programeri, imamo dovoljno pristupa Netdata i Grafani.

metrika proizvoda

Radi praktičnosti, napisali smo dosta stvari. Na primjer, postoji skup običnih funkcija koje vam omogućavaju da zapišete vrijednosti Counts, UniqueCounts u statistiku, koje se šalju negdje dalje.

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

$stats = statlogsStatData($params)

Nakon toga, možemo koristiti filtere za sortiranje i grupisanje i raditi sve što želimo od statistike - graditi grafikone, konfigurirati Watchdogove.

Pišemo veoma mnogo metrika broj događaja je od 600 milijardi do 1 bilion dnevno. Međutim, želimo da ih zadržimo barem par godinarazumjeti trendove u metrici. Spojiti sve to je veliki problem koji još nismo riješili. Reći ću vam kako je to funkcioniralo posljednjih nekoliko godina.

Imamo funkcije koje pišu ove metrike u lokalni memcacheda smanjite broj unosa. Jednom u kratkom vremenskom periodu lokalno pokrenut stats-daemon prikuplja sve zapise. Zatim demon spaja metriku u dva sloja servera sakupljači trupaca, koji agregira statistiku sa gomile naših mašina tako da sloj iza njih ne umre.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ako je potrebno, možemo pisati direktno sakupljačima dnevnika.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Ali pisanje iz koda direktno u kolektore, zaobilazeći stas-daemom, je loše skalabilno rješenje jer povećava opterećenje kolektora. Rješenje je prikladno samo ako iz nekog razloga ne možemo podići memcache stats-daemon na mašini, ili se srušio i otišli smo direktno.

Zatim, sakupljači dnevnika spajaju statistiku meowDB - ovo je naša baza podataka, koja također može pohraniti metriku.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Tada možemo napraviti binarne “near-SQL” selekcije iz koda.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Eksperiment

U ljeto 2018. imali smo interni hakaton i došla je ideja da pokušamo zamijeniti crveni dio dijagrama nečim što može pohraniti metriku u ClickHouse. Imamo logove na ClickHouse - zašto ne probati?

Često postavljana pitanja o arhitekturi i radu VKontaktea

Imali smo šemu koja je zapisivala dnevnike kroz KittenHouse.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Odlučili smo dodajte još jednu “*Kuću” na dijagram, koji će primiti upravo one metrike u formatu kako ih naš kod zapisuje putem UDP-a. Onda ih ova *House pretvara u umetke, poput trupaca, što KittenHouse razumije. On može savršeno dostaviti ove dnevnike ClickHouse-u, koji bi trebao biti u mogućnosti da ih pročita.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Šema sa bazom podataka memcache, stats-daemon i logs-collectors je zamijenjena ovom.

Često postavljana pitanja o arhitekturi i radu VKontaktea

Šema sa bazom podataka memcache, stats-daemon i logs-collectors je zamijenjena ovom.

  • Ovdje postoji depeša iz koda, koja je napisana lokalno u StatsHouseu.
  • StatsHouse zapisuje UDP metriku, već konvertovanu u SQL umetke, u KittenHouse u serijama.
  • KittenHouse ih šalje u ClickHouse.
  • Ako želimo da ih pročitamo, onda ih čitamo zaobilazeći StatsHouse - direktno iz ClickHouse koristeći običan SQL.

Je li mirno eksperiment, ali nam se sviđa kako ispada. Ako riješimo probleme sa shemom, onda ćemo se možda u potpunosti prebaciti na nju. Lično se nadam.

Shema ne štedi gvožđe. Potrebno je manje servera, lokalni demoni statistike i sakupljači dnevnika nisu potrebni, ali ClickHouse zahtijeva veći server od onih u trenutnoj shemi. Potrebno je manje servera, ali moraju biti skuplji i moćniji.

Razviti

Prvo, pogledajmo PHP implementaciju. Mi se razvijamo u git: upotreba GitLab и TeamCity za raspoređivanje. Razvojne grane se spajaju u master granu, od mastera za testiranje se spajaju u stadijume, a iz faze u proizvodnju.

Prije implementacije, uzimaju se trenutna proizvodna grana i prethodna i u njima se razmatraju različiti fajlovi - promjene: kreirane, izbrisane, promijenjene. Ova promjena se bilježi u binlog posebnog copyfast mehanizma, koji može brzo replicirati promjene na cijelu našu flotu servera. Ovdje se ne koristi direktno kopiranje, već replikacija tračeva, kada jedan server šalje promjene svojim najbližim susjedima, one svojim susjedima, itd. Ovo vam omogućava da ažurirate kod u desetinama i jedinicama sekundi u cijeloj floti. Kada promjena dosegne lokalnu repliku, ona primjenjuje ove zakrpe na njenu lokalni sistem datoteka. Vraćanje se također vrši prema istoj shemi.

Takođe dosta primenjujemo kPHP i on takođe ima sopstveni razvoj git prema dijagramu iznad. Od ovoga HTTP server binarni, onda ne možemo proizvesti diff - binarno izdanje teži stotinama MB. Stoga, ovdje postoji još jedna opcija - verzija je napisana binlog copyfast. Sa svakom gradnjom se povećava, a tokom vraćanja se takođe povećava. Verzija replicirano na servere. Lokalni copyfasti vide da je nova verzija ušla u binlog, i istom replikacijom tračeva uzimaju za sebe najnoviju verziju binarne datoteke, ne umarajući naš glavni server, ali pažljivo šireći opterećenje po mreži. Šta slijedi graciozno ponovno pokretanje za novu verziju.

Za naše motore, koji su također u suštini binarni, shema je vrlo slična:

  • git master grana;
  • binarni in .deb;
  • verzija je napisana na binlog copyfast;
  • replicirano na servere;
  • server izvlači novi .dep;
  • dpkg -i;
  • graciozno ponovno pokretanje na novu verziju.

Razlika je u tome što je naš binarni program upakovan u arhive .deb, a prilikom ispumpavanja dpkg -i se postavljaju na sistem. Zašto je kPHP raspoređen kao binarni, a motori kao dpkg? Tako se desilo. Radi - ne dirajte ga.

Korisni linkovi:

Aleksej Akulovič je jedan od onih koji, kao deo Programskog odbora, pomaže PHP Rusija 17. maja postat će najveći događaj za PHP programere u posljednje vrijeme. Pogledaj kakav kul PC imamo, šta zvučnici (dvojica razvijaju PHP jezgro!) - izgleda kao nešto što ne možete propustiti ako pišete PHP.

izvor: www.habr.com

Dodajte komentar