VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

VKontakte-nin yaranma tarixi Vikipediyadadır, bunu Pavel özü deyib. Deyəsən artıq hamı onu tanıyır. HighLoad++ Pavel-də saytın daxili hissələri, memarlığı və strukturu haqqında 2010-cu ildə mənə dedi. O vaxtdan bəri bir çox server sızdı, buna görə də məlumatları yeniləyəcəyik: biz onu parçalayacağıq, içini çıxaracağıq, çəkin və VK cihazına texniki baxımdan baxacağıq.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Aleksey Akuloviç (AterCattus) VKontakte komandasında backend developer. Bu hesabatın stenoqramı platformanın işləməsi, infrastruktur, serverlər və onlar arasında qarşılıqlı əlaqə haqqında tez-tez verilən suallara kollektiv cavabdır, lakin inkişafla bağlı deyil, daha doğrusu. dəmir haqqında. Ayrı-ayrılıqda, verilənlər bazası və bunun əvəzinə VK-nın nə olduğu, qeydlərin toplanması və bütövlükdə bütün layihənin monitorinqi haqqında. Kəsmə altındakı detallar.



Dörd ildən artıqdır ki, mən backendlə bağlı hər cür tapşırıqlarla məşğul oluram.

  • Medianın yüklənməsi, saxlanması, işlənməsi, paylanması: video, canlı yayım, audio, fotoşəkillər, sənədlər.
  • İnfrastruktur, platforma, tərtibatçı monitorinqi, qeydlər, regional keşlər, CDN, mülkiyyət RPC protokolu.
  • Xarici xidmətlərlə inteqrasiya: push bildirişləri, xarici link təhlili, RSS lenti.
  • Həmkarlarına müxtəlif suallarla kömək etmək, cavabları naməlum koda dalmaq lazımdır.

Bu müddət ərzində saytın bir çox komponentlərində əlim var idi. Mən bu təcrübəni bölüşmək istəyirəm.

Ümumi memarlıq

Hər şey, həmişə olduğu kimi, sorğuları qəbul edən server və ya serverlər qrupu ilə başlayır.

Ön server

Ön server HTTPS, RTMP və WSS vasitəsilə sorğuları qəbul edir.

HTTPS - bunlar saytın əsas və mobil veb versiyaları üçün sorğulardır: vk.com və m.vk.com və API-mizin digər rəsmi və qeyri-rəsmi müştəriləri: mobil müştərilər, messencerlər. Bizim qəbulumuz var RTMP-ayrı ön serverləri olan Canlı yayımlar üçün trafik və WSS- Streaming API üçün bağlantılar.

Serverlərdə HTTPS və WSS üçün buna dəyər nginx. RTMP yayımları üçün bu yaxınlarda öz həllimizə keçdik kive, lakin bu hesabatın əhatə dairəsindən kənardadır. Səhvlərə dözümlülük üçün bu serverlər ümumi IP ünvanlarını reklam edir və qruplar şəklində fəaliyyət göstərirlər ki, serverlərdən birində problem yaranarsa, istifadəçi sorğuları itməsin. HTTPS və WSS üçün eyni serverlər CPU yükünün bir hissəsini öz üzərinə götürmək üçün trafiki şifrələyirlər.

WSS və RTMP haqqında daha çox danışmayacağıq, ancaq adətən veb layihəsi ilə əlaqəli olan standart HTTPS sorğuları haqqında.

Arxa

Ön tərəfin arxasında adətən backend serverləri var. Onlar ön serverin müştərilərdən aldığı sorğuları emal edir.

O kPHP serverləri, HTTP demonunun işlədiyi, çünki HTTPS artıq deşifrə olunub. kPHP üzərində işləyən bir serverdir ön çəngəl modelləri: master prosesi, bir dəstə uşaq prosesləri başlayır, onlara dinləmə yuvalarını ötürür və sorğularını emal edirlər. Bu halda, istifadəçilərin hər sorğusu arasında proseslər yenidən başlamır, sadəcə olaraq, yenidən başlama əvəzinə onların vəziyyətini orijinal sıfır dəyər vəziyyətinə - sorğudan sonra sorğuya qaytarır.

Yük paylanması

Bütün arxa tərəflərimiz istənilən sorğunu emal edə biləcək böyük bir maşın hovuzu deyil. Biz onları ayrı-ayrı qruplara bölünür: ümumi, mobil, api, video, səhnələşdirmə... Ayrı bir qrup maşındakı problem bütün digərlərinə təsir etməyəcək. Video ilə bağlı problemlər yaranarsa, musiqi dinləyən istifadəçinin problemlərdən xəbəri belə olmayacaq. Sorğunun hansı backend-ə göndərilməsi konfiqurasiyaya uyğun olaraq ön tərəfdəki nginx tərəfindən müəyyən edilir.

Metrik toplama və yenidən balanslaşdırma

Hər qrupda neçə avtomobilin olması lazım olduğunu başa düşmək üçün biz QPS-ə etibar etməyin. Arxa tərəflər fərqlidir, onların fərqli sorğuları var, hər sorğunun QPS hesablanmasının fərqli mürəkkəbliyi var. Ona görə də biz biz bütövlükdə serverdə - CPU və perf-də yük konsepsiyası ilə işləyirik.

Bizdə minlərlə belə server var. Hər bir fiziki server bütün nüvələri təkrar emal etmək üçün kPHP qrupu işlədir (çünki kPHP tək yivlidir).

Məzmun Serveri

CS və ya Məzmun Serveri yaddaşdır. CS faylları saxlayan, həmçinin yüklənmiş faylları və əsas veb ön tərəfinin ona təyin etdiyi bütün növ fon sinxron tapşırıqları emal edən bir serverdir.

Faylları saxlayan on minlərlə fiziki serverimiz var. İstifadəçilər faylları yükləməyi sevirlər və biz onları saxlamağı və paylaşmağı sevirik. Bu serverlərin bəziləri xüsusi pu/pp serverləri tərəfindən bağlanır.

pu/s

VK-da şəbəkə sekmesini açsanız, pu/pp gördünüz.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

pu/pp nədir? Bir serveri digərinin ardınca bağlasaq, bağlanmış serverə fayl yükləmək və yükləmək üçün iki seçim var: birbaşa vasitəsilə http://cs100500.userapi.com/path və ya ara server vasitəsilə - http://pu.vk.com/c100500/path.

Pu foto yükləmənin tarixi adıdır, pp isə foto proxy-dir. Yəni bir server şəkilləri yükləmək üçün, digəri isə yükləmək üçündür. İndi nəinki fotolar yüklənir, həm də adı qorunub saxlanılıb.

Bu serverlər HTTPS sessiyalarını dayandırınprosessor yükünü yaddaşdan çıxarmaq üçün. Həmçinin, istifadəçi faylları bu serverlərdə işləndiyi üçün, bu maşınlarda saxlanılan daha az həssas məlumat, bir o qədər yaxşıdır. Məsələn, HTTPS şifrələmə açarları.

Maşınlar digər maşınlarımız tərəfindən bağlandığından, biz onlara “ağ” xarici İP-ləri verməməyə imkan verə bilərik və "boz" vermək. Beləliklə, biz IP hovuzunda qənaət etdik və maşınları kənar girişdən qorumağa zəmanət verdik - ona daxil olmaq üçün sadəcə IP yoxdur.

Paylaşılan IP-lər üzərində dayanıqlıq. Səhvlərə dözümlülük baxımından sxem eyni işləyir - bir neçə fiziki server ümumi fiziki IP-yə malikdir və onların qarşısındakı aparat sorğunun hara göndəriləcəyini seçir. Digər variantlar haqqında daha sonra danışacağam.

Mübahisəli məqam bu işdə olmasıdır müştəri daha az əlaqə saxlayır. Bir neçə maşın üçün eyni IP varsa - eyni host ilə: pu.vk.com və ya pp.vk.com, müştəri brauzerində bir hosta eyni vaxtda sorğuların sayına məhdudiyyət qoyulur. Ancaq hər yerdə mövcud olan HTTP/2 dövründə, bunun artıq o qədər də aktual olmadığına inanıram.

Sxemin açıq dezavantajı onun məcburiyyətində olmasıdır bütün trafiki pompalayın, başqa server vasitəsilə anbara gedir. Trafiki maşınlar vasitəsilə nəql etdiyimiz üçün eyni sxemdən istifadə edərək hələ də ağır trafiki, məsələn, videonu nəql edə bilmirik. Biz onu birbaşa ötürürük - xüsusi olaraq video üçün ayrı-ayrı anbarlar üçün ayrıca birbaşa əlaqə. Biz proxy vasitəsilə daha yüngül məzmun ötürürük.

Bir müddət əvvəl biz proxy-nin təkmilləşdirilmiş versiyasını əldə etdik. İndi sizə onların adilərdən necə fərqləndiyini və bunun nə üçün lazım olduğunu söyləyəcəyəm.

günəş

2017-ci ilin sentyabrında əvvəllər Sun-u satın almış Oracle, çox sayda Sun işçisini işdən çıxardı. Deyə bilərik ki, bu anda şirkət fəaliyyətini dayandırıb. Yeni sistem üçün ad seçərkən administratorlarımız bu şirkətin xatirəsini ehtiramla yad etmək qərarına gəldilər və yeni sistemə Günəş adını verdilər. Biz öz aramızda ona sadəcə “günəşlər” deyirik.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

pp bir neçə problem yaşadı. Qrup başına bir IP - səmərəsiz önbellek. Bir neçə fiziki server ümumi IP ünvanını paylaşır və sorğunun hansı serverə gedəcəyini idarə etmək üçün heç bir yol yoxdur. Buna görə də, eyni fayl üçün müxtəlif istifadəçilər gəlirsə, o zaman bu serverlərdə bir önbellek varsa, fayl hər bir serverin önbelleğinde bitir. Bu çox səmərəsiz bir sxemdir, lakin heç nə etmək mümkün deyil.

Nəticədə - məzmunu parçalaya bilmərik, çünki bu qrup üçün xüsusi server seçə bilmirik - onların ümumi IP-si var. Bəzi daxili səbəblərdən də bizdə var regionlarda belə serverlərin quraşdırılması mümkün deyildi. Onlar yalnız Sankt-Peterburqda dayandılar.

Günəşlərlə biz seçim sistemini dəyişdik. İndi bizdə anycast marşrutlaşdırma: dinamik marşrutlaşdırma, hər hansı bir yayım, özünü yoxlayan demon. Hər bir serverin öz fərdi IP, lakin ümumi alt şəbəkəsi var. Hər şey elə konfiqurasiya olunub ki, bir server uğursuz olarsa, trafik avtomatik olaraq eyni qrupun digər serverləri arasında yayılsın. İndi müəyyən bir server seçmək mümkündür, lazımsız keşləmə yoxdur, və etibarlılığa təsir etməmişdir.

Çəki dəstəyi. İndi ehtiyac olduqda müxtəlif gücə malik maşınlar quraşdıra bilərik, həmçinin müvəqqəti problemlər yarandıqda, yükü azaltmaq üçün işləyən "günəşlərin" çəkilərini dəyişdirin ki, onlar "istirahət etsinlər" və yenidən işə başlasınlar.

Məzmun id-si ilə paylaşma. Parçalanma ilə bağlı gülməli bir məqam: biz adətən məzmunu belə parçalayırıq ki, fərqli istifadəçilər eyni “günəş” vasitəsilə eyni fayla keçsinlər ki, onların ümumi keşi olsun.

Bu yaxınlarda “Clover” tətbiqini işə saldıq. Bu canlı yayımda onlayn viktorinadır, burada aparıcı suallar verir və istifadəçilər real vaxt rejimində cavab verir, seçimlər edir. Proqramda istifadəçilərin söhbət edə biləcəyi bir söhbət var. Eyni zamanda yayıma qoşula bilər 100 mindən çox insan. Onların hamısı bütün iştirakçılara göndərilən mesajlar yazır və mesajla birlikdə avatar da gəlir. Bir "günəş"də bir avatar üçün 100 min insan gəlirsə, o, bəzən bir bulud arxasında yuvarlana bilər.

Eyni fayl üçün sorğuların çoxalmasına tab gətirmək üçün, müəyyən bir məzmun növü üçün faylları bölgədəki bütün mövcud "günəşlər" arasında yayan axmaq bir sxemi işə salırıq.

İçəridən günəş

Nginx-də əks proxy, ya RAM-da və ya sürətli Optane/NVMe disklərində keş. Misal: http://sun4-2.userapi.com/c100500/path — dördüncü bölgədə, ikinci server qrupunda yerləşən “günəş”ə keçid. O, fiziki olaraq 100500 serverində olan yol faylını bağlayır.

Gizli yer

Memarlıq sxemimizə daha bir node əlavə edirik - keşləmə mühiti.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Aşağıda layout diaqramı var regional keşlər, onların təxminən 20-si var. Bunlar trafikin öz-özünə keçə biləcəyi önbelleklərin və "günəşlərin" yerləşdiyi yerlərdir.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Bu, multimedia məzmununun keşləşdirilməsidir; burada heç bir istifadəçi məlumatı saxlanılmır - sadəcə musiqi, video, fotoşəkillər.

İstifadəçinin bölgəsini müəyyən etmək üçün biz bölgələrdə elan edilən BGP şəbəkə prefikslərini toplayırıq. Geri qayıtma vəziyyətində, IP-ni prefikslərlə tapa bilməsək, geoip verilənlər bazasını da təhlil etməliyik. Bölgəni istifadəçinin IP-si ilə müəyyən edirik. Kodda istifadəçinin bir və ya bir neçə bölgəsinə - coğrafi baxımdan ən yaxın olduğu nöqtələrə baxa bilərik.

Necə işləyir?

Faylların populyarlığını bölgələrə görə hesablayırıq. İstifadəçinin yerləşdiyi bir sıra regional ön yaddaş və fayl identifikatoru var - biz bu cütü götürürük və hər yükləmə ilə reytinqi artırırıq.

Eyni zamanda, cinlər - bölgələrdəki xidmətlər - vaxtaşırı API-yə gəlir və deyirlər: “Mən filankəsəm, mənim bölgəmdə hələ məndə olmayan ən populyar faylların siyahısını verin. ” API, reytinqə görə çeşidlənmiş bir dəstə fayl təqdim edir, demon onları yükləyir, bölgələrə aparır və faylları oradan çatdırır. Bu, pu/pp və Sun arasında keşlərdən əsas fərqdir: onlar bu fayl keşdə olmasa belə, dərhal faylı özləri vasitəsilə verirlər və keş əvvəlcə faylı özünə yükləyir, sonra isə onu geri verməyə başlayır.

Bu vəziyyətdə alırıq məzmun istifadəçilərə daha yaxındır və şəbəkə yükünün yayılması. Məsələn, yalnız Moskva keşindən biz pik saatlarda 1 Tbit/s-dən çox yayırıq.

Ancaq problemlər var - önbellek serverləri rezin deyil. Super populyar məzmun üçün bəzən ayrı bir server üçün kifayət qədər şəbəkə yoxdur. Keş serverlərimiz 40-50 Gbit/s-dir, lakin belə bir kanalı tamamilə bağlayan məzmun var. Bölgədə populyar faylların birdən çox nüsxəsinin saxlanmasını həyata keçirməyə doğru irəliləyirik. Ümid edirəm ki, ilin sonuna kimi biz bunu həyata keçirəcəyik.

Ümumi arxitekturaya baxdıq.

  • Sorğuları qəbul edən ön serverlər.
  • Sorğuları emal edən arxa tərəflər.
  • İki növ proksi ilə bağlanan anbarlar.
  • Regional keşlər.

Bu diaqramda nə çatışmır? Əlbəttə ki, məlumatları saxladığımız verilənlər bazaları.

Verilənlər bazaları və ya mühərriklər

Biz onları verilənlər bazası deyil, mühərriklər - Mühərriklər adlandırırıq, çünki praktiki olaraq ümumi qəbul edilmiş mənada verilənlər bazamız yoxdur.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Bu zəruri tədbirdir. Bu, ona görə baş verdi ki, 2008-2009-cu illərdə, VK-nın populyarlığının kəskin artması zamanı layihə tamamilə MySQL və Memcache üzərində işləyirdi və problemlər var idi. MySQL faylları sındırmağı və xarab etməyi sevirdi, bundan sonra bərpa olunmayacaqdı və Memcache tədricən performansını itirdi və yenidən işə salınmalı oldu.

Məlum olub ki, getdikcə populyarlaşan layihədə məlumatları korlayan davamlı yaddaş və yavaşlayan keş var. Belə şəraitdə böyüyən bir layihə hazırlamaq çətindir. Layihənin diqqət mərkəzində olan kritik şeyləri öz velosipedlərimizdə yenidən yazmağa cəhd etmək qərara alındı.

Həll uğurlu oldu. Bunu etmək imkanı da var idi, həm də həddindən artıq zərurət idi, çünki o zaman başqa miqyaslı üsullar yox idi. Bir dəstə verilənlər bazası yox idi, NoSQL hələ mövcud deyildi, yalnız MySQL, Memcache, PostrgreSQL var idi - vəssalam.

Universal əməliyyat. İnkişafa C tərtibatçılarından ibarət komandamız rəhbərlik etdi və hər şey ardıcıl şəkildə edildi. Mühərrikdən asılı olmayaraq, onların hamısı diskə yazılmış təxminən eyni fayl formatına, eyni işəsalma parametrlərinə, siqnalları eyni şəkildə emal etmiş və kənar vəziyyətlər və problemlər zamanı təxminən eyni davranmışdılar. Mühərriklərin böyüməsi ilə idarəçilər üçün sistemi idarə etmək rahatdır - saxlanılmalı olan heç bir zoopark yoxdur və onlar hər bir yeni üçüncü tərəf verilənlər bazasını necə idarə etməyi yenidən öyrənməlidirlər ki, bu da tez və rahat şəkildə artırmağa imkan verdi. onların sayı.

Mühərriklərin növləri

Komanda kifayət qədər çox mühərrik yazdı. Bunlardan yalnız bəziləri bunlardır: dost, göstərişlər, şəkil, ipdb, məktublar, siyahılar, qeydlər, memcached, meowdb, xəbərlər, nostradamus, foto, çalğı siyahıları, pmemcached, sandbox, axtarış, yaddaş, bəyənmələr, tapşırıqlar,…

Xüsusi məlumat strukturu tələb edən və ya atipik sorğuları emal edən hər bir tapşırıq üçün C komandası yeni mühərrik yazır. Niyə də yox.

Ayrı bir mühərrikimiz var memcached, adi birinə bənzəyir, lakin bir dəstə ləzzətli və yavaşlamayan. ClickHouse deyil, həm də işləyir. Ayrı-ayrılıqda mövcuddur pmemcached - Mi davamlı memcached, bu da məlumatları diskdə saxlaya bilər, üstəlik, yenidən başladıqda məlumatları itirməmək üçün RAM-a uyğundur. Fərdi tapşırıqlar üçün müxtəlif mühərriklər var: növbələr, siyahılar, dəstlər - layihəmizin tələb etdiyi hər şey.

Kümələr

Kod baxımından, mühərrikləri və ya verilənlər bazalarını proseslər, obyektlər və ya nümunələr kimi düşünməyə ehtiyac yoxdur. Kod xüsusi olaraq qruplarla, mühərrik qrupları ilə işləyir - hər klaster üçün bir növ. Deyək ki, memcached klaster var - bu, sadəcə bir qrup maşındır.

Kodun ümumiyyətlə serverlərin fiziki yerini, ölçüsünü və ya sayını bilməsinə ehtiyac yoxdur. O, müəyyən identifikatordan istifadə edərək klasterə gedir.

Bunun işləməsi üçün kod və mühərriklər arasında yerləşən daha bir obyekt əlavə etməlisiniz - proxy.

RPC proxy

Proksi birləşdirən avtobus, demək olar ki, bütün saytın işlədiyi. Eyni zamanda bizdə də var xidmət kəşfi yoxdur — əvəzinə, bu proksi üçün bütün klasterlərin və bu klasterin bütün qırıqlarının yerini bilən konfiqurasiya var. Adminlər belə edir.

Proqramçılar bunun nə qədər, harada və nəyə başa gəldiyini heç maraqlandırmırlar - onlar sadəcə klasterə gedirlər. Bu, bizə çox şey verir. Sorğunu qəbul edərkən, proksi harada olduğunu bilməklə sorğunu yönləndirir - bunu özü müəyyən edir.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Bu halda proksi xidmətin nasazlığından qorunma nöqtəsidir. Bəzi mühərrik yavaşlayırsa və ya çökürsə, proksi bunu başa düşür və müştəri tərəfinə müvafiq olaraq cavab verir. Bu, vaxt aşımını aradan qaldırmağa imkan verir - kod mühərrikin cavab verməsini gözləmir, lakin onun işləmədiyini başa düşür və bir şəkildə fərqli davranmalıdır. Kod verilənlər bazalarının həmişə işləməməsi üçün hazırlanmalıdır.

Xüsusi tətbiqlər

Bəzən biz hələ də mühərrik kimi bir növ qeyri-standart həllə sahib olmaq istəyirik. Eyni zamanda, mühərriklərimiz üçün xüsusi olaraq yaradılmış hazır rpc-proxy-dən istifadə etməmək, tapşırıq üçün ayrıca proksi etmək qərara alındı.

Hələ də burada və orada mövcud olan MySQL üçün db-proxy istifadə edirik və ClickHouse üçün - Pişik evi.

Ümumiyyətlə belə işləyir. Müəyyən bir server var, o, kPHP, Go, Python işləyir - ümumiyyətlə, bizim RPC protokolumuzdan istifadə edə bilən istənilən kod. Kod yerli olaraq RPC proksisində işləyir - kodun yerləşdiyi hər bir server öz yerli proksisini idarə edir. Tələb edildikdə, proxy hara getməyi başa düşür.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Bir mühərrik digərinə keçmək istəyirsə, qonşu olsa belə, o, proxy-dən keçir, çünki qonşu başqa bir məlumat mərkəzində ola bilər. Mühərrik özündən başqa bir şeyin yerini bilməyə güvənməməlidir - bu bizim standart həllimizdir. Amma istisnalar var təbii ki :)

Bütün mühərriklərin işlədiyi TL-sxem nümunəsi.

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;

Bu, ən yaxın analoqu olan ikili protokoldur protobuf. Sxem isteğe bağlı sahələri, mürəkkəb növləri - daxili skalyarların genişləndirilməsini və sorğuları təsvir edir. Hər şey bu protokola uyğun işləyir.

TCP/UDP üzərindən TL üzərində RPC... UDP?

TL sxeminin üstündə işləyən mühərrik sorğularını yerinə yetirmək üçün RPC protokolumuz var. Bütün bunlar TCP/UDP bağlantısı üzərində işləyir. TCP başa düşüləndir, lakin niyə tez-tez UDP lazımdır?

UDP kömək edir serverlər arasında çox sayda əlaqə problemindən qaçın. Hər bir serverdə RPC proxy-si varsa və ümumiyyətlə, istənilən mühərrikə gedə bilirsə, onda hər serverə on minlərlə TCP bağlantısı var. Yük var, amma faydasızdır. UDP vəziyyətində bu problem mövcud deyil.

Lazımsız TCP əl sıxması yoxdur. Bu tipik bir problemdir: yeni bir mühərrik və ya yeni bir server işə salındıqda, bir anda bir çox TCP bağlantısı qurulur. Kiçik yüngül sorğular üçün, məsələn, UDP yükü, kod və mühərrik arasındakı bütün əlaqədir iki UDP paketi: biri bir istiqamətə, ikincisi digər tərəfə uçur. Bir gediş - və kod mühərrikdən əl sıxmadan cavab aldı.

Bəli, hər şey sadəcə işləyir paket itkisinin çox kiçik bir faizi ilə. Protokolun təkrar ötürmələr və fasilələr üçün dəstəyi var, lakin çox şey itirsək, demək olar ki, TCP alacağıq, bu da sərfəli deyil. Biz UDP-ni okeanlar arasında aparmırıq.

Bizdə minlərlə belə server var və sxem eynidir: hər bir fiziki serverdə mühərriklər paketi quraşdırılıb. Onlar bloklanmadan mümkün qədər tez işləmək üçün əsasən tək yivlidir və tək yivli həllər kimi parçalanır. Eyni zamanda, bu mühərriklərdən daha etibarlı bir şeyimiz yoxdur və məlumatların davamlı saxlanmasına çox diqqət yetirilir.

Davamlı məlumat saxlama

Mühərriklər binloglar yazır. Binlog, sonunda vəziyyətin və ya məlumatın dəyişməsi üçün hadisənin əlavə edildiyi bir fayldır. Müxtəlif həllərdə fərqli adlanır: ikili jurnal, WAL, AOF, amma prinsip eynidir.

Mühərrikin yenidən işə salınması zamanı uzun illər ərzində bütün binlogu yenidən oxumasının qarşısını almaq üçün mühərriklər yazır snapshots - cari vəziyyət. Lazım olsa əvvəl ondan oxuyurlar, sonra binlogdan oxuyub bitirirlər. Bütün binloglar eyni ikili formatda - TL sxeminə uyğun olaraq yazılır ki, idarəçilər öz alətlərindən istifadə edərək onları bərabər şəkildə idarə edə bilsinlər. Snapshotlara belə ehtiyac yoxdur. Kimin şəklinin int olduğunu, mühərrikin sehrini və hansı gövdənin heç kim üçün vacib olmadığını göstərən ümumi bir başlıq var. Bu, görüntünü qeydə alan mühərrikdə problemdir.

Əməliyyat prinsipini tez təsvir edəcəyəm. Mühərrikin işlədiyi bir server var. Yazmaq üçün yeni boş binloq açır və onu dəyişdirmək üçün hadisə yazır.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Nə vaxtsa o, ya özü şəkil çəkdirmək qərarına gəlir, ya da siqnal alır. Server yeni fayl yaradır, onun bütün vəziyyətini ona yazır, cari binlog ölçüsünü - ofset - faylın sonuna əlavə edir və daha sonra yazmağa davam edir. Yeni binlog yaradılmayıb.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Mühərrik yenidən işə salındıqda diskdə həm binlog, həm də snapshot olacaq. Mühərrik bütün görüntünü oxuyur və müəyyən bir nöqtədə vəziyyətini qaldırır.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Snapshot yaradıldığı zaman olan mövqeyi və binloqun ölçüsünü oxuyur.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Cari vəziyyəti əldə etmək üçün binloqun sonunu oxuyur və sonrakı hadisələri yazmağa davam edir. Bu sadə sxemdir, bütün mühərriklərimiz ona uyğun işləyir.

Məlumatların təkrarlanması

Nəticədə məlumatların təkrarlanması bizim bəyanata əsaslanır — biz binlogda heç bir səhifə dəyişikliyi deyil, məhz bunu yazırıq dəyişiklik tələbləri. Şəbəkə üzərindən gələnlərə çox bənzəyir, yalnız bir qədər dəyişdirilib.

Eyni sxem yalnız təkrarlama üçün deyil, həm də istifadə olunur ehtiyat nüsxələri yaratmaq üçün. Mühərrikimiz var - binloga yazan bir yazı ustası. Adminlərin quraşdırdığı hər hansı başqa yerdə bu binlog kopyalanır və budur - ehtiyat nüsxəmiz var.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Lazım olsa replika oxuCPU oxu yükünü azaltmaq üçün oxu mühərriki sadəcə işə salınır, o, binlogun sonunu oxuyur və bu əmrləri yerli olaraq yerinə yetirir.

Burada gecikmə çox kiçikdir və replikanın ustadan nə qədər geri qaldığını öyrənmək mümkündür.

RPC proksisində məlumat paylaşma

Sharding necə işləyir? Proksi hansı klaster parçasının göndəriləcəyini necə başa düşür? Kodda deyilmir: "15 qəlpəyə göndər!" - yox, bunu proxy edir.

Ən sadə sxem firstint-dir — sorğuda birinci nömrə.

get(photo100_500) => 100 % N.

Bu, sadə memcached mətn protokolu üçün bir nümunədir, lakin, əlbəttə ki, sorğular mürəkkəb və strukturlaşdırılmış ola bilər. Nümunə sorğuda ilk nömrəni, klaster ölçüsünə bölündükdə qalanı götürür.

Bu, bir qurumun məlumat lokallığına sahib olmaq istədiyimiz zaman faydalıdır. Tutaq ki, 100 istifadəçi və ya qrup identifikatorudur və biz mürəkkəb sorğular üçün bir obyektin bütün məlumatlarının bir parçada olmasını istəyirik.

Əgər sorğuların çoxluqda necə yayıldığı bizi maraqlandırmırsa, başqa bir seçim var - bütün parçanı hashing.

hash(photo100_500) => 3539886280 % N

Biz həmçinin hash, bölmənin qalan hissəsini və parça nömrəsini alırıq.

Bu seçimlərin hər ikisi yalnız klasterin ölçüsünü artırdıqda onu bölmək və ya dəfələrlə artıracağımıza hazır olduğumuz halda işləyir. Məsələn, 16 parçamız var idi, çatışmır, daha çox istəyirik - dayanmadan 32-ni etibarlı şəkildə əldə edə bilərik. Dəfələrlə deyil, artırmaq istəsək, fasilələr olacaq, çünki itkisiz hər şeyi dəqiq şəkildə bölə bilməyəcəyik. Bu seçimlər faydalıdır, lakin həmişə deyil.

İstənilən sayda server əlavə etmək və ya silmək lazımdırsa, istifadə edirik Ketama halqasında ardıcıl hashing. Ancaq eyni zamanda, məlumatların lokalizasiyasını tamamilə itiririk; sorğunu klasterə birləşdirməliyik ki, hər bir parça öz kiçik cavabını qaytarsın və sonra cavabları proxy ilə birləşdirin.

Super spesifik istəklər var. Bu belə görünür: RPC proksi sorğunu qəbul edir, hansı klasterə getməyi təyin edir və parçanı müəyyən edir. Sonra ya yazı ustaları var, ya da klasterdə replika dəstəyi varsa, o, tələb əsasında replikaya göndərilir. Proksi bütün bunları edir.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Qeydlər

Logları bir neçə yolla yazırıq. Ən sadə və aydındır memcache-ə qeydlər yazın.

ring-buffer: prefix.idx = line

Əsas prefiks var - jurnalın adı, bir xətt və bu jurnalın ölçüsü var - sətirlərin sayı. Biz 0-dan sətirlərin sayına minus 1-ə qədər təsadüfi bir ədəd götürürük. Memcache-dəki açar bu təsadüfi nömrə ilə birləşdirilən prefiksdir. Jurnal xəttini və cari vaxtı dəyərə saxlayırıq.

Günlükləri oxumaq lazım olduqda, həyata keçiririk Multi Get bütün açarları vaxta görə sıralayır və beləliklə real vaxt rejimində istehsal jurnalını əldə edir. Sxem, istehsalda bir şeyi real vaxt rejimində, heç bir şeyi pozmadan, dayandırmadan və ya digər maşınlara trafikə icazə vermədən debug etmək lazım olduqda istifadə olunur, lakin bu jurnal uzun sürmür.

Günlüklərin etibarlı saxlanması üçün bir mühərrikimiz var logs-mühərriki. Məhz buna görə yaradılmış və çoxlu sayda klasterdə geniş istifadə olunur. Bildiyim ən böyük klaster 600 TB qablaşdırılmış logları saxlayır.

Mühərrik çox köhnədir, artıq 6-7 yaşı olan klasterlər var. Bununla əlaqədar həll etməyə çalışdığımız problemlər var, məsələn, logları saxlamaq üçün ClickHouse-dan fəal şəkildə istifadə etməyə başladıq.

ClickHouse-da qeydlərin toplanması

Bu diaqram mühərriklərimizə necə girdiyimizi göstərir.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Yerli olaraq RPC vasitəsilə RPC-proksiyə gedən kod var və o, mühərrikə hara getməli olduğunu başa düşür. ClickHouse-da qeydlər yazmaq istəyiriksə, bu sxemdə iki hissəni dəyişdirməliyik:

  • bəzi mühərrikləri ClickHouse ilə əvəz edin;
  • ClickHouse-a daxil ola bilməyən RPC proksisini RPC vasitəsilə mümkün olan bəzi həllər ilə əvəz edin.

Mühərrik sadədir - biz onu server və ya ClickHouse ilə serverlər klasteri ilə əvəz edirik.

ClickHouse-a getmək üçün biz etdik Pişik Evi. Birbaşa KittenHouse-dan ClickHouse-a getsək, bunun öhdəsindən gəlməyəcək. İstəklər olmadan belə, çox sayda maşının HTTP bağlantılarından əlavə edir. Sxemin işləməsi üçün ClickHouse ilə serverdə yerli əks proxy qaldırılır, lazımi həcmdə birləşmələrə tab gətirə biləcək şəkildə yazılmışdır. O, həmçinin öz daxilindəki məlumatları nisbətən etibarlı şəkildə bufer edə bilər.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Bəzən biz RPC sxemini qeyri-standart həllərdə, məsələn, nginx-də tətbiq etmək istəmirik. Buna görə KittenHouse UDP vasitəsilə logları qəbul etmək imkanına malikdir.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Əgər logların göndəricisi və alıcısı eyni maşında işləyirsə, o zaman yerli host daxilində UDP paketini itirmə ehtimalı olduqca aşağıdır. Üçüncü tərəf həllində RPC-nin tətbiqi ehtiyacı və etibarlılıq arasında kompromis olaraq biz sadəcə UDP göndərilməsindən istifadə edirik. Bu sxemə daha sonra qayıdacağıq.

Monitorinq

İki növ qeydimiz var: administratorlar tərəfindən öz serverlərində toplananlar və tərtibatçılar tərəfindən koddan yazılanlar. Onlar iki növ göstəriciyə uyğundur: sistem və məhsul.

Sistem ölçüləri

Bütün serverlərimizdə işləyir netdata, statistik məlumatları toplayan və göndərən Qrafit Karbon. Buna görə, ClickHouse, məsələn, Whisper deyil, saxlama sistemi kimi istifadə olunur. Lazım gələrsə, birbaşa ClickHouse-dan oxuya və ya istifadə edə bilərsiniz Qrafana ölçülər, qrafiklər və hesabatlar üçün. Tərtibatçılar olaraq Netdata və Grafana-ya kifayət qədər çıxışımız var.

Məhsul göstəriciləri

Rahatlıq üçün çox şey yazdıq. Məsələn, başqa yerə göndərilən Statistikaya Counts, UniqueCounts dəyərlərini yazmağa imkan verən bir sıra adi funksiyalar var.

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

$stats = statlogsStatData($params)

Sonradan biz çeşidləmə və qruplaşdırma filtrlərindən istifadə edə və statistikadan istədiyimiz hər şeyi edə bilərik - qrafiklər qura, Watchdog-ları konfiqurasiya edə bilərik.

Çox yazırıq çoxlu ölçülər hadisələrin sayı gündə 600 milyarddan 1 trilyona qədərdir. Bununla belə, biz onları saxlamaq istəyirik ən azı bir neçə ilmetriklərdəki meylləri anlamaq üçün. Bunların hamısını bir araya gətirmək hələ həll etmədiyimiz böyük problemdir. Mən sizə son bir neçə ildə necə işlədiyini söyləyəcəyəm.

Bu ölçüləri yazan funksiyalarımız var yerli yaddaş yaddaşınagirişlərin sayını azaltmaq üçün. Qısa müddətdə bir dəfə yerli olaraq işə salındı stats-daemon bütün qeydləri toplayır. Sonra, iblis ölçüləri iki qat serverə birləşdirir log-kollektorlar, bir dəstə maşınımızın statistikasını toplayır ki, onların arxasındakı təbəqə ölməsin.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Lazım gələrsə, biz birbaşa logs-kollektorlara yaza bilərik.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Lakin stas-daemomdan yan keçərək, koddan birbaşa kollektorlara yazmaq zəif miqyaslı bir həlldir, çünki bu, kollektorun yükünü artırır. Həll yalnız nədənsə maşında memcache stats-daemonunu qaldıra bilməsək və ya qəzaya uğrayıb birbaşa getdiyimiz halda uyğundur.

Sonra, log-kollektorlar statistikanı birləşdirir meowDB - bu bizim verilənlər bazamızdır, o da ölçüləri saxlaya bilər.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Sonra koddan ikili “yaxın SQL” seçimləri edə bilərik.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Sınaq

2018-ci ilin yayında daxili hakaton keçirdik və diaqramın qırmızı hissəsini ClickHouse-da ölçüləri saxlaya bilən bir şeylə əvəz etməyə çalışmaq ideyası yarandı. ClickHouse-da qeydlərimiz var - niyə cəhd etməyək?

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

KittenHouse vasitəsilə loglar yazan bir sxemimiz var idi.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Biz qərara aldıq diaqrama başqa “*Ev” əlavə edin, kodumuz onları UDP vasitəsilə yazdığı üçün formatda dəqiq ölçüləri alacaq. Sonra bu *House onları KittenHouse-un anladığı loglar kimi əlavələrə çevirir. O, bu qeydləri oxumağı bacarmalı olan ClickHouse-a mükəmməl şəkildə çatdıra bilər.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Memcache, stats-daemon və logs-collectors verilənlər bazası olan sxem bununla əvəz edilmişdir.

VKontakte memarlığı və işi ilə bağlı tez-tez verilən suallar

Memcache, stats-daemon və logs-collectors verilənlər bazası olan sxem bununla əvəz edilmişdir.

  • StatsHouse-da yerli olaraq yazılmış koddan bir göndəriş var.
  • StatsHouse, artıq SQL əlavələrinə çevrilmiş UDP ölçülərini KittenHouse-a toplu olaraq yazır.
  • KittenHouse onları ClickHouse-a göndərir.
  • Əgər biz onları oxumaq istəyiriksə, onda biz StatsHouse-dan yan keçməklə - adi SQL-dən istifadə edərək birbaşa ClickHouse-dan oxuyuruq.

Hələ də var bir sınaq, amma necə çıxdığını bəyənirik. Sxemlə bağlı problemləri həll etsək, bəlkə də tamamilə ona keçəcəyik. Şəxsən mən buna ümid edirəm.

Sxem dəmirə qənaət etmir. Daha az serverə ehtiyac var, yerli stats-demonlar və log-kollektorlara ehtiyac yoxdur, lakin ClickHouse cari sxemdəkilərdən daha böyük server tələb edir. Daha az server tələb olunur, lakin onlar daha bahalı və daha güclü olmalıdır.

Yerləşdirmək

Əvvəlcə PHP-nin tətbiqinə nəzər salaq. -da inkişaf edirik git: istifadə edin GitLab и TeamCity yerləşdirilməsi üçün. İnkişaf filialları master filiala, sınaq üçün masterdan səhnələşdirməyə və səhnələşdirmədən istehsala birləşdirilir.

Yerləşdirmədən əvvəl cari istehsal filialı və əvvəlkisi götürülür və onlarda fərq faylları nəzərdən keçirilir - dəyişikliklər: yaradılmış, silinmiş, dəyişdirilmişdir. Bu dəyişiklik bütün server donanmamızda dəyişiklikləri tez bir zamanda təkrarlaya bilən xüsusi copyfast mühərrikinin binlogunda qeyd olunur. Burada istifadə olunan birbaşa surət çıxarmaq deyil, amma qeybətin təkrarlanması, bir server dəyişiklikləri ən yaxın qonşularına göndərdikdə, onları qonşularına və s. Bu, bütün donanma üzrə kodu onlarla və saniyə vahidləri ərzində yeniləməyə imkan verir. Dəyişiklik yerli replikaya çatdıqda, bu yamaları onun üçün tətbiq edir yerli fayl sistemi. Geri çəkilmə də eyni sxemə uyğun olaraq həyata keçirilir.

Biz həmçinin kPHP-ni çox yerləşdiririk və onun da öz inkişafı var git yuxarıdakı diaqrama görə. Bundan sonra HTTP server binar, onda biz fərq yarada bilmərik - buraxılış binarının çəkisi yüzlərlə MB təşkil edir. Buna görə də, burada başqa bir seçim var - versiya yazılır binlog copyfast. Hər qurma ilə artır və geri çəkilmə zamanı da artır. Versiya serverlərə təkrarlanır. Yerli copyfastlar binlog-a yeni versiyanın daxil olduğunu görürlər və eyni dedi-qodu replikasiyası ilə master serverimizi yormadan, yükü diqqətlə şəbəkəyə yayaraq, binarın ən son versiyasını özləri üçün götürürlər. Sonrakı zərif yenidən işə salın yeni versiya üçün.

Əsasən ikili olan mühərriklərimiz üçün sxem çox oxşardır:

  • git master filialı;
  • ikili .deb;
  • versiya binlog copyfast-a yazılır;
  • serverlərə təkrarlanır;
  • server təzə .dep çıxarır;
  • dpkg -i;
  • yeni versiyaya zərif relaunch.

Fərq ondadır ki, bizim binar arxivlərdə paketlənib .deb, və onları pompalayarkən dpkg -i sistemə yerləşdirilir. Niyə kPHP binar kimi yerləşdirilir və mühərriklər dpkg kimi yerləşdirilir? Bu belə oldu. İşləyir - ona toxunmayın.

Faydalı linklər:

Aleksey Akuloviç Proqram Komitəsinin tərkibində kömək edənlərdən biridir PHP Rusiya Mayın 17-də PHP tərtibatçıları üçün son zamanların ən böyük hadisəsi olacaq. Görün nə gözəl kompüterimiz var, nə natiqlər (onlardan ikisi PHP nüvəsini inkişaf etdirir!) - PHP yazsanız, qaçıra bilməyəcəyiniz bir şey kimi görünür.

Mənbə: www.habr.com

Добавить комментарий