FAQ oer arsjitektuer en wurk fan VKontakte

De skiednis fan 'e skepping fan VKontakte is op Wikipedia; it waard ferteld troch Pavel sels. It liket derop dat elkenien har al ken. Oer de ynterne, arsjitektuer en struktuer fan 'e side op HighLoad ++ Pavel fertelde my werom yn 2010. In protte servers binne sûnt dy tiid lekt, dus wy sille de ynformaasje bywurkje: wy sille it dissecte, de binnenkant útnimme, it weagje en it VK-apparaat út in technysk eachpunt besjen.

FAQ oer arsjitektuer en wurk fan VKontakte

Alexey Akulovich (AterCattus) backend-ûntwikkelder yn it VKontakte-team. It transkripsje fan dit rapport is in kollektyf antwurd op faak stelde fragen oer de wurking fan it platfoarm, ynfrastruktuer, servers en ynteraksje tusken har, mar net oer ûntwikkeling, nammentlik oer izer. Apart, oer databases en wat VK ynstee hat, oer it sammeljen fan logs en it kontrolearjen fan it hiele projekt as gehiel. Details ûnder de besuniging.



Al mear as fjouwer jier bin ik dwaande mei allerhanne taken dy't te krijen hawwe mei de backend.

  • Uploaden, opslaan, ferwurkjen, fersprieden fan media: fideo, live streaming, audio, foto's, dokuminten.
  • Ynfrastruktuer, platfoarm, ûntwikkeldersmonitoring, logs, regionale caches, CDN, proprietêr RPC-protokol.
  • Yntegraasje mei eksterne tsjinsten: push-notifikaasjes, parsing fan eksterne keppelings, RSS-feed.
  • It helpen fan kollega's mei ferskate fragen, wêrop de antwurden dûke yn ûnbekende koade nedich binne.

Yn dizze tiid hie ik in hân yn in protte komponinten fan 'e side. Ik wol dizze ûnderfining diele.

Algemiene arsjitektuer

Alles, lykas gewoanlik, begjint mei in server as groep servers dy't oanfragen akseptearje.

Front tsjinner

De frontserver akseptearret fersiken fia HTTPS, RTMP en WSS.

HTTPS - dit binne oanfragen foar de haad- en mobile webferzjes fan 'e side: vk.com en m.vk.com, en oare offisjele en net-offisjele kliïnten fan ús API: mobile kliïnten, messengers. Wy hawwe in resepsje RTMP-ferkear foar Live útstjoerings mei aparte front tsjinners en WSS- ferbinings foar Streaming API.

Foar HTTPS en WSS op servers is it wurdich nginx. Foar RTMP-útstjoerings binne wy ​​koartlyn oergien op ús eigen oplossing kive, mar it is bûten it berik fan it rapport. Foar fouttolerânsje advertearje dizze servers mienskiplike IP-adressen en hannelje yn groepen sadat as der in probleem is op ien fan 'e servers, brûkersoanfragen net ferlern gean. Foar HTTPS en WSS fersiferje deselde servers ferkear om in diel fan 'e CPU-lading op harsels te nimmen.

Wy sille net fierder prate oer WSS en RTMP, mar allinich oer standert HTTPS-oanfragen, dy't normaal ferbûn binne mei in webprojekt.

backend

Efter de foarkant binne d'r meastentiids backend-tsjinners. Se ferwurkje oanfragen dy't de frontserver ûntfangt fan kliïnten.

dizze kPHP-tsjinners, wêrop de HTTP-daemon rint, om't HTTPS al ûntsifere is. kPHP is in tsjinner dy't rint op prefork modellen: begjint in masterproses, in bult bernprosessen, jout harke-sockets oan har troch en se ferwurkje har oanfragen. Yn dit gefal wurde prosessen net opnij starte tusken elk fersyk fan 'e brûker, mar gewoan har steat weromsette nei de orizjinele nulwearde steat - fersyk nei fersyk, ynstee fan opnij starte.

Loadferdieling

Al ús backends binne net in enoarme pool fan masines dy't elk fersyk kinne ferwurkje. Wy se ferdield yn aparte groepen: algemien, mobyl, api, fideo, staging ... It probleem op in aparte groep masines sil gjin ynfloed op alle oaren. Yn gefal fan problemen mei fideo sil de brûker dy't nei muzyk harket net iens witte oer de problemen. Hokker backend om it fersyk te stjoeren wurdt besletten troch nginx op 'e foarkant neffens de konfiguraasje.

Metryske kolleksje en rebalancing

Om te begripen hoefolle auto's wy moatte hawwe yn elke groep, wy fertrouwe net op QPS. De backends binne oars, se hawwe ferskillende fersiken, elk fersyk hat in oare kompleksiteit fan berekkenjen QPS. Dêrom wy wy operearje mei it konsept fan load op 'e tsjinner as gehiel - op' e CPU en perf.

Wy hawwe tûzenen fan sokke tsjinners. Elke fysike tsjinner rint in kPHP-groep om alle kearnen te recyclearjen (om't kPHP ien thread is).

Ynhâld Server

CS of Content Server is in opslach. CS is in tsjinner dy't bestannen opslacht en ek uploadde bestannen ferwurket en allerhanne eftergrûnsyngroane taken dy't de haadwebfrontend deroan tawize.

Wy hawwe tsientûzenen fysike servers dy't bestannen opslaan. Brûkers hâlde fan bestannen op te laden, en wy hâlde se op te slaan en te dielen. Guon fan dizze tsjinners wurde sletten troch spesjale pu / pp tsjinners.

pu/pp

As jo ​​iepene it netwurk ljepper yn VK, do seach pu / pp.

FAQ oer arsjitektuer en wurk fan VKontakte

Wat is pu/pp? As wy de iene server nei de oare slute, dan binne d'r twa opsjes foar it uploaden en downloaden fan in bestân nei de server dy't sluten is: direkt через http://cs100500.userapi.com/path of fia tuskenlizzende tsjinner - http://pu.vk.com/c100500/path.

Pu is de histoaryske namme foar foto upload, en pp is foto proxy. Dat is, ien tsjinner is foar it uploaden fan foto's, en in oare is foar it uploaden. No wurde net allinnich foto's laden, mar de namme is bewarre bleaun.

Dizze tsjinners beëinigje HTTPS sesjeste ferwiderjen de prosessor lading út de opslach. Ek, om't brûkersbestannen op dizze servers wurde ferwurke, is de minder gefoelige ynformaasje opslein op dizze masines, hoe better. Bygelyks, HTTPS-fersiferingskaaien.

Om't de masines wurde sletten troch ús oare masines, kinne wy ​​​​leare om har gjin "wite" eksterne IP's te jaan, en jou "griis". Op dizze manier hawwe wy bewarre op it IP-pool en garandearre om de masines te beskermjen fan tagong fan bûten - d'r is gewoan gjin IP om yn te kommen.

Resiliency oer dielde IP's. Wat fouttolerânsje oanbelanget, wurket it skema itselde - ferskate fysike servers hawwe in mienskiplike fysike IP, en de hardware foar har kiest wêr't it fersyk ferstjoerd wurdt. Ik sil letter oer oare opsjes prate.

It kontroversjele punt is dat yn dit gefal de klant hâldt minder ferbiningen. As d'r deselde IP is foar ferskate masines - mei deselde host: pu.vk.com of pp.vk.com, hat de clientbrowser in limyt op it oantal simultane fersiken nei ien host. Mar yn 'e tiid fan ubiquitous HTTP / 2 leau ik dat dit net mear sa relevant is.

It dúdlike neidiel fan it skema is dat it moat pump alle ferkear, dy't nei de opslach giet, fia in oare tsjinner. Sûnt wy pompe ferkear troch masines, kinne wy ​​noch net pompe swier ferkear, Bygelyks, video, mei help fan itselde skema. Wy stjoere it direkt oer - in aparte direkte ferbining foar aparte opslach spesifyk foar fideo. Wy stjoere lichtere ynhâld troch in proxy.

Net lang lyn krigen wy in ferbettere ferzje fan proxy. No sil ik jo fertelle hoe't se ferskille fan gewoane en wêrom dit nedich is.

Sun

Yn septimber 2017, Oracle, dat earder hie kocht Sun, ûntslein in grut oantal Sun-meiwurkers. Wy kinne sizze dat op dit stuit it bedriuw ophold te bestean. By it kiezen fan in namme foar it nije systeem, besletten ús behearders hulde te bringen oan it ûnthâld fan dit bedriuw en neamden it nije systeem Sun. Under ússels neame wy har gewoan "sonnen".

FAQ oer arsjitektuer en wurk fan VKontakte

pp hie in pear problemen. Ien IP per groep - net effektyf cache. Ferskate fysike tsjinners diele in mienskiplik IP-adres, en der is gjin manier om te kontrolearjen hokker tsjinner it fersyk sil gean nei. Dêrom, as ferskillende brûkers komme foar deselde triem, dan as d'r in cache op dizze servers is, einiget it bestân yn 'e cache fan elke server. Dit is in heul yneffisjint skema, mar neat koe dien wurde.

Dêrtroch - wy kinne net shard ynhâld, om't wy gjin spesifike tsjinner foar dizze groep kinne selektearje - se hawwe in mienskiplike IP. Ek foar guon ynterne redenen hawwe wy it wie net mooglik om sokke tsjinners yn regio's te ynstallearjen. Se stiene allinnich yn Sint-Petersburch.

Mei de sinnen hawwe wy it seleksjesysteem feroare. No hawwe wy anycast routing: dynamyske routing, anycast, self-check daemon. Elke tsjinner hat syn eigen yndividuele IP, mar in mienskiplik subnet. Alles is sa ynsteld dat as ien tsjinner mislearret, it ferkear automatysk ferspraat wurdt oer de oare servers fan deselde groep. No is it mooglik om in spesifike server te selektearjen, gjin oerstallige caching, en betrouberens waard net beynfloede.

Gewicht stipe. No kinne wy ​​​​leare om masines fan ferskillende krêft te ynstallearjen as nedich, en ek, yn gefal fan tydlike problemen, feroarje de gewichten fan 'e wurkjende "sonnen" om de lading op har te ferminderjen, sadat se "rêst" en wer begjinne te wurkjen.

Sharding troch ynhâld id. In grappich ding oer sharding: wy knipje normaal ynhâld sadat ferskate brûkers troch deselde "sinne" nei deselde triem gean, sadat se in mienskiplike cache hawwe.

Wy hawwe koartlyn de applikaasje "Clover" lansearre. Dit is in online kwis yn in live útstjoering, wêrby't de gasthear fragen stelt en brûkers yn realtime antwurdzje, opsjes kieze. De app hat in petear dêr't brûkers kinne petearje. Kin tagelyk ferbine mei de útstjoering mear as 100 tûzen minsken. Se skriuwe allegear berjochten dy't nei alle dielnimmers stjoerd wurde, en in avatar komt tegearre mei it berjocht. As 100 tûzen minsken foar ien avatar yn ien "sinne" komme, dan kin it soms efter in wolk rôlje.

Om bursts fan oanfragen foar deselde triem te wjerstean, is it foar in bepaald type ynhâld dat wy in dom skema ynskeakelje dy't bestannen ferspriedt oer alle beskikbere "sonnen" yn 'e regio.

Sinne fan binnen

Reverse proxy op nginx, cache itsij yn RAM as op snelle Optane / NVMe-skiven. Foarbyld: http://sun4-2.userapi.com/c100500/path - in keppeling nei de "sinne", dy't leit yn 'e fjirde regio, de twadde tsjinner groep. It slút it paadbestân, dat fysyk op server 100500 leit.

cover

Wy foegje noch ien knooppunt ta oan ús arsjitektoanyske skema - de caching-omjouwing.

FAQ oer arsjitektuer en wurk fan VKontakte

Hjirûnder is it layoutdiagram regionale caches, der binne sa'n 20 fan harren. Dit binne de plakken dêr't caches en "sonnen" lizze, dy't ferkear troch harsels kinne cache.

FAQ oer arsjitektuer en wurk fan VKontakte

Dit is caching fan multimedia-ynhâld; gjin brûkersgegevens wurde hjir opslein - gewoan muzyk, fideo, foto's.

Om te bepalen de brûker syn regio, wy wy sammelje BGP netwurk foarheaksels oankundige yn de regio. Yn it gefal fan fallback moatte wy ek de geoip-databank parse as wy de IP net kinne fine troch foarheaksels. Wy bepale de regio troch it IP fan de brûker. Yn 'e koade kinne wy ​​​​sjogge nei ien of mear regio's fan' e brûker - dy punten dêr't hy geografysk it tichtste is.

Hoe wurket it?

Wy telle de populariteit fan bestannen per regio. D'r is in oantal regionale cache wêr't de brûker leit, en in triemidentifikator - wy nimme dit pear en ferheegje de beoardieling mei elke download.

Tagelyk komme demoanen - tsjinsten yn regio's - fan tiid ta tiid nei de API en sizze: "Ik bin sa'n en sa'n cache, jou my in list mei de populêrste bestannen yn myn regio dy't noch net op my binne. ” De API leveret in boskje bestannen sortearre op beoardieling, de daemon downloadt se, bringt se nei de regio's en leveret de bestannen dêrwei. Dit is it fûnemintele ferskil tusken pu/pp en Sun út caches: se jouwe it bestân fuortendaliks troch harsels, sels as dit bestân net yn 'e cache stiet, en de cache downloadt it bestân earst nei himsels, en begjint it dan werom te jaan.

Yn dit gefal krije wy ynhâld tichter by brûkers en it fersprieden fan it netwurk load. Bygelyks, allinich út 'e Moskou-cache fersprieden wy mear as 1 Tbit / s yn' e peakstiden.

Mar d'r binne problemen - cache tsjinners binne gjin rubber. Foar super populêre ynhâld is d'r soms net genôch netwurk foar in aparte server. Us cache-tsjinners binne 40-50 Gbit / s, mar d'r is ynhâld dy't sa'n kanaal folslein ferstoppe. Wy geane nei it ymplementearjen fan opslach fan mear dan ien kopy fan populêre bestannen yn 'e regio. Ik hoopje dat wy it ein fan it jier útfiere sille.

Wy hawwe sjoen nei de algemiene arsjitektuer.

  • Front tsjinners dy't akseptearje fersiken.
  • Backends dat proses fersiken.
  • Opslach dy't wurde sletten troch twa soarten proxy's.
  • Regionale caches.

Wat mist yn dit diagram? Fansels, de databases dêr't wy bewarje gegevens.

Databases of motors

Wy neame se gjin databases, mar motoren - Engines, om't wy praktysk gjin databases hawwe yn 'e algemien akseptearre sin.

FAQ oer arsjitektuer en wurk fan VKontakte

Dit is in needsaaklike maatregel. Dit barde om't yn 2008-2009, doe't VK in eksplosive groei yn populariteit hie, it projekt folslein wurke oan MySQL en Memcache en der wiene problemen. MySQL hâldde fan ferûngelokke en korrupte bestannen, wêrnei't it net soe herstelle, en Memcache waard stadichoan degradearre yn prestaasjes en moast opnij starte.

It docht bliken dat it hieltyd populêrder projekt persistente opslach hie, dy't gegevens ferneatiget, en in cache, dy't fertraget. Yn sokke omstannichheden is it dreech om in groeiend projekt te ûntwikkeljen. Der is besletten om te besykjen om de krityske saken dêr't it projekt op rjochte wie wer te skriuwen op ús eigen fytsen.

De oplossing wie suksesfol. Der wie in kâns om dit te dwaan, en ek in uterste needsaak, om't oare manieren fan skaalfergrutting bestienen doe net. D'r wiene net in boskje databases, NoSQL bestie noch net, d'r wiene allinich MySQL, Memcache, PostrgreSQL - en dat is it.

Universele operaasje. De ûntwikkeling waard laat troch ús team fan C-ûntwikkelders en alles waard op in konsekwinte manier dien. Nettsjinsteande de motor, se hiene allegear sawat itselde bestânsformaat op skiif skreaun, deselde startparameters, ferwurke sinjalen op deselde manier, en gedragen sawat itselde yn gefal fan rânesituaasjes en problemen. Mei de groei fan motoren is it handich foar behearders om it systeem te betsjinjen - d'r is gjin bistetún dy't moat wurde ûnderhâlden, en se moatte opnij leare hoe't jo elke nije databank fan tredden kinne operearje, wat it mooglik makke om fluch en maklik fergrutsje harren oantal.

Soarten motors

It team skreau nochal wat motoren. Hjir binne mar guon fan harren: freon, hints, ôfbylding, ipdb, letters, listen, logs, memcached, meowdb, nijs, nostradamus, foto, playlists, pmemcached, sânbak, sykje, opslach, likes, taken, ...

Foar elke taak dy't in spesifike gegevensstruktuer fereasket of atypyske oanfragen ferwurket, skriuwt it C-team in nije motor. Wêrom net.

Wy hawwe in aparte motor memcached, dy't gelyk is oan in gewoane, mar mei in bosk guod, en dy't net fertraget. Net ClickHouse, mar it wurket ek. Beskikber apart pmemcached Is oanhâldende memcached, dat kin ek bewarje gegevens op skiif, boppedat, dan past yn RAM, om net te ferliezen gegevens by it opnij starte. D'r binne ferskate motoren foar yndividuele taken: wachtrijen, listen, sets - alles dat ús projekt fereasket.

Klusters

Fanút in koadeperspektyf is d'r gjin needsaak om te tinken oan motoren of databases as prosessen, entiteiten of ynstânsjes. De koade wurket spesifyk mei klusters, mei groepen fan motoren - ien type per kluster. Litte we sizze dat der in memcached kluster - it is mar in groep masines.

De koade hoecht de fysike lokaasje, grutte of oantal servers hielendal net te witten. Hy giet nei it kluster mei in bepaalde identifier.

Om dit te wurkjen, moatte jo noch ien entiteit tafoegje dy't leit tusken de koade en de motoren - proxy.

RPC proxy

Proxy ferbinende bus, dêr't hast de hiele side op rint. Tagelyk hawwe wy gjin tsjinst ûntdekking - ynstee is d'r in konfiguraasje foar dizze proxy, dy't de lokaasje fan alle klusters en alle shards fan dit kluster wit. Dit is wat admins dogge.

Programmeurs meitsje it hielendal net út hoefolle, wêr en wat it kostet - se geane gewoan nei it kluster. Dit lit ús in protte. By it ûntfangen fan in fersyk omliedt de proxy it fersyk troch, wittende wêr't - it bepaalt dit sels.

FAQ oer arsjitektuer en wurk fan VKontakte

Yn dit gefal is proxy in punt fan beskerming tsjin tsjinstfalen. As guon motor fertraget of crasht, dan begrypt de proxy dit en reagearret dêrmei oan 'e kliïntkant. Hjirmei kinne jo de time-out fuortsmite - de koade wachtet net op 'e motor om te reagearjen, mar begrypt dat it net wurket en op ien of oare manier oars moat gedrage. De koade moat wurde taret op it feit dat de databases net altyd wurkje.

Spesifike ymplemintaasjes

Soms wolle wy noch wol in soarte fan net-standert oplossing as motor hawwe. Tagelyk waard besletten om ús klearmakke rpc-proxy net te brûken, spesifyk makke foar ús motoren, mar in aparte proxy te meitsjen foar de taak.

Foar MySQL, dy't wy hjir en dêr noch hawwe, brûke wy db-proxy, en foar ClickHouse - Kittenhûs.

It wurket oer it algemien sa. D'r is in bepaalde tsjinner, it rint kPHP, Go, Python - yn 't algemien, elke koade dy't ús RPC-protokol brûke kin. De koade rint lokaal op in RPC-proxy - elke tsjinner wêr't de koade leit rint syn eigen lokale proxy. Op oanfraach begrypt de proxy wêr't te gean.

FAQ oer arsjitektuer en wurk fan VKontakte

As de iene motor nei de oare wol, sels as it in buorman is, giet it troch in proxy, om't de buorman yn in oar datasintrum kin. De motor moat net fertrouwe op it witten fan de lokaasje fan wat oars as himsels - dit is ús standert oplossing. Mar der binne fansels útsûnderingen :)

In foarbyld fan in TL-skema dêr't alle motoren wurkje.

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;

Dit is in binêre protokol, wêrfan de tichtste analoog is protobuf. It skema beskriuwt opsjonele fjilden, komplekse typen - útwreidingen fan ynboude skalaren, en queries. Alles wurket neffens dit protokol.

RPC oer TL oer TCP / UDP ... UDP?

Wy hawwe in RPC-protokol foar it útfieren fan motoroanfragen dy't boppe op it TL-skema rint. Dit alles wurket oer in TCP / UDP-ferbining. TCP is begryplik, mar wêrom hawwe wy UDP faak nedich?

UDP helpt foarkomme it probleem fan in grut oantal ferbiningen tusken servers. As elke tsjinner in RPC-proxy hat en, yn 't algemien, it kin nei elke motor gean, dan binne d'r tsientûzenen TCP-ferbiningen per tsjinner. Der is in lading, mar it is nutteloos. Yn it gefal fan UDP bestiet dit probleem net.

Gjin oerstallige TCP-handshake. Dit is in typysk probleem: as in nije motor of in nije server wurdt lansearre, wurde in protte TCP-ferbiningen tagelyk oprjochte. Foar lytse lichtgewicht fersiken, Bygelyks, UDP payload, alle kommunikaasje tusken de koade en de motor is twa UDP-pakketten: de iene fljocht yn de iene rjochting, de twadde yn de oare. Ien rûnreis - en de koade krige in antwurd fan 'e motor sûnder in handshake.

Ja, it wurket allegear gewoan mei in heul lyts persintaazje pakketferlies. It protokol hat stipe foar retransmits en timeouts, mar as wy ferlieze in protte, wy krije hast TCP, dat is net rendabel. Wy ride gjin UDP oer oseanen.

Wy hawwe tûzenen fan sokke tsjinners, en it skema is itselde: in pakket fan motoren wurdt ynstallearre op elke fysike tsjinner. Se binne meast single-threaded om sa fluch mooglik te rinnen sûnder blokkearjen, en wurde ferdield as single-threaded oplossings. Tagelyk hawwe wy neat mear betrouber as dizze motoren, en in soad omtinken wurdt betelle oan persistente gegevens opslach.

Persistente gegevens opslach

Motoren skriuwe binlogs. In binlog is in triem oan 'e ein wêrfan in evenemint foar in feroaring yn steat of gegevens wurdt tafoege. Yn ferskate oplossingen wurdt it oars neamd: binêr log, Wal, AOF, mar it prinsipe is itselde.

Om foar te kommen dat de motor in protte jierren it hiele binlog opnij lêze by it opnij starte, skriuwe de motoren snapshots - aktuele steat. As it nedich is, lêze se der earst út, en meitsje dan it lêzen út 'e binlog ôf. Alle binlogs binne skreaun yn itselde binêre formaat - neffens it TL-skema, sadat admins se gelyk kinne beheare mei har ark. D'r is gjin ferlet fan snapshots. D'r is in algemiene koptekst dy't oanjout waans momintopname int is, magy fan 'e motor, en hokker lichem foar gjinien wichtich is. Dit is in probleem mei de motor dy't de momintopname opnaam.

Ik sil fluch beskriuwe it prinsipe fan operaasje. Der is in tsjinner dêr't de motor rint. Hy iepenet in nije lege binlog foar skriuwen en skriuwt in evenemint foar feroaring oan.

FAQ oer arsjitektuer en wurk fan VKontakte

Op in stuit beslút hy sels in momintopname te meitsjen, of hy krijt in sinjaal. De tsjinner makket in nij bestân, skriuwt syn hiele steat deryn, heakket de hjoeddeistige binloggrutte - offset - ta oan 'e ein fan 'e triem, en skriuwt fierder. In nije binlog wurdt net oanmakke.

FAQ oer arsjitektuer en wurk fan VKontakte

Op in stuit, as de motor opnij starte, sil d'r sawol in binlog as in momintopname op 'e skiif wêze. De motor lêst de hiele momintopname en ferheget syn steat op in bepaald punt.

FAQ oer arsjitektuer en wurk fan VKontakte

Lês de posysje dy't wie op it momint dat de momintopname waard makke en de grutte fan 'e binlog.

FAQ oer arsjitektuer en wurk fan VKontakte

Lês it ein fan 'e binlog om de hjoeddeistige steat te krijen en bliuwt fierdere eveneminten skriuwen. Dit is in ienfâldich skema; ​​al ús motoren wurkje neffens it.

Data replikaasje

As gefolch, gegevens replikaasje yn ús statement-basearre - wy skriuwe yn 'e binlog gjin side feroarings, mar nammentlik feroarje fersiken. Hiel gelyk oan wat komt oer it netwurk, mar in bytsje oanpast.

Itselde skema wurdt brûkt net allinnich foar replikaasje, mar ek om backups te meitsjen. Wy hawwe in motor - in skriuwmaster dy't skriuwt nei de binlog. Op elk oar plak dêr't de admins it ynstelle, wurdt dizze binlog kopiearre, en dat is it - wy hawwe in reservekopy.

FAQ oer arsjitektuer en wurk fan VKontakte

As it nedich is lêzen replikaOm de CPU-lêslading te ferminderjen, wurdt de lêsmotor gewoan lansearre, dy't it ein fan 'e binlog lêst en dizze kommando's lokaal útfiert.

De efterstân hjir is hiel lyts, en it is mooglik om út te finen hoefolle de replika leit efter de master.

Data shading yn RPC proxy

Hoe wurket shading? Hoe begrypt de proxy nei hokker kluster-shard te stjoeren? De koade seit net: "Stjoer foar 15 shards!" - nee, dit wurdt dien troch de proxy.

De ienfâldichste skema is firstint - it earste nûmer yn it fersyk.

get(photo100_500) => 100 % N.

Dit is in foarbyld foar in ienfâldich memcached tekstprotokol, mar, fansels, fragen kinne kompleks en strukturearre wêze. It foarbyld nimt it earste nûmer yn 'e query en de rest as dield troch de klustergrutte.

Dit is handich as wy gegevenslokaasje fan ien entiteit wolle hawwe. Litte wy sizze dat 100 in brûker of groep ID is, en wy wolle dat alle gegevens fan ien entiteit op ien shard stean foar komplekse fragen.

As it ús net skele hoe't oanfragen ferspraat wurde oer it kluster, is d'r in oare opsje - hashing de hiele shard.

hash(photo100_500) => 3539886280 % N

Wy krije ek de hash, de rest fan 'e divyzje en it shardnûmer.

Beide fan dizze opsjes wurkje allinnich as wy binne taret op it feit dat as wy fergrutsje de grutte fan it kluster, wy sille split it of fergrutsje it mei in meardere kearen. Bygelyks, wy hiene 16 shards, wy hawwe net genôch, wy wolle mear - wy kinne feilich krije 32 sûnder downtime. As wy wolle fergrutsje net multiples, der sil wêze downtime, omdat wy sille net by steat wêze om sekuer splitst alles sûnder ferliezen. Dizze opsjes binne nuttich, mar net altyd.

As wy in willekeurige oantal tsjinners tafoegje of fuortsmite moatte, brûke wy Konsekwint hashing op 'e ring a la Ketama. Mar tagelyk ferlieze wy de lokaasje fan 'e gegevens folslein; wy moatte it fersyk fusearje nei it kluster sadat elk stik syn eigen lytse antwurd werombringt, en dan de antwurden fusearje nei de proxy.

D'r binne superspesifike oanfragen. It sjocht der sa út: RPC-proxy ûntfangt it fersyk, bepaalt nei hokker kluster te gean en bepaalt de shard. Dan binne d'r of skriuwmasters, of, as it kluster replika-stipe hat, stjoert it op oanfraach nei in replika. De proxy docht dit alles.

FAQ oer arsjitektuer en wurk fan VKontakte

Logs

Wy skriuwe logs op ferskate manieren. De meast foar de hân lizzende en ienfâldige is skriuw logs nei memcache.

ring-buffer: prefix.idx = line

D'r is in kaai foarheaksel - de namme fan it log, in rigel, en d'r is de grutte fan dit log - it oantal rigels. Wy nimme in willekeurich getal fan 0 nei it oantal rigels minus 1. De kaai yn memcache is in foarheaksel ferbûn mei dit willekeurige getal. Wy bewarje de logline en de aktuele tiid nei de wearde.

As it nedich is om logs te lêzen, fiere wy út Multi Get alle kaaien, sortearre troch tiid, en sa krije in produksje log yn real time. It skema wurdt brûkt as jo wat yn 'e produksje yn echte tiid moatte debuggen, sûnder wat te brekken, sûnder stopjen of ferkear nei oare masines te stopjen, mar dit log duorret net lang.

Foar betroubere opslach fan logs hawwe wy in motor logs-motor. Dit is krekt wêrom it waard makke en wurdt in protte brûkt yn in grut oantal klusters. It grutste kluster dat ik wit fan winkels 600 TB fan ynpakt logs.

De motor is tige âld, der binne klusters dy't al 6-7 jier âld binne. D'r binne problemen mei it dy't wy besykje op te lossen, bygelyks begon wy ClickHouse aktyf te brûken om logs op te slaan.

It sammeljen fan logs yn ClickHouse

Dit diagram lit sjen hoe't wy yn ús motoren rinne.

FAQ oer arsjitektuer en wurk fan VKontakte

Der is koade dy't giet lokaal fia RPC nei de RPC-proxy, en it begrypt wêr't te gean nei de motor. As wy logs yn ClickHouse wolle skriuwe, moatte wy twa dielen yn dit skema feroarje:

  • ferfange wat motor mei ClickHouse;
  • ferfange de RPC proxy, dy't gjin tagong ta ClickHouse, mei wat oplossing dat kin, en fia RPC.

De motor is ienfâldich - wy ferfange it mei in server as in kluster fan servers mei ClickHouse.

En om nei ClickHouse te gean, diene wy Kittenhûs. As wy direkt fan KittenHouse nei ClickHouse gean, sil it net omgean. Sels sûnder oanfragen foeget it ta fan HTTP-ferbiningen fan in enoarm oantal masines. Foar it skema om te wurkjen, op in server mei ClickHouse lokale reverse proxy wurdt ferhege, dy't op sa'n manier skreaun is dat it de fereaske folumes fan ferbiningen ferneare kin. It kin ek gegevens yn himsels relatyf betrouber bufferje.

FAQ oer arsjitektuer en wurk fan VKontakte

Soms wolle wy it RPC-skema net ymplementearje yn net-standert oplossingen, bygelyks yn nginx. Dêrom hat KittenHouse de mooglikheid om logs te ûntfangen fia UDP.

FAQ oer arsjitektuer en wurk fan VKontakte

As de stjoerder en ûntfanger fan 'e logs op deselde masine wurkje, dan is de kâns op it ferliezen fan in UDP-pakket binnen de lokale host frij leech. As kompromis tusken de needsaak om RPC te ymplementearjen yn in oplossing fan tredden en betrouberens, brûke wy gewoan UDP-ferstjoeren. Wy komme letter werom op dit skema.

Monitoring

Wy hawwe twa soarten logs: dy sammele troch behearders op har servers en dy skreaun troch ûntwikkelders út koade. Se oerienkomme mei twa soarten metriken: systeem en produkt.

Systeem metrics

It wurket op al ús servers netdata, dy't statistiken sammelt en stjoert nei Graphite Carbon. Dêrom wurdt ClickHouse brûkt as opslachsysteem, en net Whisper, bygelyks. As it nedich is, kinne jo direkt lêze fan ClickHouse, of brûke grafana foar metriken, grafiken en rapporten. As ûntwikkelders hawwe wy genôch tagong ta Netdata en Grafana.

Produkt metrics

Foar it gemak hawwe wy in protte dingen skreaun. Bygelyks, d'r is in set fan gewoane funksjes wêrmei jo Counts, UniqueCounts-wearden yn statistyk kinne skriuwe, dy't earne fierder stjoerd wurde.

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

$stats = statlogsStatData($params)

Ferfolgens kinne wy ​​sortearjen en groepearingsfilters brûke en alles dwaan wat wy wolle fan statistyk - grafiken bouwe, Watchdogs konfigurearje.

Wy skriuwe tige in protte metriken it oantal eveneminten is fan 600 miljard oant 1 trillion per dei. Wy wolle se lykwols hâlde op syn minst in pear jierom trends yn metriken te begripen. Alles byinoar bringe is in grut probleem dat wy noch net oplost hawwe. Ik sil jo fertelle hoe't it de lêste jierren wurke hat.

Wy hawwe funksjes dy't dizze metriken skriuwe nei lokale memcacheom it oantal ynstjoerings te ferminderjen. Ien kear yn 'e koarte perioade fan tiid lokaal lansearre stats-daemon sammelet alle records. Dêrnei fusearret de demon de metriken yn twa lagen fan servers logs-samlers, dy't statistiken fan in bosk fan ús masines sammelt, sadat de laach efter har net stjert.

FAQ oer arsjitektuer en wurk fan VKontakte

As it nedich is, kinne wy ​​​​direkt skriuwe oan logs-samlers.

FAQ oer arsjitektuer en wurk fan VKontakte

Mar it skriuwen fan koade direkt nei samlers, bypassing stas-daemom, is in min scalable oplossing omdat it fergruttet de lading op de samler. De oplossing is allinich geskikt as wy om ien of oare reden de memcache stats-daemon net op 'e masine kinne ferheegje, of it ferûngelokke en wy gongen direkt.

Folgjende fusearje logs-samlers statistiken yn meowdb - dit is ús databank, dy't ek metriken kin opslaan.

FAQ oer arsjitektuer en wurk fan VKontakte

Dan kinne wy ​​​​binêre "near-SQL" seleksjes meitsje fan 'e koade.

FAQ oer arsjitektuer en wurk fan VKontakte

Eksperimint

Yn 'e simmer fan 2018 hienen wy in ynterne hackathon, en it idee kaam op om te besykjen it reade diel fan it diagram te ferfangen troch wat dat metriken yn ClickHouse koe opslaan. Wy hawwe logs op ClickHouse - wêrom besykje it net?

FAQ oer arsjitektuer en wurk fan VKontakte

Wy hiene in skema dat logs skreau fia KittenHouse.

FAQ oer arsjitektuer en wurk fan VKontakte

Wy hawwe besletten foegje in oare "* Hûs" ta oan it diagram, dy't krekt de metriken yn 'e opmaak krije sil as ús koade se skriuwt fia UDP. Dan feroaret dit *Hûs se yn ynserts, lykas logs, dy't KittenHouse begrypt. Hy kin dizze logs perfekt leverje oan ClickHouse, dy't se moatte kinne lêze.

FAQ oer arsjitektuer en wurk fan VKontakte

It skema mei memcache, stats-daemon en logs-collectors databank wurdt ferfongen troch dizze.

FAQ oer arsjitektuer en wurk fan VKontakte

It skema mei memcache, stats-daemon en logs-collectors databank wurdt ferfongen troch dizze.

  • D'r is hjir in útstjoering fan koade, dy't lokaal skreaun is yn StatsHouse.
  • StatsHouse skriuwt UDP-metriken, al omboud ta SQL-ynserts, nei KittenHouse yn batches.
  • KittenHouse stjoert se nei ClickHouse.
  • As wy se lêze wolle, lêze wy se dan StatsHouse om te gean - direkt fan ClickHouse mei gewoane SQL.

Is it noch eksperimint, mar wy graach hoe't it docht bliken. As wy de problemen mei it skema oplosse, dan sille wy der miskien hielendal op oerskeakelje. Persoanlik hoopje ik it.

De regeling sparret gjin izer. Minder servers binne nedich, lokale stats-daemons en logs-samlers binne net nedich, mar ClickHouse fereasket in gruttere server dan dy yn it hjoeddeistige skema. Minder servers binne nedich, mar se moatte djoerder en machtiger wêze.

Ynsette

Litte wy earst nei de PHP-ynset sjen. Wy ûntwikkelje yn gean: brûke GitLab и TeamCity foar ynset. Untwikkelingstûken wurde gearfoege yn 'e mastertûke, fan' e master foar testen wurde se gearfoege yn staging, en fan staging yn produksje.

Foar ynset wurde de hjoeddeistige produksjetak en de foarige nommen, en diff-bestannen wurde dêryn beskôge - feroarings: oanmakke, wiske, feroare. Dizze wiziging wurdt opnommen yn 'e binlog fan in spesjale copyfast-motor, dy't wizigingen fluch kin replikearje nei ús heule serverfloat. Wat hjir brûkt wurdt is net direkt kopiearjen, mar gossip replikaasje, as ien tsjinner feroarings stjoert nei syn neiste buorlju, dy nei har buorlju, ensfh. Hjirmei kinne jo de koade yn tsientallen en ienheden fan sekonden bywurkje oer de heule float. As de feroaring de lokale replika berikt, jildt dizze patches op har lokaal triemsysteem. Rollback wurdt ek útfierd neffens itselde skema.

Wy ynsette ek kPHP in protte en it hat ek in eigen ûntwikkeling op gean neffens it diagram hjirboppe. Sûnt dit HTTP-tsjinner binêr, dan kinne wy ​​​​diff net produsearje - de frijlittingsbinêre weaget hûnderten MB. Dêrom is d'r in oare opsje hjir - de ferzje is skreaun nei binlog copyfast. Mei elke bou nimt it ta, en tidens it weromdraaien nimt it ek ta. Ferzje replikearre nei servers. Lokale copyfasts sjogge dat in nije ferzje yn 'e binlog ynfierd is, en troch deselde roddelreplikaasje nimme se de lêste ferzje fan' e binêr foar harsels, sûnder ús mastertsjinner te wurch, mar de lading soarchfâldich oer it netwurk te fersprieden. Wat folget sierlike relaunch foar de nije ferzje.

Foar ús motoren, dy't ek yn essinsje binaries binne, is it skema heul gelyk:

  • git master branch;
  • binary yn .deb;
  • de ferzje is skreaun nei binlog copyfast;
  • replikearre nei servers;
  • de tsjinner lûkt in frisse .dep;
  • dpkg -i;
  • sierlike relaunch nei nije ferzje.

It ferskil is dat ús binêr is ferpakt yn argiven .deb, en by it útpompen se dpkg -i wurde pleatst op it systeem. Wêrom wurdt kPHP ynset as in binêre, en motoren wurde ynset as dpkg? It barde sa. It wurket - net oanreitsje it.

Nuttige links:

Alexey Akulovich is ien fan dyjingen dy't, as ûnderdiel fan it programma Komitee, helpt PHP Ruslân op maaie 17th wurdt it grutste evenemint foar PHP ûntwikkelders yn resinte tiden. Sjoch wat in koele PC wy hawwe, wat sprekkers (twa fan harren ûntwikkelje PHP-kearn!) - liket iets dat jo net kinne misse as jo PHP skriuwe.

Boarne: www.habr.com

Add a comment