Fəsil 12 · 9 dəq oxu

Data sistemlərinin gələcəyi

Data sistemlərinin gələcəyi

Əvvəlki on bir fəsil hər dəfə bir problemi götürüb onun mövcud həllərini müqayisə etdi: storage engine-lər, üsulları, transaction isolation səviyyələri, batch və stream engine-lər. Hər fəsildə eyni nəticə təkrarlandı: hər şeyi yaxşı edən tək alət yoxdur. Real tətbiq bir database, bir search index, bir , bir və bir analitik store-dan ibarət olur və əsl sistem dizaynı bu parçaları necə birləşdirməkdədir.

Bu fəsil həmin birləşdirmə məsələsinə baxır və üç suala cavab axtarır: fərqli alətləri bir sistemdə necə sinxron saxlamaq olar, tətbiqi bu parçaların üstündə necə qurmaq olar və nəticənin düzgünlüyünü necə təmin etmək olar. Sonda isə data sistemlərini quran mühəndisin məsuliyyətinə qısa, lakin ciddi bir baxış var.

Data integration: törəmə ilə birləşdirmək

Eyni data bir neçə formada lazım olanda, Fəsil 11-dəki dərs tətbiq olunur: bir sistem system of record-dur, qalanları ondan törədilir. Search index database-in başqa bir görünüşüdür, sorğunun hazır nəticəsidir, warehouse-dakı cədvəl event log-unun aggregation-ıdır. Törəmə istiqamətini açıq müəyyən etmək bütün gizli uyğunsuzluqlarını aradan qaldırır.

Törəmənin açarı sıradır. Bütün yazmalar bir log-dan keçirsə, hər consumer onları eyni ardıcıllıqla tətbiq edir və Fəsil 9-dakı total order broadcast alınır, yalnız consensus alqoritmi yox, partition olunmuş durable log vasitəsilə. Bu, deterministic törəməni mümkün edir: eyni log, eyni funksiya, eyni nəticə.

Total order-in də limiti var. Bir leader-in throughput-undan böyük yük partition tələb edir və partition-lar arasında sıra yoxdur. Geo-distributed data center-lər arasında hər yazmaya sinxron sıra vermək Fəsil 8-dəki gecikmələrlə mümkün deyil. İki ayrı service öz log-larına yazırsa, onların arasında total order yoxdur. Ümumiləşdirsək: total order kiçik miqyasda qiymətli, böyük miqyasda bahalıdır və sistem dizaynı hansı data-nın həqiqətən sıralı olmalı olduğunu seçməkdir.

Batch və stream birlikdə

hər iki yanaşmanı yanaşı işlədirdi: event-lər immutable log-a yazılır, yaxınlaşdırılmış sürətli view, isə həmin log-un üzərində dəqiq, yavaş view qurur. Fikir doğrudur, batch yenidən işlədilə bilən dəqiqlik verir, stream aşağı . Praktikada isə eyni məntiqi iki fərqli framework-də iki dəfə yazıb saxlamaq, iki output-u birləşdirmək və gecikmiş event-ləri hər ikisində düzgün idarə etmək komandaları yorurdu.

Müasir engine-lər bu bölgünü aradan qaldırır. Lazım olan üç şeydir: tarixi event-ləri həmin log-dan təkrar oxumaq, yəni Fəsil 11-dəki replay; batch-in semantikasını stream-də idempotence və checkpointing ilə əldə etmək; və pəncərələri processing time-a yox, event time-a görə hesablamaq. Bu üç xüsusiyyəti verən sistemdə batch sadəcə sonlu stream-dir.

Database-ləri unbundle etmək

Database-in içində nə baş verir? Yazma transaction log-a düşür, oradan , secondary index-lərə, materialised view-lara tətbiq olunur. Fəsil 3-də gördüyümüz index əslində törəmə data-dır və CREATE INDEX komandası snapshot götürüb log-u izləyən yeni follower yaratmaqdır, Fəsil 5-dəki kimi. Fərq odur ki, database bunu bir prosesin içində, tam ardıcıllıq zəmanəti ilə edir.

Bu baxımdan Unix fəlsəfəsi ilə relational database arasında köhnə mübahisə maraqlı görünür. Unix kiçik alətlərin kompozisiyasıdır, relational database isə hər şeyi bir sistemdə saxlayan, yüksək səviyyəli abstraction-dır. Bu gün heç biri tam qalib gəlməyib: database-lər daha çox şeyi daxilə alır, eyni zamanda tətbiqlər xüsusi alətləri kənarda birləşdirir.

Kənarda birləşdirməyin iki yolu var:

  • Federated database. Müxtəlif storage engine-lərin üstündə vahid sorğu interfeysi. Bu, oxuma tərəfində unbundling-dir və relational model-in ənənəsindədir.
  • Unbundled database. Yazma tərəfində sinxronizasiya: hər yazma log-a gedir, hər storage engine həmin log-un consumer-idir. Bu, Fəsil 11-dəki və .

Yazma tərəfində sinxronizasiya daha çətin, lakin daha vacibdir, çünki Fəsil 7-dəki distributed transaction-ların heterogen sistemlərdə işləməməsi burada ortaya çıxır. Log-based, asinxron, consumer-lər distributed transaction-ların əvəzini verir: daha zəif zəmanət, qat-qat daha yüksək robustness. Tərəflərin bir-birindən asılı olmaması, bir consumer çökəndə digərlərinin davam etməsi, yeni consumer-in köhnələrə toxunmadan əlavə edilməsi, hamısı Unix pipe-ın distributed versiyasıdır.

Çatışmayan isə bu kompozisiyanı yazmaq üçün dildir. Bu gün mysql | elasticsearch kimi bir şey yoxdur; hər törəmə connector kodla, pipeline-la, schema mapping-lə əl ilə qurulur.

Tətbiqi dataflow ətrafında qurmaq

Derived data-nın üstündə tətbiq necə görünür? Tətbiq kodu törəmə funksiyasıdır: input event-ləri alıb output state yaradır. Secondary index trivial funksiyadır, full-text index və ranking tələb edir, machine learning model-i isə training event-lərinin mürəkkəb funksiyasıdır. Bütün hallarda struktur eynidir.

Bu baxış tətbiq kodu ilə state-i ayırır. Ənənəvi database tətbiqi kənarda, passiv saxlayır: kod sorğu edir, database cavab verir, data dəyişəndə kodun xəbəri olmur. Dataflow yanaşmasında isə əksinə: data dəyişikliyi event-dir, kod ona reaksiya verir, nəticə yeni event-dir. Stream processor-lar tətbiq kodunu bu tərzdə işlədən runtime-dır.

müqayisə edək. Service-lər arasında sinxron request-response Fəsil 8-dəki bütün problemləri daşıyır: , , kaskad gecikmə. Məsələn, sifariş service-i valyuta kursunu hər dəfə başqa service-dən soruşursa, kurs service-i yavaşlayanda sifariş də yavaşlayır. Dataflow versiyasında kurs dəyişikliyi stream-dir, sifariş processor-u onun lokal kopyasını saxlayır, Fəsil 11-dəki stream-table join. Şəbəkə sorğusu yoxdur, kurs bir saniyə gecikmiş ola bilər, amma sistem daha sürətli və daha robust-dur.

Derived state-i müşahidə etmək

Dataflow yazma tərəfini həll edir. Oxuma tərəfi də stream kimi düşünülə bilər. Materialised view əslində əvvəlcədən hesablanmış ; çətin olduğu üçün view-ları log-dan deterministic şəkildə yeniləmək daha etibarlıdır.

İrəli getsək: client-in özü də derived state saxlaya bilər. Offline işləyən mobil tətbiq lokal database-dir, sinxronizasiya isə event-lərin iki istiqamətdə ötürülməsidir. Server state dəyişikliklərini client-ə push edirsə, UI sorğu-cavab deyil, stream-ə subscribe olan consumer-dir. Bu halda oxuma da event-dir: sorğunu log-a yazmaq, nəticəni stream kimi almaq. Sıralı log-da oxuma event-i ilə yazma event-i yanaşı dayananda, Fəsil 9-dakı linearizable oxuma kimi dəqiq səbəbiyyət əlaqəsi alınır və hansı istifadəçinin nə vaxt nəyi gördüyü audit edilə bilir. Qiyməti əlavə I/O-dur; hər oxuma üçün deyil, lakin bəzi hallar üçün dəyər.

Düzgünlüyə doğru

Derived data asinxron və . Bu, "düzgünlük yoxdur" demək deyil, düzgünlüyün başqa yerdə təmin olunması deməkdir.

End-to-end arqument

"" ifadəsi tez-tez yanlış anlaşılır. Stream framework-ü daxildə hər event-i bir dəfə emal edə bilər, amma istifadəçi "ödə" düyməsinə iki dəfə basıbsa və ya client sonra request-i təkrar göndəribsə, framework bunu bilmir. Fəsil 7-dəki transaction da kömək etmir: iki ayrı transaction iki dəfə pul çıxarır. Duplicate-i yalnız end-to-end həll etmək olar: client hər əməliyyata unikal id verir, server həmin id-ni unikal cədvələ yazır və təkrar gələndə eyni cavabı qaytarır.

INSERT INTO requests (request_id, from, to, amount)
VALUES ('f8a3...', 4002, 4005, 20.00);   -- ikinci dəfə unique violation

Eyni prinsip uniqueness də tətbiq olunur: "bu username boşdur?" sualına cavab vermək üçün bütün username tələblərini bir partition-a yönəldib log-da sıralamaq kifayətdir. Partition daxilində total order var, ona görə ilk tələb qalib gəlir, qalanları rədd edilir, Fəsil 9-dakı consensus-u o partition üçün log özü verir. Eyni event-in bir neçə partition-a təsir etməsi, məsələn, pul köçürməsi, atomic commit-siz də həll olunur: tələb bir event kimi log-a yazılır, iki ayrı processor onu oxuyub hərəsi öz hesabında dəyişiklik edir. Hər ikisi eyni log-u eyni sırada oxuduğu üçün heç biri digərindən xəbərsiz qalmır.

Timeliness və integrity

"Consistency" sözü əslində iki fərqli şeyi birləşdirir:

  • Timeliness. İstifadəçi sistemin təzə vəziyyətini görür. Pozulanda istifadəçi köhnə data görür və bir az sonra düzəlir; narahat edici, lakin müvəqqəti.
  • . Data zədələnməyib: itki, ziddiyyət, çatışmayan index girişi yoxdur. Pozulanda bu, daimidir və öz-özünə düzəlmir.

Fəsil 7-dəki ACID transaction ikisini birlikdə verir. Dataflow sistemləri isə onları ayırır: timeliness zəifləyir, isə sıralı log, deterministic törəmə, consumer-lər və end-to-end id-lərlə qorunur. Bu kompromis çox vaxt doğrudur, çünki istifadəçi gecikməyə dözür, itirilmiş ödənişə yox.

Biznesin özü də çox vaxt bunu tələb etmir. Bilet satışında bir neçə artıq satış üzr istəmək və kompensasiya ilə həll olunur; bank köçürməsinin iki dəfə icra edilməsi isə yox. Loosely interpreted və kompensasiya biznes prosesinin təbii hissəsidir, bu, Fəsil 9-dakı koordinasiyanın hər yazmada deyil, yalnız həqiqətən lazım olan yerdə işlədilməsinə imkan verir. Koordinasiyadan qaçan sistem daha sürətli, daha əlçatan və geo-distributed işləməyə qadirdir.

Trust, but verify

Bütün bu zəmanətlər hardware-in, software-in və fərziyyələrin doğru olmasından asılıdır. Disk sakit korrupsiya edir, Fəsil 8-də gördüyümüz kimi şəbəkə qəribə şeylər edir, 20 illik database-də hələ də tapılmamış bug-lar var. Buna görə auditing ayrı bir dizayn məqsədidir: derived view-u log-dan yenidən hesablayıb mövcud view ilə müqayisə etmək, end-to-end yoxlamaq, periodik "bu iki sistem həqiqətən eynidir?" job-ları işlətmək.

bu baxımdan bəxtəvərdir: log həm sistemin mənbəyi, həm də audit trail-idir. Verifikasiya mədəniyyəti isə texnologiyadan çox vərdişdir: backup-ı restore etmədən etibar etməmək, monitoring-in yalnız aşağı düşməni deyil, data-nın düzgünlüyünü də ölçməsi.

Düzgün işi görmək

Bu kitab texnologiya haqqındadır, lakin data sistemləri insanlar haqqında data saxlayır və son sözü onlara ayırmaq lazımdır.

Predictive analytics batch və stream pipeline-larının təbii davamıdır: event-lərdən model öyrənir, model qərar verir. Qərar kredit, iş və ya azadlıq haqqındadırsa, model-in bias sistemə daxil edilmiş ayrıseçkilikdir və "alqoritm belə dedi" cavabı məsuliyyəti aradan qaldırmır. Feedback loop daha gizlidir: tövsiyə sistemi istifadəçiyə onsuz da inandığını göstərir, model həmin kliklərlə yenidən train olunur, dönüş daralır.

Tracking-in miqyası fərqli bir məsələdir. Bir neçə il əvvəl "data toplayaq, sonra nəyə lazım olduğunu taparıq" ağıllı səslənirdi. Bu gün aydındır ki, data həm asset, həm də liability-dir: hər saxlanılan record sızma, sui-istifadə və hüquqi risk daşıyır. Consent çox vaxt formal, privacy isə geri dönməzdir. Qanunvericilik, məsələn GDPR, silinmə hüququ tələb edir və bu, immutable log-larla gərginlik yaradır: Fəsil 11-də gördüyümüz kimi, silmə bütün derived sistemlərdə həmin data-nı tapıb yenidən yazmaq deməkdir. Sistem dizaynı bunu sonradan deyil, əvvəldən nəzərə almalıdır.

Mühəndis olaraq biz nəyi necə saxladığımıza qərar veririk. Həmin qərarın ağırlığını hiss etmək peşəkarlığın hissəsidir.

Kitabdan özünüzlə aparacaqlarınız

Hər fəsildə eyni bir neçə ideya təkrarlandı və onlar konkret texnologiyadan uzun yaşayacaq:

  • Append-only log hər yerdədir: storage engine, , , . Sıralı, immutable yazma distributed sistemin ən güclü primitividir.
  • Trade-off-lar texnologiyada deyil, tələblərdədir. və , sinxron və asinxron , serializable və snapshot isolation, batch və stream: hər cüt bir şeyi verir, bir şeyi alır.
  • Fault normal haldır. Şəbəkə gecikir, saatlar səhv gedir, proses dayanır. Düzgün sistem fault-ları gizlətmir, onlarla hesablaşır.
  • Derived data bir istiqamətdə axır. System of record-u seçin, qalanını ondan törədin, törəməni deterministic və edin.
  • Düzgünlük end-to-end-dir. Heç bir layer tək başına və ya vermir; onlar tətbiqin başından sonuna qədər dizayn edilir.

Tapşırıqlar

  1. Şirkətinizdə database, search index, analitik warehouse və tövsiyə model-i var. Hər birini system of record-dan törəyən consumer kimi yenidən çəkin: hansı log-dan oxuyur, total order harada lazımdır, harada partition-lar kifayətdir? Bir consumer bir həftə dayansa nə olur?
  2. Pul köçürməsi API-sini end-to-end edin: client, API server, log və iki hesab processor-u arasında yolunu addım-addım yazın. Client sonra təkrar göndərəndə, processor-lardan biri çökəndə və log compaction baş verəndə nə olur?
  3. Immutable event log və GDPR silinmə hüququ arasında gərginliyi həll edən dizayn təklif edin. key-lərin silinməsi, log-un yenidən yazılması və derived view-ların yenidən qurulması variantlarını , audit və operability baxımından müqayisə edin.