KKK arhitektuuri ja VKontakte töö kohta

VKontakte loomise ajalugu on Wikipedias, seda rääkis Pavel ise. Tundub, et kõik teavad teda juba. Teave saidi sisemiste, arhitektuuri ja struktuuri kohta saidil HighLoad++ Pavel ütles mulle 2010. aastal. Sellest ajast on lekkinud palju servereid, seega uuendame infot: lahkame lahti, võtame sisemused välja, kaalume ja vaatame VK seadet tehnilisest küljest.

KKK arhitektuuri ja VKontakte töö kohta

Aleksei Akulovitš (AterCattus) taustaprogrammi arendaja VKontakte meeskonnas. Selle aruande ärakiri on kollektiivne vastus korduma kippuvatele küsimustele platvormi toimimise, infrastruktuuri, serverite ja nendevahelise suhtluse kohta, kuid mitte arenduse kohta. raua kohta. Eraldi andmebaasidest ja selle asemel, mis VK-l on, logide kogumisest ja kogu projekti jälgimisest tervikuna. Detailid lõike all.



Üle nelja aasta olen tegelenud kõikvõimalike backendiga seotud ülesannetega.

  • Meediumite üleslaadimine, salvestamine, töötlemine, levitamine: video, otseülekanne, heli, fotod, dokumendid.
  • Infrastruktuur, platvorm, arendaja jälgimine, logid, piirkondlikud vahemälud, CDN, patenteeritud RPC-protokoll.
  • Integratsioon välisteenustega: tõukemärguanded, välislingi sõelumine, RSS-voog.
  • Kolleegide abistamine erinevate küsimustega, mille vastused nõuavad tundmatusse koodi sukeldumist.

Selle aja jooksul oli mul palju saidi komponente. Ma tahan seda kogemust jagada.

Üldarhitektuur

Kõik, nagu tavaliselt, algab serverist või serverite rühmast, mis taotlusi vastu võtab.

Esiserver

Esiserver võtab päringuid vastu HTTPS-i, RTMP-i ja WSS-i kaudu.

HTTPS - need on taotlused saidi peamise ja mobiilse veebiversiooni jaoks: vk.com ja m.vk.com ning meie API muude ametlike ja mitteametlike klientide jaoks: mobiilikliendid, sõnumitoojad. Meil on vastuvõtt RTMP-liiklus otseülekannete jaoks eraldi esiserveritega ja WSS- Streaming API ühendused.

Serverite HTTPS-i ja WSS-i jaoks tasub see ära nginx. RTMP-saadete puhul läksime hiljuti üle oma lahendusele kive, kuid see jääb aruande reguleerimisalast välja. Veataluvuse tagamiseks reklaamivad need serverid levinud IP-aadresse ja tegutsevad rühmadena, et kui mõnes serveris on probleem, ei läheks kasutajate päringud kaduma. HTTPS-i ja WSS-i puhul krüpteerivad samad serverid liiklust, et võtta osa protsessori koormusest enda peale.

Me ei räägi pikemalt WSS-ist ja RTMP-st, vaid ainult standardsetest HTTPS-i päringutest, mida tavaliselt seostatakse veebiprojektiga.

Taustaprogramm

Esikülje taga on tavaliselt tagaserverid. Nad töötlevad päringuid, mille esiserver saab klientidelt.

see kPHP serverid, millel HTTP deemon töötab, sest HTTPS on juba dekrüptitud. kPHP on server, mis töötab preforki mudelid: käivitab põhiprotsessi, hulk alamprotsesse, edastab neile kuulamispesad ja nad töötlevad nende taotlusi. Sel juhul ei taaskäivitata protsesse iga kasutaja päringu vahel, vaid lihtsalt lähtestatakse nende olek algse nullväärtusega olekusse – taaskäivitamise asemel päring päringu järel.

Koormuse jaotus

Kõik meie taustaprogrammid ei ole suur hulk masinaid, mis suudaksid mis tahes taotlusi töödelda. Meie nemad jagatud eraldi rühmadesse: üldine, mobiilne, api, video, lavastus... Eraldi masinarühma probleem ei mõjuta kõiki teisi. Videoga seotud probleemide korral ei saa muusikat kuulav kasutaja probleemidest isegi teada. Millisele taustaprogrammile päring saata, otsustab nginx esiküljel vastavalt konfiguratsioonile.

Mõõdikute kogumine ja tasakaalustamine

Et mõista, kui palju autosid meil igas rühmas peab olema, me ärge lootke QPS-ile. Taustaprogrammid on erinevad, neil on erinevad päringud, igal päringul on erinev QPS-i arvutamise keerukus. Sellepärast me töötame koormuse kontseptsiooniga serveril tervikuna - protsessoril ja perf.

Meil on tuhandeid selliseid servereid. Iga füüsiline server käivitab kõigi tuumade taaskasutamiseks kPHP rühma (kuna kPHP on ühe keermega).

Sisuserver

CS või sisuserver on salvestusruum. CS on server, mis salvestab faile ja töötleb ka üleslaaditud faile ja kõikvõimalikke taustal sünkroonseid ülesandeid, mille peamine veebiliides sellele määrab.

Meil on kümneid tuhandeid füüsilisi servereid, mis salvestavad faile. Kasutajatele meeldib faile üles laadida ning meile meeldib neid salvestada ja jagada. Mõned neist serveritest on suletud spetsiaalsete pu/pp serveritega.

pu/pp

Kui avasite VK-s võrgu vahekaardi, nägite pu/pp.

KKK arhitektuuri ja VKontakte töö kohta

Mis on pu/pp? Kui sulgeme ühe serveri teise järel, on faili üles- ja allalaadimiseks suletud serverisse kaks võimalust: otse läbi http://cs100500.userapi.com/path või vaheserveri kaudu - http://pu.vk.com/c100500/path.

Pu on fotode üleslaadimise ajalooline nimi ja pp on foto puhverserver. See tähendab, et üks server on fotode ja teine ​​​​üleslaadimiseks. Nüüd ei laadita mitte ainult fotosid, vaid ka nimi on säilinud.

Need serverid lõpetage HTTPS-i seansidprotsessori koormuse eemaldamiseks mälust. Kuna kasutajafaile töödeldakse nendes serverites, siis mida vähem tundlikku teavet nendesse masinatesse salvestatakse, seda parem. Näiteks HTTPS-i krüpteerimisvõtmed.

Kuna masinad on suletud meie teiste masinate poolt, saame lubada, et me ei anna neile “valgeid” väliseid IP-sid ja anna "hall". Nii hoidsime kokku IP-kogumi pealt ja garanteerisime masinate kaitsmise välise juurdepääsu eest – sinna lihtsalt pole IP-d, kuhu pääseda.

Vastupidavus jagatud IP-de üle. Veataluvuse osas töötab skeem samamoodi – mitmel füüsilisel serveril on ühine füüsiline IP ja nende ees olev riistvara valib, kuhu päring saata. Muudest võimalustest räägin hiljem.

Vastuoluline punkt on see, et antud juhul klient hoiab vähem ühendusi. Kui mitme masina jaoks on sama IP - sama hostiga: pu.vk.com või pp.vk.com, on kliendibrauseris ühele hostile saadetavate samaaegsete päringute arvu piirang. Kuid üldlevinud HTTP/2 ajal usun, et see pole enam nii asjakohane.

Skeemi ilmne puudus on see, et see peab olema pumpa kogu liiklus, mis läheb salvestusruumi teise serveri kaudu. Kuna me pumpame liiklust läbi masinate, ei saa me veel sama skeemi järgi pumbata tihedat liiklust, näiteks videot. Me edastame selle otse - eraldi otseühendus eraldi videosalvestuste jaoks. Kergemat sisu edastame puhverserveri kaudu.

Mitte kaua aega tagasi saime puhverserveri täiustatud versiooni. Nüüd ma ütlen teile, kuidas need erinevad tavalistest ja miks see on vajalik.

Sun

2017. aasta septembris oli varem Suni ostnud Oracle vallandas tohutu hulga Suni töötajaid. Võime öelda, et sel hetkel lakkas ettevõte eksisteerimast. Uuele süsteemile nime valides otsustasid meie administraatorid avaldada austust selle ettevõtte mälestusele ja andsid uuele süsteemile nimeks Sun. Omavahel kutsume teda lihtsalt "päikesteks".

KKK arhitektuuri ja VKontakte töö kohta

pp-l oli mõned probleemid. Üks IP rühma kohta – ebaefektiivne vahemälu. Mitmel füüsilisel serveril on ühine IP-aadress ja pole võimalik kontrollida, millisesse serverisse päring suunatakse. Seega, kui sama faili jaoks tulevad erinevad kasutajad, siis kui nendel serveritel on vahemälu, siis fail jõuab iga serveri vahemällu. See on väga ebaefektiivne skeem, kuid midagi ei saa teha.

Järelikult - me ei saa sisu killustada, kuna me ei saa selle grupi jaoks konkreetset serverit valida - neil on ühine IP. Ka mõnel sisemisel põhjusel selliseid servereid ei olnud võimalik piirkondadesse installida. Nad seisid ainult Peterburis.

Päikesega muutsime valikusüsteemi. Nüüd on meil anycasti marsruutimine: dünaamiline marsruutimine, anycast, enesekontrolli deemon. Igal serveril on oma individuaalne IP, kuid ühine alamvõrk. Kõik on konfigureeritud nii, et kui üks server ebaõnnestub, jaotatakse liiklus automaatselt sama rühma teiste serverite vahel. Nüüd on võimalik valida konkreetne server, pole üleliigset vahemällu, ja töökindlus see ei muutunud.

Kaalu tugi. Nüüd saame endale lubada erineva võimsusega masinate paigaldamist vastavalt vajadusele ning ka ajutiste probleemide korral töötavate “päikeste” raskusi nende koormuse vähendamiseks muuta, et need “puhkaksid” ja hakkaksid uuesti tööle.

Jagamine sisu ID järgi. Naljakas seik jagamise kohta: tavaliselt jagame sisu nii, et erinevad kasutajad läheksid sama faili juurde läbi sama „päikese”, et neil oleks ühine vahemälu.

Hiljuti käivitasime rakenduse "Clover". See on otseülekande veebiviktoriin, kus saatejuht esitab küsimusi ja kasutajad vastavad reaalajas, valides valikuid. Rakendusel on vestlus, kus kasutajad saavad vestelda. Saab samaaegselt ühenduda saatega rohkem kui 100 tuhat inimest. Nad kõik kirjutavad sõnumeid, mis saadetakse kõigile osalejatele ja sõnumiga kaasneb avatar. Kui ühe avatari järele tuleb 100 tuhat inimest ühes “päikeses”, siis võib see vahel pilve taha veereda.

Selleks, et sama faili päringud vastu seista, lülitame teatud tüüpi sisu puhul sisse rumala skeemi, mis levitab failid kõigis regioonis saadaolevates "päikestes".

Päike seestpoolt

Pöörake puhverserverit nginxis, vahemälu kas RAM-is või kiiretel Optane/NVMe ketastel. Näide: http://sun4-2.userapi.com/c100500/path — link "päikesele", mis asub neljandas piirkonnas, teises serverirühmas. See sulgeb teefaili, mis asub füüsiliselt serveris 100500.

Cache

Lisame oma arhitektuuriskeemi veel ühe sõlme – vahemällu salvestamise keskkonna.

KKK arhitektuuri ja VKontakte töö kohta

Allpool on paigutusskeem piirkondlikud vahemälud, neid on umbes 20. Need on kohad, kus asuvad vahemälud ja "päikesed", mis võivad liiklust ise vahemällu salvestada.

KKK arhitektuuri ja VKontakte töö kohta

See on multimeediumisisu vahemällu salvestamine; siin ei salvestata kasutajaandmeid – ainult muusika, videod, fotod.

Kasutaja piirkonna määramiseks me kogume piirkondades väljakuulutatud BGP-võrgu eesliiteid. Kui me ei leidnud IP-d eesliidete järgi, peame parsima ka geoip-i andmebaasi. Määrame piirkonna kasutaja IP järgi. Koodis saame vaadata üht või mitut kasutaja piirkonda – neid punkte, millele ta on geograafiliselt kõige lähemal.

Kuidas see toimib?

Loendame failide populaarsust piirkondade kaupa. Seal on mitu piirkondlikku vahemälu, kus kasutaja asub, ja failiidentifikaator – võtame selle paari ja suurendame iga allalaadimisega reitingut.

Samal ajal tulevad deemonid - piirkondades asuvad teenused - aeg-ajalt API-sse ja ütlevad: "Olen selline ja selline vahemälu, andke mulle nimekiri minu piirkonna populaarseimatest failidest, mida minus veel pole. ” API edastab hulga faile, mis on sorteeritud reitingute järgi, deemon laadib need alla, viib need piirkondadesse ja edastab failid sealt. See on pu/pp ja Suni vahemälude põhimõtteline erinevus: nad annavad faili kohe enda kaudu, isegi kui seda faili vahemälus pole, ja vahemälu laadib faili esmalt endale ja seejärel hakkab seda tagasi andma.

Sel juhul saame sisu kasutajatele lähemal ja võrgu koormuse hajutamine. Näiteks ainult Moskva vahemälust levitame tipptundidel rohkem kui 1 Tbit/s.

Kuid on probleeme - vahemäluserverid ei ole kummist. Ülipopulaarse sisu puhul ei piisa mõnikord võrgust eraldi serveri jaoks. Meie vahemäluserverid on 40-50 Gbit/s, kuid on sisu, mis sellise kanali täielikult ummistab. Liigume selles piirkonnas populaarsete failide enam kui ühe koopia salvestamise juurutamise poole. Loodan, et rakendame selle aasta lõpuks.

Vaatasime üldist arhitektuuri.

  • Esiserverid, mis võtavad vastu taotlusi.
  • Taustaprogrammid, mis töötlevad taotlusi.
  • Salvestusruumid, mis on suletud kahte tüüpi puhverserveritega.
  • Piirkondlikud vahemälud.

Mis sellel diagrammil puudu on? Muidugi andmebaasid, kuhu andmeid salvestame.

Andmebaasid või mootorid

Me nimetame neid mitte andmebaasideks, vaid mootoriteks - mootoriteks, kuna meil praktiliselt puuduvad andmebaasid üldtunnustatud tähenduses.

KKK arhitektuuri ja VKontakte töö kohta

See on vajalik meede. See juhtus seetõttu, et aastatel 2008-2009, kui VK populaarsus plahvatuslikult kasvas, töötas projekt täielikult MySQL-i ja Memcache'i peal ning tekkis probleeme. MySQL armastas krahhi ja faile rikkuda, pärast mida see ei taastunud ning Memcache jõudlus halvenes järk-järgult ja see tuli taaskäivitada.

Selgub, et üha populaarsemaks muutuval projektil oli püsimälu, mis rikub andmeid, ja vahemälu, mis aeglustab. Sellistes tingimustes on kasvuprojekti raske välja töötada. Otsustati proovida need kriitilised asjad, millele projekt keskendus, ümber kirjutada meie enda jalgratastele.

Lahendus oli edukas. Selleks oli nii võimalus kui ka äärmine vajadus, sest muid skaleerimisviise tol ajal ei eksisteerinud. Seal polnud hunnikut andmebaase, NoSQL-i polnud veel olemas, olid ainult MySQL, Memcache, PostrgreSQL - ja kõik.

Universaalne töö. Arendust juhtis meie C-arendajate meeskond ja kõik toimus järjepidevalt. Sõltumata mootorist oli neil kõigil ligikaudu sama failivorming, mis oli kettale kirjutatud, samad käivitusparameetrid, töödeldi signaale ühtemoodi ning käitusid servaolukordade ja probleemide korral ligikaudu samamoodi. Mootorite kasvuga on süsteemi haldajatel mugav kasutada – pole loomaaeda, mida oleks vaja hooldada ning iga uue kolmanda osapoole andmebaasi haldamist tuleb uuesti õppida, mis võimaldas kiiresti ja mugavalt suurendada nende arv.

Mootorite tüübid

Meeskond kirjutas üsna palju mootoreid. Siin on vaid mõned neist: sõber, vihjed, pilt, ipdb, tähed, loendid, logid, memcached, meowdb, uudised, nostradamus, foto, esitusloendid, pmemcached, liivakast, otsing, salvestusruum, meeldimised, ülesanded, ...

Iga ülesande jaoks, mis nõuab konkreetset andmestruktuuri või töötleb ebatüüpilisi päringuid, kirjutab C-meeskond uue mootori. Miks mitte.

Meil on eraldi mootor mälukaart, mis sarnaneb tavalisele, aga hunniku hea-paremaga ja mis ei võta hoogu maha. Mitte ClickHouse, aga see ka töötab. Saadaval eraldi pmemcached - Kas püsivalt salvestatud, mis suudab salvestada andmeid ka kettale, lisaks mahub see RAM-i, et mitte kaotada andmeid taaskäivitamisel. Üksikute ülesannete jaoks on erinevaid mootoreid: järjekorrad, loendid, komplektid - kõik, mida meie projekt nõuab.

Klastrid

Koodi vaatenurgast ei ole vaja mõelda mootoritele või andmebaasidele kui protsessidele, olemitele või eksemplaridele. Kood töötab spetsiaalselt klastritega, mootorirühmadega - üks tüüp klastri kohta. Oletame, et on vahemällu salvestatud klaster – see on lihtsalt rühm masinaid.

Kood ei pea üldse teadma serverite füüsilist asukohta, suurust ega arvu. Ta läheb klastrisse kindlat identifikaatorit kasutades.

Selle toimimiseks peate lisama veel ühe olemi, mis asub koodi ja mootorite vahel - volikiri.

RPC puhverserver

Puhverserver ühendusbuss, millel töötab peaaegu kogu sait. Samal ajal on meil teenust ei leitud — selle asemel on selle puhverserveri jaoks konfiguratsioon, mis teab kõigi klastrite ja selle klastri kõigi kildude asukohta. Seda teevad administraatorid.

Programmeerijaid ei huvita üldse, kui palju, kus ja mis see maksab – nad lähevad lihtsalt klastrisse. See võimaldab meil palju. Päringu saamisel suunab puhverserver päringu ümber, teades kuhu – määrab selle ise.

KKK arhitektuuri ja VKontakte töö kohta

Sel juhul on puhverserver kaitsepunkt teenusetõrgete eest. Kui mõni mootor aeglustub või jookseb kokku, saab puhverserver sellest aru ja reageerib vastavalt kliendi poolele. See võimaldab ajalõpu eemaldada – kood ei oota mootori reageerimist, vaid saab aru, et see ei tööta ja peab kuidagi teisiti käituma. Kood peab olema valmis selleks, et andmebaasid alati ei tööta.

Konkreetsed teostused

Mõnikord tahame ikka väga, et mootoriks oleks mingi ebastandardne lahendus. Samal ajal otsustati mitte kasutada meie spetsiaalselt meie mootorite jaoks loodud valmis rpc-puhverserverit, vaid teha ülesande jaoks eraldi puhverserver.

MySQL-i jaoks, mida meil siin-seal ikka on, kasutame db-puhverserverit ja ClickHouse'i jaoks - Kassipoeg.

See töötab üldiselt nii. Seal on kindel server, see töötab kPHP, Go, Python - üldiselt mis tahes kood, mis saab kasutada meie RPC-protokolli. Kood töötab lokaalselt RPC puhverserveril – iga server, kus kood asub, käitab oma kohalikku puhverserverit. Taotluse korral saab puhverserver aru, kuhu pöörduda.

KKK arhitektuuri ja VKontakte töö kohta

Kui üks mootor tahab minna teisele, isegi kui see on naaber, siis see läbib puhverserveri, sest naaber võib olla teises andmekeskuses. Mootor ei tohiks loota millegi muu asukoha teadmisele peale iseenda – see on meie standardlahendus. Aga muidugi on erandeid :)

Näide TL-skeemist, mille järgi töötavad kõik mootorid.

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;

See on binaarne protokoll, mille lähim analoog on protobuf. Skeem kirjeldab ette valikulisi välju, keerukaid tüüpe – sisseehitatud skalaaride laiendusi ja päringuid. Kõik töötab selle protokolli järgi.

RPC üle TL üle TCP/UDP… UDP?

Meil on mootoripäringute täitmiseks RPC-protokoll, mis töötab TL-skeemi peal. See kõik töötab TCP/UDP-ühenduse kaudu. TCP on arusaadav, kuid miks me vajame sageli UDP-d?

UDP aitab vältida suure hulga serveritevaheliste ühenduste probleemi. Kui igal serveril on RPC-puhverserver ja üldiselt võib see minna suvalisele mootorile, siis on serveri kohta kümneid tuhandeid TCP-ühendusi. Koormus on, kuid see on kasutu. UDP puhul seda probleemi ei esine.

Ei mingit üleliigset TCP-käepigistust. See on tüüpiline probleem: kui käivitatakse uus mootor või uus server, luuakse korraga palju TCP-ühendusi. Väikeste kergete päringute, näiteks UDP kasuliku koormuse puhul, toimub kogu side koodi ja mootori vahel kaks UDP paketti: üks lendab ühes, teine ​​teises suunas. Üks edasi-tagasi reis - ja kood sai mootorilt vastuse ilma käepigistuseta.

Jah, see kõik lihtsalt töötab väga väikese pakettkao protsendiga. Protokollil on kordusedastuste ja ajalõppude tugi, kuid kui kaotame palju, saame peaaegu TCP, mis pole kasulik. Me ei sõida UDP-ga üle ookeanide.

Meil on tuhandeid selliseid servereid ja skeem on sama: igasse füüsilisse serverisse on installitud pakett mootoreid. Need on enamasti ühe keermega, et töötada võimalikult kiiresti ilma blokeeringuteta, ja need on killustatud ühe keermega lahendustena. Samas pole meil nendest mootoritest midagi usaldusväärsemat ja palju tähelepanu pööratakse püsivale andmesalvestusele.

Pidev andmete salvestamine

Mootorid kirjutavad binloge. Binlog on fail, mille lõppu lisatakse oleku või andmete muutumise sündmus. Erinevates lahendustes nimetatakse seda erinevalt: binaarlogi, WAL, AOF, kuid põhimõte on sama.

Et mootor ei loeks taaskäivitamisel mitu aastat kogu binlogi uuesti läbi, kirjutavad mootorid hetktõmmised – hetkeseis. Vajadusel loevad nad kõigepealt sellest ja seejärel lõpetavad lugemise binlogist. Kõik binlogid on kirjutatud samas binaarvormingus – TL skeemi järgi, et administraatorid saaksid neid oma tööriistu kasutades võrdselt hallata. Sellist hetktõmmiste vajadust pole. Seal on üldine päis, mis näitab, kelle hetktõmmis on int, mootori võlu ja milline keha pole kellelegi oluline. See on hetktõmmise salvestanud mootori probleem.

Kirjeldan kiiresti tööpõhimõtet. Seal on server, millel mootor töötab. Ta avab kirjutamiseks uue tühja binlogi ja kirjutab selle muutmiseks sündmuse.

KKK arhitektuuri ja VKontakte töö kohta

Mingil hetkel otsustab ta kas ise pildistada või saab signaali. Server loob uue faili, kirjutab sellesse kogu oleku, lisab faili lõppu praeguse binlogi suuruse – nihke – ja jätkab kirjutamist. Uut binlogi ei looda.

KKK arhitektuuri ja VKontakte töö kohta

Mingil hetkel, kui mootor taaskäivitub, on kettal nii binlog kui ka snapshot. Mootor loeb kogu hetktõmmise ja tõstab oma olekut teatud punktis.

KKK arhitektuuri ja VKontakte töö kohta

Loeb hetktõmmise loomise ajal positsiooni ja binlogi suuruse.

KKK arhitektuuri ja VKontakte töö kohta

Loeb hetkeseisu vaatamiseks binlogi lõpu ja jätkab edasiste sündmuste kirjutamist. See on lihtne skeem, kõik meie mootorid töötavad selle järgi.

Andmete replikatsioon

Selle tulemusena andmete replikatsioon meie väitepõhine — me kirjutame binlogi mitte mingeid lehemuudatusi, vaid just nimelt muutmistaotlused. Väga sarnane sellega, mis tuleb võrgu kaudu, ainult veidi muudetud.

Sama skeemi kasutatakse mitte ainult replikatsiooniks, vaid ka varukoopiate loomiseks. Meil on mootor – kirjutamismeister, mis kirjutab binlogi. Igas teises kohas, kus administraatorid selle seadistavad, kopeeritakse see binlog ja ongi kõik – meil on varukoopia.

KKK arhitektuuri ja VKontakte töö kohta

Kui vajate koopia lugemineProtsessori lugemiskoormuse vähendamiseks käivitatakse lihtsalt lugemismootor, mis loeb binlogi lõppu ja täidab need käsud kohapeal.

Siin on mahajäämus väga väike ja on võimalik teada saada, kui palju koopia kaptenist maha jääb.

Andmete jagamine RPC puhverserveris

Kuidas jagamine töötab? Kuidas puhverserver aru saab, millisele klastri killule saata? Kood ei ütle: "Saada 15 killu eest!" - ei, seda teeb puhverserver.

Lihtsaim skeem on firstint — päringu esimene number.

get(photo100_500) => 100 % N.

See on näide lihtsa vahemällu salvestatud tekstiprotokolli kohta, kuid loomulikult võivad päringud olla keerulised ja struktureeritud. Näide võtab päringu esimese arvu ja ülejäänud arvu, kui see jagatakse klastri suurusega.

See on kasulik, kui soovime ühe üksuse andmete asukohta. Oletame, et 100 on kasutaja või rühma ID ja me tahame, et kõik ühe olemi andmed oleksid keeruliste päringute jaoks ühes killus.

Kui meid ei huvita, kuidas päringud klastris jaotuvad, on veel üks võimalus – kogu killu räsimine.

hash(photo100_500) => 3539886280 % N

Samuti saame räsi, jaotuse ülejäänud osa ja killu numbri.

Mõlemad valikud töötavad ainult siis, kui oleme valmis selleks, et klastri suuruse suurendamisel jagame selle kaheks või suurendame seda mitmekordseks. Näiteks oli meil 16 kildu, meil ei ole piisavalt, tahame rohkem - saame ohutult 32 ilma seisakuta. Kui tahame suurendada, mitte kordades, siis tekib seisakuid, sest me ei saa kõike täpselt jaotada ilma kadudeta. Need valikud on kasulikud, kuid mitte alati.

Kui meil on vaja lisada või eemaldada suvaline arv servereid, kasutame seda Järjepidev räsimine sõrmuses a la Ketama. Kuid samal ajal kaotame täielikult andmete asukoha; peame ühendama päringu klastriga, nii et iga tükk tagastaks oma väikese vastuse, ja seejärel liitma vastused puhverserverile.

On ülispetsiifilisi taotlusi. See näeb välja järgmine: RPC puhverserver võtab päringu vastu, määrab, millisesse kobarasse minna, ja määrab killu. Siis on olemas kas kirjutamisjuhised või kui klastris on koopia tugi, saadab see nõudmisel koopiale. Puhverserver teeb seda kõike.

KKK arhitektuuri ja VKontakte töö kohta

Palgid

Kirjutame logisid mitmel viisil. Kõige ilmsem ja lihtsam on kirjutada logid memcache'i.

ring-buffer: prefix.idx = line

Seal on võtme eesliide - logi nimi, rida ja selle logi suurus - ridade arv. Me võtame juhusliku arvu 0-st ridade arvuni, millest on lahutatud 1. Memcache'i võti on selle juhusliku numbriga ühendatud eesliide. Väärtusse salvestame logirea ja praeguse aja.

Kui on vaja logisid lugeda, teostame Multi Get kõik võtmed on sorteeritud aja järgi ja seega saate reaalajas tootmislogi. Skeemi kasutatakse siis, kui on vaja midagi tootmises siluda reaalajas, midagi lõhkumata, peatamata või liiklust teistele masinatele lubamata, kuid see logi ei kesta kaua.

Palkide usaldusväärseks ladustamiseks on meil mootor logi-mootor. Just sellepärast see loodi ja seda kasutatakse laialdaselt paljudes klastrites. Minu teada suurim klaster sisaldab 600 TB pakitud palke.

Mootor on väga vana, on klastreid, mis on juba 6-7 aastat vanad. Sellega on probleeme, mida proovime lahendada, näiteks hakkasime ClickHouse'i logide salvestamiseks aktiivselt kasutama.

Logide kogumine ClickHouse'is

See diagramm näitab, kuidas me oma mootoritesse siseneme.

KKK arhitektuuri ja VKontakte töö kohta

Seal on kood, mis läheb kohalikult RPC kaudu RPC-puhverserverile ja see mõistab, kuhu mootorisse minna. Kui tahame ClickHouse'is logisid kirjutada, peame selles skeemis muutma kahte osa:

  • asendada mõni mootor ClickHouse'iga;
  • asendada RPC puhverserver, millele ClickHouse'ile juurde ei pääse, mõne lahendusega, mis seda saab, ja RPC kaudu.

Mootor on lihtne – asendame selle serveriga või ClickHouse’i serverite klastriga.

Ja ClickHouse'i minekuks me seda tegime Kassipoja maja. Kui me läheme KittenHouse'ist otse ClickHouse'i, siis see ei tule toime. Isegi ilma päringuteta lisandub see suure hulga masinate HTTP-ühendustest. Et skeem töötaks, ClickHouse'iga serveris kohalik pöördpuhverserver tõstetakse, mis on kirjutatud nii, et see peab vastu nõutavatele ühenduste mahtudele. Samuti suudab see suhteliselt usaldusväärselt andmeid enda sees puhverdada.

KKK arhitektuuri ja VKontakte töö kohta

Mõnikord ei taha me RPC-skeemi rakendada mittestandardsetes lahendustes, näiteks nginxis. Seetõttu on KittenHouse'il võimalus UDP kaudu logisid vastu võtta.

KKK arhitektuuri ja VKontakte töö kohta

Kui logide saatja ja saaja töötavad samas masinas, on UDP-paketi kadumise tõenäosus kohalikus hostis üsna väike. Kompromissina kolmanda osapoole lahenduses RPC juurutamise vajaduse ja töökindluse vahel kasutame lihtsalt UDP-saatmist. Tuleme selle skeemi juurde hiljem tagasi.

Jälgimine

Meil on kahte tüüpi logisid: administraatorite kogutud logid oma serverites ja need, mille on kirjutanud arendajad koodist. Need vastavad kahte tüüpi mõõdikutele: süsteem ja toode.

Süsteemi mõõdikud

See töötab kõigis meie serverites Netiandmed, mis kogub statistikat ja saadab selle aadressile Grafiit süsinik. Seetõttu kasutatakse salvestussüsteemina ClickHouse'i, mitte näiteks Whisperit. Vajadusel saab ClickHouse'ist otse lugeda või kasutada grafana mõõdikute, graafikute ja aruannete jaoks. Arendajatena on meil piisavalt juurdepääsu Netdatale ja Grafanale.

Tootemõõdikud

Mugavuse huvides oleme kirjutanud palju asju. Näiteks on tavaliste funktsioonide komplekt, mis võimaldab kirjutada statistikasse loenduste, unikaalsete loenduste väärtusi, mis saadetakse kuhugi kaugemale.

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

$stats = statlogsStatData($params)

Seejärel saame kasutada sortimis- ja rühmitamisfiltreid ning teha statistikast kõike, mida tahame – koostada graafikuid, seadistada valvekoeri.

Kirjutame väga palju mõõdikuid sündmuste arv on 600 miljardist 1 triljonini päevas. Siiski tahame neid hoida vähemalt paar aastatmõõdikute suundumuste mõistmiseks. Selle kõige kokku panemine on suur probleem, mida me pole veel lahendanud. Ma räägin teile, kuidas see on viimase paari aasta jooksul toiminud.

Meil on funktsioonid, mis neid mõõdikuid kirjutavad kohalikku memcache'ikirjete arvu vähendamiseks. Kord lühikese aja jooksul kohapeal käivitatud stats-deemon kogub kõik rekordid. Järgmisena liidab deemon mõõdikud kaheks serverikihiks palgid-kogujad, mis koondab meie masinate hulga statistikat nii, et nende taga olev kiht ei sureks.

KKK arhitektuuri ja VKontakte töö kohta

Vajadusel saame kirjutada otse palkidele-kogujatele.

KKK arhitektuuri ja VKontakte töö kohta

Kuid koodist otse kollektoritele kirjutamine, stas-daemomist mööda minnes, on halvasti skaleeritav lahendus, kuna see suurendab kollektori koormust. Lahendus sobib ainult siis, kui mingil põhjusel me ei saa masinal memcache stats-deemonit tõsta või see jooksis kokku ja läksime otse.

Järgmiseks liidavad logid-kogujad statistikasse mjäuDB - see on meie andmebaas, mis võib salvestada ka mõõdikuid.

KKK arhitektuuri ja VKontakte töö kohta

Seejärel saame koodist teha binaarseid “SQL-i peaaegu” valikuid.

KKK arhitektuuri ja VKontakte töö kohta

Eksperiment

2018. aasta suvel toimus meil sisemine häkaton ja tekkis mõte proovida asendada diagrammi punane osa millegagi, mis võiks ClickHouse’i mõõdikuid salvestada. Meil on ClickHouse'is logid – miks mitte proovida?

KKK arhitektuuri ja VKontakte töö kohta

Meil oli skeem, mis kirjutas logisid KittenHouse'i kaudu.

KKK arhitektuuri ja VKontakte töö kohta

Otsustasime lisage diagrammile veel üks "*Maja"., mis saab täpselt mõõdikud sellises vormingus, nagu meie kood need UDP kaudu kirjutab. Siis muudab see *House need sisestusteks, nagu palgid, millest KittenHouse aru saab. Ta suudab need logid suurepäraselt edastada ClickHouse'ile, mis peaks suutma neid lugeda.

KKK arhitektuuri ja VKontakte töö kohta

Sellega asendatakse skeem mälumälu, stats-deemoni ja logide-kogujate andmebaasiga.

KKK arhitektuuri ja VKontakte töö kohta

Sellega asendatakse skeem mälumälu, stats-deemoni ja logide-kogujate andmebaasiga.

  • Siin on saadetis koodist, mis on kirjutatud kohapeal StatsHouse'is.
  • StatsHouse kirjutab KittenHouse'i partiidena UDP-mõõdikud, mis on juba konverteeritud SQL-i sisestusteks.
  • KittenHouse saadab need ClickHouse'ile.
  • Kui tahame neid lugeda, siis loeme neid StatsHouse'ist mööda minnes – otse ClickHouse'ist, kasutades tavalist SQL-i.

Kas ikka katse, aga meile meeldib, kuidas see välja tuleb. Kui skeemiga probleemid lahendame, läheme võib-olla sellele täielikult üle. Mina isiklikult loodan nii.

Kava rauda kokku ei hoia. Vaja on vähem servereid, kohalikke statistikadeemone ja logide kogujaid pole vaja, kuid ClickHouse nõuab suuremat serverit kui praeguses skeemis. Vaja on vähem servereid, kuid need peavad olema kallimad ja võimsamad.

Kasutusele võtta

Kõigepealt vaatame PHP juurutamist. Me areneme sisse git: kasutada GitLab и TeamCity kasutuselevõtuks. Arendusharud liidetakse põhiharuks, testimise jaoks liidetakse põhiharust lavastusse ja lavastusest tootmisse.

Enne juurutamist võetakse praegune tootmisharu ja eelmine ning nendes arvestatakse diff-faile - muudatusi: loodud, kustutatud, muudetud. See muudatus salvestatakse spetsiaalse kopeerimismootori binlogi, mis suudab kiiresti korrata muudatusi kogu meie serveripargis. Siin ei kasutata otse kopeerimist, vaid kuulujuttude replikatsioon, kui üks server saadab muudatused lähimatele naabritele, need oma naabritele jne. See võimaldab teil koodi värskendada kümnete ja sekundite ühikutega kogu sõidukipargi ulatuses. Kui muudatus jõuab kohaliku koopiani, rakendab see need plaastrid omale kohalik failisüsteem. Tagasivõtmine toimub ka sama skeemi järgi.

Samuti juurutame palju kPHP-d ja sellel on ka oma arendus git vastavalt ülaltoodud skeemile. Alates sellest HTTP-serveri binaarfail, siis me ei saa toota diff - väljalaskebinaar kaalub sadu MB. Seetõttu on siin veel üks võimalus - versioon on kirjutatud binlog copyfast. Iga ehitamisega see suureneb ja tagasipööramise ajal ka suureneb. Versioon replikeeritakse serveritesse. Kohalikud copyfastid näevad, et binlogi on sisenenud uus versioon ja sama kuulujuttude replikatsiooni abil võtavad nad enda jaoks binaarfaili uusima versiooni, väsimata meie peaserverit, vaid jaotades koormust hoolikalt üle võrgu. Mis järgneb graatsiline taaskäivitamine uue versiooni jaoks.

Meie mootorite puhul, mis on samuti sisuliselt kahendkoodid, on skeem väga sarnane:

  • git master filiaal;
  • binaarne sisse deb;
  • versioon kirjutatakse binlogi copyfasti;
  • kopeeritud serveritesse;
  • server tõmbab välja värske .dep;
  • dpkg -i;
  • graatsiline taaskäivitamine uuele versioonile.

Erinevus seisneb selles, et meie binaarfail on pakitud arhiividesse deb, ja nende väljapumpamisel dpkg -i paigutatakse süsteemi. Miks juurutatakse kPHP kahendfailina ja mootorid dpkg-na? See juhtus nii. See töötab – ära puuduta seda.

Kasulikud lingid:

Aleksei Akulovitš on üks neist, kes programmikomitee koosseisus aitab PHP Venemaa 17. mail saab PHP arendajate jaoks viimase aja suurim sündmus. Vaata kui lahe arvuti meil on, mis kõlarid (neist kaks arendavad PHP-tuuma!) - tundub midagi, millest ei saa PHP kirjutamisel märkamata jääda.

Allikas: www.habr.com

Lisa kommentaar