NewSQL = NoSQL+ACID

NewSQL = NoSQL+ACID
Bu yaxınlara qədər Odnoklassniki-də real vaxt rejimində işlənmiş təxminən 50 TB məlumat SQL Serverdə saxlanılırdı. Belə bir həcm üçün SQL DBMS-dən istifadə edərək sürətli və etibarlı, hətta xətaya dözümlü məlumat mərkəzinə girişi təmin etmək demək olar ki, mümkün deyil. Adətən belə hallarda NoSQL anbarlarından biri istifadə olunur, lakin hər şeyi NoSQL-ə köçürmək olmur: bəzi qurumlar ACID əməliyyat zəmanətlərini tələb edir.

Bu, bizi NewSQL yaddaşından, yəni NoSQL sistemlərinin nasazlıqlara dözümlülüyünü, miqyasını və performansını təmin edən, lakin eyni zamanda klassik sistemlərə tanış olan ACID zəmanətlərini özündə saxlayan DBMS-dən istifadə etməyə gətirib çıxardı. Bu yeni sinfin işləyən sənaye sistemləri azdır, ona görə də biz belə bir sistemi özümüz tətbiq etdik və kommersiya istifadəsinə verdik.

Necə işləyir və nə baş verdi - kəsik altında oxuyun.

Bu gün Odnoklassniki-nin aylıq auditoriyası 70 milyondan çox unikal ziyarətçidir. Biz ilk beşliyə daxil olun dünyanın ən böyük sosial şəbəkələri və istifadəçilərin ən çox vaxt keçirdikləri ilk iyirmi saytda. "OK" infrastrukturu çox yüksək yükləri idarə edir: hər cəbhə üçün bir milyondan çox HTTP sorğusu/san. 8000 ədəddən çox olan server parkının hissələri bir-birinə yaxın - dörd Moskva məlumat mərkəzində yerləşir ki, bu da onların arasında 1 ms-dən az şəbəkə gecikməsini təmin etməyə imkan verir.

Biz 2010-cu ildən 0.6 versiyasından başlayaraq Cassandra-dan istifadə edirik. Bu gün bir neçə onlarla klaster fəaliyyət göstərir. Ən sürətli klaster saniyədə 4 milyondan çox əməliyyat emal edir, ən böyüyü isə 260 TB saxlayır.

Bununla belə, bunların hamısı saxlamaq üçün istifadə edilən adi NoSQL klasterləridir zəif əlaqələndirilmişdir data. Biz həmçinin Odnoklassniki yaranandan bəri istifadə olunan əsas ardıcıl yaddaşı, Microsoft SQL Serveri əvəz etmək istədik. Yaddaş 300-dən çox SQL Server Standard Edition maşınından ibarət idi, bu maşınlarda 50 TB məlumat - biznes subyektləri var idi. Bu məlumatlar ACID əməliyyatlarının bir hissəsi kimi dəyişdirilir və tələb olunur yüksək tutarlılıq.

Məlumatları SQL Server qovşaqları arasında yaymaq üçün həm şaquli, həm də üfüqi istifadə etdik bölmək (parçalanma). Tarixən biz sadə məlumatların bölüşdürülməsi sxemindən istifadə etdik: hər bir obyekt bir işarə ilə əlaqələndirilirdi - obyekt ID-nin funksiyası. Eyni işarəyə malik olan obyektlər eyni SQL serverinə yerləşdirildi. Master-detal əlaqəsi elə həyata keçirildi ki, master və uşaq qeydlərinin işarələri həmişə üst-üstə düşür və eyni serverdə yerləşir. Sosial şəbəkədə demək olar ki, bütün qeydlər istifadəçi adından yaradılır, yəni bir funksional alt sistem daxilində bütün istifadəçi məlumatları bir serverdə saxlanılır. Yəni, bir iş əməliyyatı demək olar ki, həmişə bir SQL serverinin cədvəllərini əhatə edir ki, bu da istifadə etməyə ehtiyac olmadan yerli ACID əməliyyatlarından istifadə edərək məlumatların ardıcıllığını təmin etməyə imkan verir. yavaş və etibarsız paylanmış ACID əməliyyatları.

Sharding və SQL-i sürətləndirmək sayəsində:

  • Biz Xarici açar məhdudiyyətlərindən istifadə etmirik, çünki parçalanma zamanı obyekt identifikatoru başqa serverdə yerləşə bilər.
  • DBMS CPU-nun əlavə yüklənməsi səbəbindən biz saxlanılan prosedurlardan və tetikleyicilərdən istifadə etmirik.
  • Yuxarıda göstərilənlərin hamısına və diskdən çoxlu təsadüfi oxunmalara görə biz JOIN-lərdən istifadə etmirik.
  • Tranzaksiyadan kənarda biz çıxılmaz vəziyyətləri azaltmaq üçün Read Uncommitted izolyasiya səviyyəsindən istifadə edirik.
  • Biz yalnız qısa əməliyyatlar həyata keçiririk (orta hesabla 100 ms-dən az).
  • Çoxlu sayda çıxılmaz vəziyyətə görə çox sıralı YENİLƏNİB və SİL funksiyalarından istifadə etmirik - biz bir anda yalnız bir qeydi yeniləyirik.
  • Sorğular həmişə yalnız indekslərlə yerinə yetirilir - tam cədvəl skan planı olan sorğu bizim üçün verilənlər bazasının həddindən artıq yüklənməsi və onun uğursuzluğu deməkdir.

Bu addımlar bizə SQL serverlərinin demək olar ki, maksimum performansını sıxışdırmağa imkan verdi. Ancaq problemlər getdikcə daha da artdı. Gəlin onlara nəzər salaq.

SQL ilə bağlı problemlər

  • Öz-özünə yazılmış parçalanmadan istifadə etdiyimizə görə, yeni parçaların əlavə edilməsi idarəçilər tərəfindən əl ilə həyata keçirilirdi. Bütün bu müddət ərzində genişlənə bilən məlumat replikaları sorğulara xidmət etməmişdir.
  • Cədvəldəki qeydlərin sayı artdıqca daxiletmə və dəyişdirmə sürəti azalır, mövcud cədvələ indekslər əlavə edilərkən sürət dəfələrlə azalır, indekslərin yaradılması və yenidən yaradılması iş vaxtını alır.
  • İstehsalda az miqdarda SQL Server üçün Windows-un olması infrastrukturun idarə edilməsini çətinləşdirir

Amma əsas problem budur

xətaya dözümlülük

Klassik SQL Server zəif səhvlərə dözümlüdür. Tutaq ki, sizin yalnız bir verilənlər bazası serveriniz var və o, hər üç ildən bir uğursuz olur. Hazırda sayt 20 dəqiqə işləmir, bu məqbuldur. Əgər 64 serveriniz varsa, o zaman sayt hər üç həftədə bir dəfə bağlanır. Əgər 200 serveriniz varsa, o zaman sayt hər həftə işləmir. Bu problemdir.

SQL serverinin nasazlıqlara dözümlülüyünü yaxşılaşdırmaq üçün nə etmək olar? Vikipediya bizi qurmağa dəvət edir yüksək əlçatan klaster: komponentlərdən hər hansı birinin nasazlığı halında ehtiyat nüsxə olduğu halda.

Bunun üçün bahalı avadanlıq parkı tələb olunur: çoxsaylı təkrarlama, fiber optika, ümumi saxlama və ehtiyatın daxil edilməsi etibarlı işləmir: daxilolmaların təxminən 10% -i əsas qovşağın arxasında bir qatar ilə ehtiyat qovşağının uğursuzluğu ilə başa çatır.

Lakin belə yüksək əlçatan klasterin əsas çatışmazlığı onun yerləşdiyi məlumat mərkəzinin sıradan çıxması halında əlçatanlığın sıfır olmasıdır. Odnoklassniki-də dörd məlumat mərkəzi var və tam nasazlıq halında onlardan birində işləməyi təmin etməliyik.

Bunun üçün istifadə edə bilərik Multi Master SQL Serverə quraşdırılmış replikasiya. Bu həll proqram təminatının dəyərinə görə daha baha başa gəlir və məşhur replikasiya problemlərindən əziyyət çəkir - sinxron replikasiya ilə gözlənilməz əməliyyat gecikmələri və asinxron ilə replikasiyanın (və nəticədə itirilmiş modifikasiyaların) tətbiqində gecikmələr. nəzərdə tutulur münaqişənin əl ilə həlli bu seçimi bizim üçün tamamilə uyğunsuz edir.

Bütün bu problemlər köklü həll tələb edirdi və biz onların ətraflı təhlilinə keçdik. Burada biz SQL Serverin əsasən nə etdiyi - əməliyyatlarla tanış olmalıyıq.

Sadə əməliyyat

Tətbiq olunan SQL proqramçısı nöqteyi-nəzərindən ən sadə əməliyyatı nəzərdən keçirək: alboma şəkil əlavə etmək. Albomlar və fotoşəkillər müxtəlif boşqablarda saxlanılır. Albomda ictimai foto sayğac var. Sonra belə bir əməliyyat aşağıdakı addımlara bölünür:

  1. Albomu açarla bloklayırıq.
  2. Fotoşəkil cədvəlində bir giriş yaradın.
  3. Fotonun ictimai statusu varsa, o zaman albomdakı ictimai fotoşəkillərin sayğacını yığırıq, qeydi yeniləyirik və əməliyyatı həyata keçiririk.

Və ya psevdokodda:

TX.start("Albums", id);
Album album = albums.lock(id);
Photo photo = photos.create(…);

if (photo.status == PUBLIC ) {
    album.incPublicPhotosCount();
}
album.update();

TX.commit();

Görürük ki, iş əməliyyatı üçün ən çox yayılmış ssenari verilənlər bazasından məlumatları proqram serverinin yaddaşına oxumaq, nəyisə dəyişdirmək və yeni dəyərləri yenidən verilənlər bazasına saxlamaqdır. Adətən belə bir əməliyyatda biz bir neçə obyekti, bir neçə cədvəli yeniləyirik.

Əməliyyat həyata keçirildikdə, eyni məlumatın başqa bir sistemdən eyni vaxtda dəyişdirilməsi baş verə bilər. Məsələn, Antispam qərar verə bilər ki, istifadəçi bir növ şübhəlidir və buna görə də istifadəçinin bütün şəkilləri artıq ictimai olmamalıdır, onlar moderasiyaya göndərilməlidir, bu da photo.status-un başqa bir dəyərə dəyişdirilməsi və müvafiq sayğacların söndürülməsi deməkdir. Aydındır ki, əgər bu əməliyyat tətbiqin atomikliyinə zəmanət olmadan və rəqib modifikasiyaların izolyasiyası olmadan baş verərsə, ACID, onda nəticə sizə lazım olan olmayacaq - ya foto sayğac yanlış dəyəri göstərəcək, ya da bütün şəkillər moderasiyaya göndərilməyəcək.

Odnoklassniki-nin mövcud olduğu müddətdə müxtəlif biznes subyektlərini bir əməliyyat çərçivəsində manipulyasiya edən çoxlu belə kodlar yazılmışdır. NoSQL-ə miqrasiya təcrübəsinə görə Hadisənin ardıcıllığı biz bilirik ki, ən böyük problem (və vaxt aparan) məlumatların ardıcıllığını qorumaq üçün kod hazırlamaq ehtiyacıdır. Buna görə də biz yeni saxlama üçün əsas tələbi real ACID əməliyyatlarının tətbiqi məntiqinin təmin edilməsi hesab etdik.

Digər eyni dərəcədə vacib tələblər bunlar idi:

  • Məlumat mərkəzinin nasazlığı halında, həm oxumaq, həm də yeni yaddaşa yazmaq mümkün olmalıdır.
  • Mövcud inkişaf sürətini saxlamaq. Yəni, yeni repozitoriya ilə işləyərkən kodun miqdarı təxminən eyni olmalıdır, depoya nəsə əlavə etməyə, münaqişələrin həlli üçün alqoritmlər hazırlamağa, ikinci dərəcəli indeksləri saxlamağa və s.
  • Yeni yaddaşın sürəti həm məlumatları oxuyarkən, həm də əməliyyatları emal edərkən kifayət qədər sürətli olmalıdır ki, bu da effektiv şəkildə akademik cəhətdən ciddi, ümumi təyinatlı, lakin yavaş həllər, məsələn, iki fazalı öhdəliklər.
  • Tez avtomatik miqyaslama.
  • Ekzotik dəmir parçaları almağa ehtiyac olmadan adi ucuz serverlərdən istifadə.
  • Şirkətin inkişaf etdiriciləri tərəfindən saxlama inkişafı imkanı. Başqa sözlə, prioritet özəllikli və ya açıq mənbə həllərinə verilirdi, tercihen Java-da.

Qərarlar, qərarlar

Mümkün həlləri təhlil edərək, iki mümkün memarlıq seçimi ilə qarşılaşdıq:

Birincisi, hər hansı bir SQL serverini götürmək və tələb olunan nasazlığa dözümlülüyü, miqyaslaşdırma mexanizmini, uğursuz klasterləşdirməni, münaqişələrin həllini və paylanmış, etibarlı və sürətli ACID əməliyyatlarını həyata keçirməkdir. Biz bu seçimi çox qeyri-ciddi və vaxt aparan kimi qiymətləndirdik.

İkinci seçim, həyata keçirilən miqyaslama, əvəzetmə qruplaşması, münaqişələrin həlli ilə hazır NoSQL yaddaşını götürmək və əməliyyatları və SQL-i özünüz həyata keçirməkdir. İlk baxışdan, hətta SQL-in tətbiqi vəzifəsi, ACID əməliyyatlarını deməmək, illərin işi kimi görünür. Lakin sonra anladıq ki, praktikada istifadə etdiyimiz SQL xüsusiyyətləri dəsti ANSI SQL-dən çox uzaqdır. Cassandra CQL ANSI SQL-dən uzaqdır. CQL-ə daha yaxından nəzər saldıqda onun ehtiyac duyduğumuza kifayət qədər yaxın olduğunu başa düşdük.

Cassandra və CQL

Bəs, Kassandranın nəyi maraqlıdır, hansı xüsusiyyətlərə malikdir?

Birincisi, burada müxtəlif məlumat növlərini dəstəkləyən cədvəllər yarada bilərsiniz, əsas açarla SEÇİM və ya YENİLƏNİB edə bilərsiniz.

CREATE TABLE photos (id bigint KEY, owner bigint,…);
SELECT * FROM photos WHERE id=?;
UPDATE photos SET … WHERE id=?;

Replika məlumatlarının ardıcıllığını təmin etmək üçün Cassandra istifadə edir kvorum yanaşması. Ən sadə halda, bu o deməkdir ki, klasterin müxtəlif qovşaqlarına eyni cərgənin üç replikasını yerləşdirərkən, qovşaqların əksəriyyəti (yəni üçdən ikisi) bu yazma əməliyyatının uğurunu təsdiqləsə, yazı uğurlu sayılır. Oxuyarkən qovşaqların əksəriyyəti sorğulansa və onları təsdiqləsə, seriyanın məlumatları ardıcıl hesab olunur. Beləliklə, üç replika varsa, bir node uğursuz olarsa, məlumatların tam və ani ardıcıllığına zəmanət verilir. Bu yanaşma bizə daha etibarlı sxemi həyata keçirməyə imkan verdi: həmişə hər üç replikaya sorğu göndərin, ən sürətli ikisindən cavab gözləyin. Üçüncü replikanın gec cavabı daha sonra atılır. Eyni zamanda, cavabı gecikdirən qovşaqda ciddi problemlər yarana bilər - əyləclər, JVM-də zibil yığılması, linux nüvəsində birbaşa yaddaşın bərpası, aparat çatışmazlığı, şəbəkədən ayrılma. Bununla belə, müştəri əməliyyatları və məlumatları heç bir şəkildə təsirlənmir.

Üç node daxil olub ikisindən cavab aldığımız yanaşma adlanır spekulyasiya: əlavə replikalar üçün sorğu "düşməmişdən" əvvəl göndərilir.

Cassandra-nın başqa bir üstünlüyü, etdiyiniz dəyişikliklərin paketə tam tətbiq edilməsini və ya tamamilə tətbiq edilməməsini təmin edən bir mexanizm olan Batchlog-dur. Bu, bizə A-nı ACID-də atomikliyi həll etməyə imkan verir.

Kassandrada əməliyyatlara ən yaxın şey sözdə "yüngül əməliyyatlar". Ancaq onlar "real" ACID əməliyyatlarından uzaqdırlar: əslində bu, etmək üçün bir fürsətdir CAS Paxos ağır çəkili protokol konsensusundan istifadə edərək yalnız bir rekordun məlumatları üzərində. Buna görə də belə əməliyyatların sürəti aşağıdır.

Kassandrada nəyi əldən verdik

Beləliklə, biz Kassandrada real ACID əməliyyatlarını həyata keçirməli olduq. Onun köməyi ilə biz klassik DBMS-nin digər iki rahat xüsusiyyətini asanlıqla həyata keçirə bildik: ardıcıl sürətli indekslər, bu, bizə məlumatları yalnız əsas açarla deyil, həm də monoton avtomatik artım identifikatorlarının adi generatoru ilə seçməyə imkan verəcəkdir.

C*Bir

Beləliklə, yeni DBMS doğuldu C*Bir, üç növ server qovşağından ibarətdir:

  • Saxlamalar (demək olar ki,) yerli disklərdə məlumatların saxlanmasına cavabdeh olan standart Cassandra serverləridir. Məlumatların yükü və həcmi artdıqca onların sayı asanlıqla onlarla və yüzlərlə ölçülə bilər.
  • Əməliyyat koordinatorları - əməliyyatların icrasını təmin edir.
  • Müştərilər biznes əməliyyatlarını həyata keçirən və əməliyyatlara başlayan proqram serverləridir. Belə müştərilər minlərlə ola bilər.

NewSQL = NoSQL+ACID

Bütün növ serverlər ümumi bir klasterdədir, bir-biri ilə əlaqə saxlamaq üçün Kassandranın daxili mesaj protokolundan istifadə edin və qeybət klaster məlumatlarının mübadiləsi üçün. Heartbeat-in köməyi ilə serverlər qarşılıqlı nasazlıqlar haqqında məlumat əldə edir, vahid verilənlər sxemini - cədvəlləri, onların strukturunu və replikasiyasını saxlayır; bölmə sxemi, klaster topologiyası və s.

Müştərilər

NewSQL = NoSQL+ACID

Standart sürücülərin əvəzinə Fat Client rejimi istifadə olunur. Belə bir qovşaq məlumatları saxlamır, lakin sorğunun icrası koordinatoru kimi çıxış edə bilər, yəni Müştərinin özü onun sorğularının koordinatoru kimi çıxış edir: saxlama replikalarını sorğulayır və münaqişələri həll edir. Bu, uzaqdan koordinatorla əlaqə tələb edən standart sürücüdən daha etibarlı və sürətli deyil, həm də sorğuların ötürülməsinə nəzarət etməyə imkan verir. Müştəridə açıq olan əməliyyatdan kənar sorğular anbarlara göndərilir. Müştəri əməliyyatı açıbsa, əməliyyat daxilindəki bütün sorğular əməliyyat koordinatoruna göndərilir.
NewSQL = NoSQL+ACID

C*One Əməliyyat Koordinatoru

Koordinator, C*One üçün sıfırdan həyata keçirdiyimiz şeydir. O, əməliyyatların, kilidlərin və əməliyyatların tətbiqi qaydasının idarə edilməsinə cavabdehdir.

Hər bir xidmət göstərilən əməliyyat üçün koordinator vaxt damğası yaradır: hər bir sonrakı əməliyyat əvvəlki əməliyyatdan böyükdür. Kassandrada münaqişənin həlli sistemi vaxt möhürlərinə əsaslandığından (iki ziddiyyətli qeyddən, ən son vaxt damğası müvafiq hesab olunur), münaqişə həmişə sonrakı əməliyyatın xeyrinə həll olunacaq. Beləliklə, biz həyata keçirdik lamport saatı paylanmış sistemdə münaqişələri həll etmək üçün ucuz bir yoldur.

Kilidlər

İzolyasiyanı təmin etmək üçün ən asan yoldan - qeydin əsas açarında pessimist kilidlərdən istifadə etmək qərarına gəldik. Başqa sözlə, tranzaksiya zamanı qeyd əvvəlcə kilidlənməlidir, yalnız bundan sonra oxunmalı, dəyişdirilməlidir və saxlanmalıdır. Yalnız müvəffəqiyyətli öhdəlikdən sonra rekordun kilidi açıla bilər ki, rəqabət aparan əməliyyatlar ondan istifadə edə bilsin.

Belə bir kilidin həyata keçirilməsi paylanmayan bir mühitdə sadədir. Paylanmış sistemdə iki əsas yol var: ya klasterdə paylanmış kilidləməni həyata keçirin, ya da eyni qeydi əhatə edən əməliyyatlara həmişə eyni koordinator tərəfindən xidmət göstərilməsi üçün əməliyyatları paylayın.

Bizim vəziyyətimizdə məlumatlar SQL-də yerli əməliyyatlar qrupları arasında artıq paylandığı üçün koordinatorlara yerli əməliyyatlar qruplarını təyin etmək qərara alındı: bir koordinator bütün əməliyyatları 0-dan 9-a qədər bir işarə ilə, ikincisi - bir işarə ilə həyata keçirir. 10-dan 19-a qədər və s. Nəticədə, koordinatorun nümunələrinin hər biri əməliyyat qrupunun ustası olur.

Sonra kilidlər koordinatorun yaddaşında banal HashMap kimi həyata keçirilə bilər.

Koordinatorların imtinaları

Bir koordinator eksklüziv olaraq bir qrup əməliyyata xidmət göstərdiyindən, əməliyyatı yerinə yetirmək üçün təkrar cəhdin fasilə müddətində olması üçün onun uğursuzluq faktını tez müəyyən etmək çox vacibdir. Bunu sürətli və etibarlı etmək üçün biz tam şəbəkəli kvorum eşitmə protokolundan istifadə etdik:

Hər bir məlumat mərkəzində ən azı iki koordinator qovşağı var. Vaxtaşırı olaraq hər bir koordinator digər koordinatorlara ürək döyüntüsü mesajı göndərir və onların fəaliyyəti, həmçinin klasterdəki hansı koordinatorlardan sonuncu dəfə ürək döyüntüsü mesajları alması barədə məlumat verir.

NewSQL = NoSQL+ACID

Qalanlardan ürək döyüntüsü mesajlarının bir hissəsi kimi oxşar məlumatları alaraq, hər bir koordinator kvorum prinsipini rəhbər tutaraq, klasterin hansı qovşaqlarının işlədiyini və hansının işləmədiyini özü üçün qərar verir: əgər X qovşağı klasterdəki qovşaqların əksəriyyətindən haqqında məlumat alıbsa. Y qovşağından mesajların normal qəbulu, sonra , Y işləyir. Əksinə, əksəriyyət Y qovşağından əskik mesajları bildirən kimi, Y uğursuz olur. Maraqlıdır ki, əgər kvorum X qovşağına ondan daha mesaj almadığını söyləsə, X node özü özünü uğursuz hesab edəcək.

Ürək döyüntüsü mesajları yüksək tezlikdə, saniyədə təxminən 20 dəfə, 50 ms müddətində göndərilir. Java-da zibil toplayıcının yaratdığı müqayisəli fasilə vaxtlarına görə tətbiqin 50 ms ərzində cavabını təmin etmək çətindir. GC pauzalarının müddəti üçün hədəfi təyin etməyə imkan verən G1 zibil toplayıcısından istifadə edərək bu cavab müddətinə nail ola bildik. Bununla belə, bəzən, olduqca nadir hallarda, kollektorun fasilələri 50 ms-dən çox olur, bu da səhv bir nasazlığın aşkarlanmasına səbəb ola bilər. Bunun qarşısını almaq üçün koordinator uzaq qovşaqdan ilk ürək döyüntüsü mesajı itirildikdə, yalnız ardıcıl olaraq bir neçəsi əskik olduqda onun nasazlığı barədə məlumat vermir.Beləliklə, koordinator qovşağının nasazlığını 200 ms-də aşkarlaya bildik.

Ancaq hansı düyünün fəaliyyətini dayandırdığını tez başa düşmək kifayət deyil. Bununla bağlı nəsə etmək lazımdır.

Rezervasyon

Klassik sxem, ustanın uğursuzluğu halında, onlardan birini istifadə edərək yenisini seçməyə başlamasını nəzərdə tutur. dəbli universal alqoritmlər. Bununla belə, bu cür alqoritmlərin zaman və seçki prosesinin özünün müddəti baxımından yaxınlaşması ilə bağlı məlum problemləri var. Biz tam qoşulmuş şəbəkədə koordinatorun dəyişdirilməsi sxemindən istifadə edərək belə əlavə gecikmələrin qarşısını ala bildik:

NewSQL = NoSQL+ACID

Tutaq ki, biz 50-ci qrupda əməliyyatı yerinə yetirmək istəyirik.Əvəzedici sxemi əvvəlcədən müəyyən edək, yəni əsas koordinatorun uğursuzluğu halında 50-ci qrup əməliyyatlarını hansı qovşaqlar yerinə yetirəcək. Məqsədimiz məlumat mərkəzinin nasazlığı halında sistemi işlək vəziyyətdə saxlamaqdır. Müəyyən edək ki, birinci ehtiyat başqa bir məlumat mərkəzindən bir qovşaq, ikinci ehtiyat üçüncüdən bir qovşaq olacaqdır. Bu sxem bir dəfə seçilir və klasterin topologiyası dəyişənə qədər, yəni ona yeni qovşaqlar daxil olana qədər dəyişmir (bu, çox nadir hallarda olur). Köhnəsinin uğursuzluğu halında yeni aktiv ustanın seçilməsi qaydası həmişə belə olacaq: birinci ehtiyat aktiv ustaya çevriləcək, əgər o, fəaliyyətini dayandırıbsa, ikinci ehtiyat olacaq.

Belə bir sxem universal alqoritmdən daha etibarlıdır, çünki yeni bir usta aktivləşdirmək üçün köhnənin uğursuzluq faktını müəyyən etmək kifayətdir.

Bəs müştərilər ustalardan hansının hazırda işlədiyini necə başa düşəcəklər? 50 ms-də minlərlə müştəriyə məlumat göndərmək mümkün deyil. Mümkündür ki, müştəri əməliyyatı açmaq üçün sorğu göndərir, lakin bu master artıq işləmədiyini hələ bilmir və sorğu fasilədə dayanacaq. Bunun baş verməməsi üçün müştərilər spekulyativ olaraq qrupun masterinə və onun hər iki ehtiyatına bir anda əməliyyat açmaq üçün sorğu göndərirlər, lakin bu sorğuya yalnız hazırda aktiv master olan şəxs cavab verəcək. Əməliyyat çərçivəsində bütün sonrakı əlaqə müştəri tərəfindən yalnız aktiv master ilə həyata keçiriləcək.

Gözləmə ustaları özlərinə məxsus olmayan əməliyyatlar üçün qəbul edilmiş sorğuları bir müddət saxlanılan doğulmamış əməliyyatların növbəsinə yerləşdirirlər. Aktiv master ölürsə, yeni master öz növbəsindən əməliyyatların açılması tələblərini emal edir və müştəriyə cavab verir. Müştəri artıq köhnə usta ilə əməliyyat açmağı bacarıbsa, ikinci cavab nəzərə alınmır (və açıq-aydın belə bir əməliyyat tamamlanmayacaq və müştəri tərəfindən təkrarlanacaq).

Bir əməliyyat necə işləyir

Tutaq ki, müştəri koordinatora filan əsas açarla filan müəssisə üçün əməliyyat açmaq üçün sorğu göndərib. Koordinator bu obyekti kilidləyir və onu yaddaşdakı kilid cədvəlinə yerləşdirir. Lazım gələrsə, koordinator bu obyekti mağazadan oxuyur və alınan məlumatları koordinatorun yaddaşında əməliyyat vəziyyətində saxlayır.

NewSQL = NoSQL+ACID

Müştəri tranzaksiyadakı məlumatları dəyişdirmək istədikdə, koordinatora obyekti dəyişdirmək üçün sorğu göndərir və koordinator yeni məlumatları əməliyyat vəziyyəti cədvəlində yaddaşda yerləşdirir. Bu qeydi tamamlayır - yaddaşa yazılmır.

NewSQL = NoSQL+ACID

Müştəri aktiv əməliyyatın bir hissəsi kimi öz dəyişdirilmiş məlumatlarını tələb etdikdə, koordinator aşağıdakı kimi hərəkət edir:

  • identifikator artıq əməliyyatdadırsa, məlumat yaddaşdan götürülür;
  • əgər yaddaşda identifikator yoxdursa, onda çatışmayan məlumatlar yaddaş qovşaqlarından oxunur, artıq yaddaşda olanlarla birləşdirilir və nəticə müştəriyə qaytarılır.

Beləliklə, müştəri öz dəyişikliklərini oxuya bilər və digər müştərilər bu dəyişiklikləri görmürlər, çünki onlar yalnız koordinatorun yaddaşında saxlanılır, onlar hələ Cassandra qovşaqlarında deyil.

NewSQL = NoSQL+ACID

Müştəri öhdəliyi göndərdikdə, xidmətin yaddaşda olması vəziyyəti koordinator tərəfindən daxil edilmiş partiyada saxlanılır və Cassandra mağazalarına daxil edilmiş partiya kimi göndərilir. Repozitorlar bu paketin atomik (tam) tətbiqi üçün lazım olan hər şeyi edir və kilidləri buraxan və müştəriyə əməliyyatın uğurunu təsdiqləyən koordinatora cavab qaytarır.

NewSQL = NoSQL+ACID

Geriyə qayıtmaq üçün koordinator yalnız əməliyyatın vəziyyətinin tutduğu yaddaşı boşaltmalıdır.

Yuxarıda təsvir edilən təkmilləşdirmələr nəticəsində biz ACID prinsiplərini həyata keçirdik:

  • Atomluq. Bu, sistemdə heç bir əməliyyatın qismən sabitlənməyəcəyinə, ya onun bütün alt əməliyyatlarının yerinə yetiriləcəyinə, ya da heç birinin yerinə yetirilməyəcəyinə zəmanətdir. Bizim vəziyyətimizdə bu prinsip Cassandra-da daxil edilmiş partiyaya görə müşahidə olunur.
  • Ardıcıllıq. Hər bir uğurlu əməliyyat, tərifinə görə, yalnız etibarlı nəticələr verir. Əgər əməliyyat açıldıqdan və bəzi əməliyyatlar yerinə yetirildikdən sonra nəticənin etibarsız olduğu aşkar edilərsə, geri çəkilmə həyata keçirilir.
  • izolə. Əməliyyat icra edildikdə paralel əməliyyatlar onun nəticəsinə təsir etməməlidir. Paralel əməliyyatlar koordinatorda pessimist kilidlərlə təcrid olunur. Tranzaksiyadan kənar oxunuşlar üçün Oxunma Təhlükəsizliyi səviyyəsində izolyasiya prinsipinə riayət edilir.
  • Davamlılıq. Aşağı səviyyələrdəki problemlərdən asılı olmayaraq - sistemin söndürülməsi, hardware nasazlığı - müvəffəqiyyətlə tamamlanan əməliyyat nəticəsində edilən dəyişikliklər fəaliyyəti bərpa etdikdən sonra yadda saxlanmalıdır.

İndekslər üzrə oxunması

Sadə bir cədvəl götürək:

CREATE TABLE photos (
id bigint primary key,
owner bigint,
modified timestamp,
…)

Onun ID (əsas açar), sahibi və dəyişdirilmə tarixi var. Çox sadə bir sorğu etməlisiniz - "son gün üçün" dəyişiklik tarixi ilə sahibi haqqında məlumatları seçin.

SELECT *
WHERE owner=?
AND modified>?

Belə bir sorğunu tez bir zamanda emal etmək üçün klassik SQL DBMS-də sütunlar (sahibi, dəyişdirilmiş) üzərində indeks qurmalısınız. Biz bunu olduqca sadə şəkildə edə bilərik, çünki indi bizdə ACID zəmanətləri var!

C*One-də indekslər

Qeyd ID-nin əsas açar olduğu fotoşəkilləri olan ilkin cədvəl var.

NewSQL = NoSQL+ACID

İndeks üçün C*One orijinal cədvəlin surəti olan yeni cədvəl yaradır. Açar indeks ifadəsi ilə eynidir, lakin o, həm də mənbə cədvəlindəki qeydin əsas açarını ehtiva edir:

NewSQL = NoSQL+ACID

İndi "son XNUMX saatda sahib" sorğusu başqa cədvəldən seçim kimi yenidən yazıla bilər:

SELECT * FROM i1_test
WHERE owner=?
AND modified>?

Mənbə cədvəli fotoşəkilləri ilə i1 indeksi arasında məlumat uyğunluğu koordinator tərəfindən avtomatik olaraq saxlanılır. Yalnız məlumat sxeminə əsasən, dəyişiklik qəbul edildikdə, koordinator təkcə əsas cədvəlin deyil, həm də nüsxələrin dəyişikliklərini yaradır və xatırlayır. İndeks cədvəli ilə əlavə hərəkətlər edilmir, jurnallar oxunmur, kilidlər istifadə edilmir. Yəni, indekslərin əlavə edilməsi demək olar ki, resursları istehlak etmir və dəyişikliklərin tətbiqi sürətinə praktiki olaraq təsir göstərmir.

ACID-in köməyi ilə biz "SQL-də olduğu kimi" indeksləri həyata keçirə bildik. Onlar ardıcıl, genişlənə bilən, sürətli, tərtib edilə bilən və CQL sorğu dilinə daxil edilmişdir. İndeks dəstəyi proqram kodunda heç bir dəyişiklik tələb etmir. SQL-də olduğu kimi hər şey sadədir. Və ən əsası, indekslər orijinal əməliyyat cədvəlinə dəyişikliklərin icra sürətinə təsir göstərmir.

Nə olub

Biz C*One-ni üç il əvvəl hazırladıq və kommersiya istifadəsinə verdik.

Axırımız nə oldu? Bunu sosial şəbəkədə ən vacib məlumat növlərindən biri olan fotoşəkillərin işlənməsi və saxlanması üçün alt sistem nümunəsində qiymətləndirək. Bu, fotoşəkillərin bədənləri haqqında deyil, hər cür meta-informasiya haqqındadır. İndi Odnoklassniki-də təxminən 20 milyard belə qeyd var, sistem saniyədə 80 min oxuma sorğusunu, məlumatların dəyişdirilməsi ilə bağlı saniyədə 8 minə qədər ACID əməliyyatını emal edir.

Replikasiya əmsalı = 1 olan SQL-dən istifadə etdikdə (lakin RAID 10-da), foto meta-məlumat 32 Microsoft SQL Server maşınından (əlavə 11 ehtiyat hissə) yüksək əlçatan klasterdə saxlanılırdı. Həmçinin ehtiyat nüsxələrin saxlanması üçün 10 server ayrılıb. Cəmi 50 bahalı maşın. Eyni zamanda, sistem marja olmadan nominal yükdə işləyirdi.

Yeni sistemə köçdükdən sonra biz replikasiya faktoru = 3 aldıq - hər bir məlumat mərkəzində bir nüsxə. Sistem 63 Cassandra saxlama qovşağından və 6 koordinator maşınından, cəmi 69 serverdən ibarətdir. Lakin bu maşınlar daha ucuzdur və SQL sisteminin qiymətinin təxminən 30%-ni təşkil edir. Bu vəziyyətdə yük 30% səviyyəsində saxlanılır.

C*One tətbiqi ilə gecikmə də azaldı: SQL-də yazma əməliyyatı təxminən 4,5 ms çəkdi. C * One-da - təxminən 1,6 ms. Əməliyyatın müddəti orta hesabla 40 ms-dən azdır, öhdəlik 2 ms-də tamamlanır, oxuma və yazma müddəti orta hesabla 2 ms-dir. 99-cu faizlik cəmi 3-3,1 ms-dir, fasilələrin sayı 100 dəfə azalıb - bütün bunlar spekulyasiyanın geniş yayılması ilə bağlıdır.

Bu günə qədər SQL Server qovşaqlarının əksəriyyəti istismardan çıxarılıb, yeni məhsullar yalnız C * One istifadə edərək hazırlanır. Biz C*One buludumuzda işləmək üçün uyğunlaşdırdıq tək buludlu, bu, yeni klasterlərin yerləşdirilməsini sürətləndirməyə, konfiqurasiyanı sadələşdirməyə və əməliyyatı avtomatlaşdırmağa imkan verdi. Mənbə kodu olmasaydı, bu, daha çətin və səhv olardı.

İndi biz digər anbarlarımızı buludlara köçürmək üzərində işləyirik - lakin bu, tamamilə fərqli bir hekayədir.

Mənbə: www.habr.com

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