Useampien kehittäjien pitäisi tietää tämä tietokannoista

Huomautus. käännös: Jaana Dogan on kokenut Googlen insinööri, joka työskentelee parhaillaan yrityksen Go-kielellä kirjoitettujen tuotantopalvelujen havaittavuuden parissa. Tässä artikkelissa, joka sai suuren suosion englanninkielisen yleisön keskuudessa, hän kokosi 17 kohtaan tärkeitä teknisiä yksityiskohtia DBMS-järjestelmistä (ja joskus hajautetuista järjestelmistä yleensä), joita on hyödyllistä harkita suurten / vaativien sovellusten kehittäjille.

Useampien kehittäjien pitäisi tietää tämä tietokannoista

Suurin osa tietokonejärjestelmistä seuraa tilaansa ja vaatii siten jonkinlaisen tiedontallennusjärjestelmän. Olen kerännyt tietoa tietokannoista pitkän ajan kuluessa, ja tein matkan varrella suunnitteluvirheitä, jotka johtivat tietojen katoamiseen ja katkoksiin. Suuria tietomääriä käsittelevissä järjestelmissä tietokannat ovat järjestelmäarkkitehtuurin ytimessä ja toimivat avaintekijänä optimaalisen ratkaisun valinnassa. Huolimatta siitä, että tietokannan työhön kiinnitetään erityistä huomiota, ongelmat, joita sovelluskehittäjät yrittävät ennakoida, ovat usein vain jäävuoren huippu. Tässä artikkelisarjassa jaan ideoita, joista on hyötyä kehittäjille, jotka eivät ole erikoistuneet tähän alaan.

  1. Olet onnekas, jos 99,999 % ajasta verkko ei aiheuta ongelmia.
  2. HAPPO tarkoittaa monia eri asioita.
  3. Jokaisella tietokannalla on omat mekanisminsa johdonmukaisuuden ja eristyneisyyden varmistamiseksi.
  4. Optimistinen esto tulee apuun, kun normaalia on vaikea ylläpitää.
  5. Likaisten lukujen ja tietojen katoamisen lisäksi on muitakin poikkeavuuksia.
  6. Tietokanta ja käyttäjä eivät aina ole samaa mieltä toimintatavasta.
  7. Sovellustason jakaminen voidaan siirtää sovelluksen ulkopuolelle.
  8. Automaattinen lisäys voi olla vaarallista.
  9. Vanhentuneet tiedot voivat olla hyödyllisiä, eikä niitä tarvitse lukita.
  10. Vääristymät ovat tyypillisiä kaikille aikalähteille.
  11. Viiveellä on monia merkityksiä.
  12. Suorituskykyvaatimukset tulee arvioida tietyn tapahtuman osalta.
  13. Sisäkkäiset tapahtumat voivat olla vaarallisia.
  14. Tapahtumat eivät saa olla sidoksissa sovelluksen tilaan.
  15. Kyselysuunnittelijat voivat kertoa sinulle paljon tietokannoista.
  16. Verkkosiirto on vaikeaa, mutta mahdollista.
  17. Tietokannan merkittävä lisäys lisää ennakoimattomuutta.

Haluan kiittää Emmanuel Odekea, Rein Henrichsiä ja muita palautteesta tämän artikkelin aikaisemmasta versiosta.

Olet onnekas, jos 99,999 % ajasta verkko ei aiheuta ongelmia.

Edelleen jää kysymys siitä, kuinka luotettavia nykyaikaiset verkkoteknologiat ovat ja kuinka usein järjestelmät ovat kaatuneita verkkovikojen vuoksi. Tietoa aiheesta on niukasti, ja tutkimusta hallitsevat usein suuret organisaatiot, joilla on erikoistuneet verkostot, laitteet ja henkilöstö.

Spannerin (Googlen maailmanlaajuisesti hajautetun tietokanta) saatavuusaste on 99,999 %, joten Google väittää, että vain 7,6% ongelmat liittyvät verkkoon. Samalla yritys kutsuu erikoistunutta verkkoaan korkean käytettävyyden "pääpilariksi". Opiskelu Bailis ja Kingsburyvuonna 2014 tehty , haastaa yhden "vääriä käsityksiä hajautetusta tietojenkäsittelystä", jonka Peter Deutsch muotoili vuonna 1994. Onko verkko todella luotettava?

Laajempaa Internetiä varten tehtyä kattavaa tutkimusta jättiläisten yritysten ulkopuolella ei yksinkertaisesti ole olemassa. Suurilta toimijoilta ei myöskään ole riittävästi tietoa siitä, kuinka suuri osuus heidän asiakkaidensa ongelmista liittyy verkkoon. Olemme hyvin tietoisia suurten pilvipalveluntarjoajien verkkopinon katkoksista, jotka voivat kaataa kokonaisen osan Internetiä useiksi tunteiksi yksinkertaisesti siksi, että ne ovat korkean profiilin tapahtumia, jotka vaikuttavat moniin ihmisiin ja yrityksiin. Verkkokatkot voivat aiheuttaa ongelmia monissa muissa tapauksissa, vaikka kaikki tapaukset eivät olisikaan valokeilassa. Pilvipalveluiden asiakkaat eivät myöskään tiedä mitään ongelmien syistä. Jos vika ilmenee, sitä on lähes mahdotonta selittää palveluntarjoajan verkkovirheen syyksi. Heille kolmannen osapuolen palvelut ovat mustia laatikoita. Vaikutuksia on mahdotonta arvioida ilman suurta palveluntarjoajaa.

Ottaen huomioon, mitä suuret toimijat kertovat järjestelmistään, on turvallista sanoa, että olet onnekas, jos verkko-ongelmat aiheuttavat vain pienen osan mahdollisista seisokkiongelmista. Verkkoviestintä kärsii edelleen sellaisista arkipäiväisistä asioista kuin laitteistovioista, topologian muutoksista, hallinnollisten asetusten muutoksista ja sähkökatkoksista. Äskettäin yllätyin kuullessani, että luettelo mahdollisista ongelmista lisättiin hain puree (kyllä, kuulit oikein).

ACID tarkoittaa monia eri asioita

Lyhenne ACID tarkoittaa Atomicity, Consistency, Isolation, Reliability. Näiden tapahtumien ominaisuuksien tarkoituksena on varmistaa niiden pätevyys vikojen, virheiden, laitteistovikojen jne. Ilman ACID- tai vastaavia järjestelmiä sovelluskehittäjien olisi vaikea erottaa, mistä he ovat vastuussa ja mistä tietokanta on vastuussa. Useimmat relaatiotapahtumatietokannat yrittävät olla ACID-yhteensopivia, mutta uudet lähestymistavat, kuten NoSQL, ovat synnyttäneet monia tietokantoja ilman ACID-tapahtumia, koska ne ovat kalliita toteuttaa.

Kun astuin alalle ensimmäistä kertaa, tekninen johtajamme puhui ACID-konseptin merkityksellisyydestä. Ollakseni rehellinen, ACID:tä pidetään karkeana kuvauksena pikemminkin kuin tiukkana toteutusstandardina. Nykyään pidän sitä enimmäkseen hyödyllisenä, koska se tuo esiin tietyn luokan ongelmia (ja ehdottaa useita mahdollisia ratkaisuja).

Kaikki DBMS-järjestelmät eivät ole ACID-yhteensopivia; Samaan aikaan ACID:tä tukevat tietokantatoteutukset ymmärtävät vaatimukset eri tavalla. Yksi syistä, miksi ACID-toteutukset ovat hajanaisia, johtuu monista kompromisseista, jotka on tehtävä ACID-vaatimusten toteuttamiseksi. Tekijät voivat esittää tietokantansa ACID-yhteensopivina, mutta reunatapausten tulkinta voi vaihdella dramaattisesti, samoin kuin "epätodennäköisten" tapahtumien käsittelymekanismi. Ainakin kehittäjät voivat saada korkean tason ymmärryksen perustoteutusten monimutkaisuudesta saadakseen oikean käsityksen niiden erityisestä käyttäytymisestä ja suunnittelun kompromisseista.

Keskustelu siitä, täyttääkö MongoDB ACID-vaatimukset, jatkuu myös version 4 julkaisun jälkeen. MongoDB:tä ei ole tuettu pitkään aikaan puunkorjuu, vaikka oletusarvoisesti tiedot siirrettiin levylle enintään kerran 60 sekunnissa. Kuvittele seuraava skenaario: sovellus lähettää kaksi kirjoitusta (w1 ja w2). MongoDB tallentaa w1:n onnistuneesti, mutta w2 katoaa laitteistovian vuoksi.

Useampien kehittäjien pitäisi tietää tämä tietokannoista
Skenaariota kuvaava kaavio. MongoDB kaatuu ennen kuin se voi kirjoittaa tietoja levylle

Levylle sitoutuminen on kallis prosessi. Välttämällä toistuvia sitoumuksia kehittäjät parantavat tallennussuorituskykyä luotettavuuden kustannuksella. MongoDB tukee tällä hetkellä lokiin kirjaamista, mutta likaiset kirjoitukset voivat silti vaikuttaa tietojen eheyteen, koska lokit tallennetaan oletuksena 100 ms:n välein. Eli samanlainen skenaario on edelleen mahdollinen lokeille ja niissä esitetyille muutoksille, vaikka riski on paljon pienempi.

Jokaisella tietokannalla on omat yhtenäisyys- ja eristysmekanisminsa

ACID-vaatimuksista johdonmukaisuus ja eristyneisyys tarjoavat eniten erilaisia ​​toteutuksia, koska kompromissien valikoima on laajempi. On sanottava, että johdonmukaisuus ja eristäminen ovat melko kalliita toimintoja. Ne vaativat koordinointia ja lisäävät kilpailua tietojen johdonmukaisuudesta. Ongelman monimutkaisuus lisääntyy huomattavasti, kun tietokanta on skaalattava vaakasuunnassa useiden tietokeskusten kesken (varsinkin jos ne sijaitsevat eri maantieteellisillä alueilla). Korkean johdonmukaisuuden saavuttaminen on erittäin vaikeaa, koska se myös vähentää käytettävyyttä ja lisää verkon segmentoitumista. Jos haluat yleisemmän selityksen tälle ilmiölle, suosittelen viittaamaan CAP-lause. On myös syytä huomata, että sovellukset voivat käsitellä pieniä määriä epäjohdonmukaisuuksia, ja ohjelmoijat voivat ymmärtää ongelman vivahteet riittävän hyvin ottaakseen käyttöön lisälogiikkaa sovelluksessa epäjohdonmukaisuuksien käsittelemiseksi ilman, että he luottavat suuresti tietokantaan sen käsittelemisessä.

DBMS:t tarjoavat usein erilaisia ​​eristystasoja. Sovelluskehittäjät voivat valita tehokkaimman vaihtoehdon mieltymystensä perusteella. Matala eristys mahdollistaa suuremman nopeuden, mutta lisää myös datakilpailun riskiä. Korkea eristys pienentää tätä todennäköisyyttä, mutta hidastaa työtä ja voi johtaa kilpailuun, joka johtaa sellaisiin jarruihin pohjassa, että vika alkaa.

Useampien kehittäjien pitäisi tietää tämä tietokannoista
Olemassa olevien samanaikaisuusmallien ja niiden välisten suhteiden tarkastelu

SQL-standardi määrittelee vain neljä eristystasoa, vaikka teoriassa ja käytännössä niitä on paljon enemmän. Jepson.io tarjoaa erinomaisen yleiskatsauksen olemassa olevista samanaikaisuusmalleista. Esimerkiksi Google Spanner takaa ulkoisen serialisoitavuuden kellon synkronoinnin kanssa, ja vaikka tämä on tiukempi eristyskerros, sitä ei ole määritelty standardeissa eristyskerroksissa.

SQL-standardi mainitsee seuraavat eristystasot:

  • sarjoittaa (tiukimmat ja kallein): Serialisoitavalla suorituksella on sama vaikutus kuin joillakin peräkkäisillä tapahtumien suorittamisella. Peräkkäinen suoritus tarkoittaa, että jokainen seuraava tapahtuma alkaa vasta, kun edellinen on suoritettu. On huomattava, että taso sarjoittaa Usein toteutetaan niin kutsuttuna snapshot-eristyksenä (esimerkiksi Oraclessa) tulkintaerojen vuoksi, vaikka itse tilannekuvan eristämistä ei esitetä SQL-standardissa.
  • Toistettavaa luettavaa: Nykyisen tapahtuman sitomattomat tietueet ovat käytettävissä nykyiselle tapahtumalle, mutta muiden tapahtumien tekemät muutokset (kuten uudet rivit) ei näkyvä.
  • Lue sitoutunut: Ei-sitovia tietoja ei ole saatavilla tapahtumille. Tässä tapauksessa tapahtumat voivat nähdä vain sitoutuneita tietoja, ja haamulukuja voi tapahtua. Jos tapahtuma lisää ja sitoo uusia rivejä, nykyinen tapahtuma näkee ne kyselyn yhteydessä.
  • Lue sitoutumaton (vähiten tiukka ja kallis taso): Likaiset lukemat ovat sallittuja, tapahtumat voivat nähdä muiden tapahtumien tekemiä sitomattomia muutoksia. Käytännössä tämä taso voi olla hyödyllinen karkeissa arvioissa, kuten kyselyissä COUNT(*) pöydällä.

Taso sarjoittaa minimoi datakilpailujen riskin, samalla kun se on kallein toteuttaa ja johtaa järjestelmän korkeimpaan kilpailukuormaan. Muut eristystasot ovat helpompia toteuttaa, mutta ne lisäävät datakilpailujen todennäköisyyttä. Joissakin DBMS-järjestelmissä voit asettaa mukautetun eristystason, toisilla on vahvat asetukset, eikä kaikkia tasoja tueta.

Eristystasojen tukea mainostetaan usein tietyssä DBMS:ssä, mutta vain sen käyttäytymisen huolellinen tutkiminen voi paljastaa, mitä todella tapahtuu.

Useampien kehittäjien pitäisi tietää tämä tietokannoista
Katsaus samanaikaisuuden poikkeavuuksiin eri eristystasoilla eri tietokantajärjestelmille

Martin Kleppmann projektissaan erakkomaja Vertaa eri eristystasoja, puhuu samanaikaisuuden poikkeavuuksista ja siitä, pystyykö tietokanta noudattamaan tiettyä eristystasoa. Kleppmannin tutkimus osoittaa, kuinka eri tavalla tietokantojen kehittäjät ajattelevat eristystasoista.

Optimistinen esto tulee apuun, kun normaalia on vaikea ylläpitää.

Estäminen voi olla erittäin kallista, ei vain siksi, että se lisää kilpailua tietokannassa, vaan myös siksi, että se vaatii sovelluspalvelimien jatkuvan yhteyden tietokantaan. Verkon segmentointi voi pahentaa eksklusiivisia lukitustilanteita ja johtaa lukkiutumiseen, jota on vaikea tunnistaa ja ratkaista. Tapauksissa, joissa eksklusiivinen lukitus ei sovellu, optimistinen lukitus auttaa.

Optimistinen lukko on menetelmä, jossa merkkijonoa lukiessaan se ottaa huomioon sen version, tarkistussumman tai viimeisen muokkauksen ajan. Tämän avulla voit varmistaa, että atomiversiota ei tapahdu, ennen kuin muutat merkintää:

UPDATE products
SET name = 'Telegraph receiver', version = 2
WHERE id = 1 AND version = 1

Tässä tapauksessa taulukon päivittäminen products ei suoriteta, jos jokin muu toiminto on aiemmin tehnyt muutoksia tälle riville. Jos tälle riville ei suoritettu muita toimintoja, yhden rivin muutos tapahtuu ja voimme sanoa, että päivitys onnistui.

Likaisten lukujen ja tietojen katoamisen lisäksi on muitakin poikkeavuuksia

Tietojen johdonmukaisuuden osalta painopiste on mahdollisissa kilpailuolosuhteissa, jotka voivat johtaa likaisiin lukuihin ja tietojen katoamiseen. Tietojen poikkeamat eivät kuitenkaan lopu tähän.

Yksi esimerkki tällaisista poikkeavuuksista on tallennuksen vääristymä (kirjoitusvirheitä). Vääristymiä on vaikea havaita, koska niitä ei yleensä etsitä aktiivisesti. Ne eivät johdu likaisista lukemista tai tietojen katoamisesta, vaan tiedoille asetettujen loogisten rajoitusten rikkomisesta.

Tarkastellaan esimerkiksi valvontasovellusta, joka edellyttää yhden operaattorin olevan päivystys koko ajan:

BEGIN tx1;                      BEGIN tx2;
SELECT COUNT(*)
FROM operators
WHERE oncall = true;
0                               SELECT COUNT(*)
                                FROM operators
                                WHERE oncall = TRUE;
                                0
UPDATE operators                UPDATE operators
SET oncall = TRUE               SET oncall = TRUE
WHERE userId = 4;               WHERE userId = 2;
COMMIT tx1;                     COMMIT tx2;

Yllä olevassa tilanteessa tapahtuu tietueen korruptio, jos molemmat tapahtumat onnistuvat. Vaikka likaisia ​​lukuja tai tietojen katoamista ei tapahtunut, tietojen eheys vaarantui: nyt kahden henkilön katsotaan olevan päivystys samanaikaisesti.

Serialisoitava eristys, skeeman suunnittelu tai tietokantarajoitukset voivat auttaa poistamaan kirjoitusvirheitä. Kehittäjien on kyettävä tunnistamaan tällaiset poikkeamat kehityksen aikana, jotta ne voidaan välttää tuotannossa. Samanaikaisesti tallennusvääristymiä on erittäin vaikea etsiä koodikannasta. Varsinkin suurissa järjestelmissä, kun eri kehitystiimit vastaavat samoihin taulukoihin perustuvien toimintojen toteuttamisesta eivätkä pääse yksimielisyyteen datan käytön yksityiskohdista.

Tietokanta ja käyttäjä eivät aina ole yhtä mieltä siitä, mitä tehdä

Yksi tietokantojen keskeisistä ominaisuuksista on suoritusmääräyksen takaaminen, mutta tämä tilaus itsessään ei välttämättä ole läpinäkyvä ohjelmistokehittäjälle. Tietokannat suorittavat tapahtumat vastaanotetussa järjestyksessä, eivät ohjelmoijien tarkoittamassa järjestyksessä. Tapahtumajärjestystä on vaikea ennustaa, varsinkin erittäin kuormitetuissa rinnakkaisjärjestelmissä.

Kehityksen aikana, erityisesti käytettäessä ei-estokirjastoja, huono tyyli ja heikko luettavuus voivat saada käyttäjät uskomaan, että tapahtumat suoritetaan peräkkäin, vaikka itse asiassa ne voivat saapua tietokantaan missä tahansa järjestyksessä.

Ensi silmäyksellä alla olevassa ohjelmassa T1 ja T2 kutsutaan peräkkäin, mutta jos nämä toiminnot eivät ole estäviä ja palauttavat tuloksen välittömästi muodossa lupaus, niin puheluiden järjestys määräytyy niiden hetkien mukaan, jolloin he tulivat tietokantaan:

tulos1 = T1() // todelliset tulokset ovat lupauksia
tulos2 = T2()

Jos atomiteettia vaaditaan (eli joko kaikki toiminnot on suoritettava loppuun tai keskeytettävä) ja järjestyksellä on väliä, operaatiot T1 ja T2 on suoritettava yhdessä tapahtumassa.

Sovellustason jakaminen voidaan siirtää sovelluksen ulkopuolelle

Jakaminen on menetelmä tietokannan vaakasuoraan osiointiin. Jotkut tietokannat voivat automaattisesti jakaa tiedot vaakasuunnassa, kun taas toiset eivät tai ole kovin hyviä siinä. Kun data-arkkitehdit/kehittäjät pystyvät ennustamaan tarkasti, kuinka dataa käytetään, he voivat luoda vaakaosioita käyttäjätilaan sen sijaan, että delegoisivat tämän työn tietokantaan. Tätä prosessia kutsutaan "sovellustason jakamiseksi" (sovellustason jako).

Valitettavasti tämä nimi luo usein väärinkäsityksen, että sharding elää sovelluspalveluissa. Itse asiassa se voidaan toteuttaa erillisenä kerroksena tietokannan edessä. Tietojen kasvusta ja skeemojen iteraatioista riippuen jakovaatimuksista voi tulla melko monimutkaisia. Jotkin strategiat voivat hyötyä iterointikyvystä ilman, että sovelluspalvelimia tarvitsee sijoittaa uudelleen.

Useampien kehittäjien pitäisi tietää tämä tietokannoista
Esimerkki arkkitehtuurista, jossa sovelluspalvelimet on erotettu jakopalvelusta

Jakamisen siirtäminen erilliseen palveluun laajentaa mahdollisuuksia käyttää erilaisia ​​jakostrategioita ilman tarvetta asentaa sovelluksia uudelleen. Vitess on esimerkki tällaisesta jakojärjestelmästä sovellustasolla. Vitess tarjoaa MySQL:lle horisontaalisen jaon ja mahdollistaa asiakkaiden yhteyden siihen MySQL-protokollan kautta. Järjestelmä segmentoi tiedot eri MySQL-solmuihin, jotka eivät tiedä mitään toisistaan.

Automaattinen lisäys voi olla vaarallista

AUTOMAATTINEN LISÄYS on yleinen tapa luoda perusavaimia. Usein on tapauksia, joissa tietokantoja käytetään ID-generaattoreina ja tietokanta sisältää tunnisteiden luomiseen suunniteltuja taulukoita. On useita syitä, miksi ensisijaisten avainten luominen automaattisen lisäyksen avulla ei ole ihanteellista:

  • Hajautetussa tietokannassa automaattinen lisäys on vakava ongelma. ID:n luomiseen tarvitaan yleinen lukitus. Sen sijaan voit luoda UUID:n: tämä ei vaadi vuorovaikutusta tietokantasolmujen välillä. Automaattinen lisäys lukoilla voi johtaa kiistaan ​​ja heikentää merkittävästi lisäosien suorituskykyä hajautetuissa tilanteissa. Jotkin tietokantajärjestelmät (esimerkiksi MySQL) saattavat vaatia erityisiä määrityksiä ja tarkempaa huomiota järjestääkseen master-master-replikoinnin oikein. Ja on helppo tehdä virheitä määrityksen aikana, mikä johtaa tallennusvirheisiin.
  • Joissakin tietokannoissa on ensisijaisiin avaimiin perustuvia osiointialgoritmeja. Peräkkäiset tunnukset voivat johtaa arvaamattomiin hot spoteihin ja lisääntyneeseen kuormitukseen joissakin osioissa, kun taas toiset jäävät käyttämättä.
  • Ensisijainen avain on nopein tapa käyttää tietokannan riviä. Paremmilla tavoilla tietueiden tunnistamiseen peräkkäiset tunnukset voivat muuttaa taulukoiden tärkeimmän sarakkeen hyödyttömäksi sarakkeeksi, joka on täynnä merkityksettömiä arvoja. Siksi, aina kun mahdollista, valitse globaalisti ainutlaatuinen ja luonnollinen ensisijainen avain (esim. käyttäjätunnus).

Ennen kuin päätät lähestymistavasta, harkitse automaattisesti kasvavien tunnusten ja UUID-tunnusten vaikutusta indeksointiin, osiointiin ja jakamiseen.

Vanhentuneet tiedot voivat olla hyödyllisiä eivätkä vaadi lukitsemista

Multiversion Concurrency Control (MVCC) toteuttaa monia johdonmukaisuusvaatimuksia, joita käsiteltiin lyhyesti edellä. Jotkut tietokannat (esimerkiksi Postgres, Spanner) käyttävät MVCC:tä tapahtumien "syöttämiseen" tilannekuvilla - tietokannan vanhemmilla versioilla. Snapshot-tapahtumat voidaan myös sarjottaa johdonmukaisuuden varmistamiseksi. Kun luetaan vanhasta tilannevedosta, luetaan vanhentuneet tiedot.

Hieman vanhentuneiden tietojen lukeminen voi olla hyödyllistä esimerkiksi luotaessa tiedoista analytiikkaa tai laskettaessa likimääräisiä kokonaisarvoja.

Ensimmäinen etu vanhojen tietojen kanssa työskentelyssä on alhainen latenssi (varsinkin jos tietokanta on hajallaan eri maantieteellisillä alueilla). Toinen on se, että vain luku -tapahtumat ovat lukitsemattomia. Tämä on merkittävä etu sovelluksille, jotka lukevat paljon, kunhan ne voivat käsitellä vanhentuneita tietoja.

Useampien kehittäjien pitäisi tietää tämä tietokannoista
Sovelluspalvelin lukee paikallisesta replikosta 5 sekuntia vanhentuneet tiedot, vaikka uusin versio olisi saatavilla Tyynenmeren toisella puolella

DBMS-järjestelmät tyhjentävät automaattisesti vanhemmat versiot ja joissakin tapauksissa sallivat sinun tehdä tämän pyynnöstä. Esimerkiksi Postgres antaa käyttäjille mahdollisuuden tehdä VACUUM pyynnöstä ja myös säännöllisesti suorittaa tämän toiminnon automaattisesti. Spanner pyörittää roskakoria päästäkseen eroon yli tunnin vanhoista kuvista.

Kaikki aikalähteet ovat alttiina vääristymille

Tietojenkäsittelytieteen parhaiten varjeltu salaisuus on, että kaikki ajoitussovellusliittymät valehtelevat. Itse asiassa koneemme eivät tiedä tarkkaa nykyistä aikaa. Tietokoneet sisältävät kvartsikiteitä, jotka synnyttävät värähtelyjä, joita käytetään pitämään aikaa. Ne eivät kuitenkaan ole tarpeeksi tarkkoja ja voivat olla tarkan ajan edellä/jäljessä. Vuoro voi olla 20 sekuntia päivässä. Siksi tietokoneidemme aika on ajoittain synkronoitava verkon kanssa.

Synkronointiin käytetään NTP-palvelimia, mutta itse synkronointiprosessissa on verkon viiveitä. Jopa synkronointi NTP-palvelimen kanssa samassa datakeskuksessa kestää jonkin aikaa. On selvää, että työskentely julkisen NTP-palvelimen kanssa voi johtaa vielä suurempiin vääristymiin.

Atomikellot ja niiden GPS-vastineet sopivat paremmin kellonajan määrittämiseen, mutta ne ovat kalliita ja vaativat monimutkaisen asennuksen, joten niitä ei voi asentaa jokaiseen autoon. Tämän vuoksi palvelinkeskukset käyttävät porrastettua lähestymistapaa. Atomi- ja/tai GPS-kellot näyttävät tarkan ajan, jonka jälkeen se lähetetään muille koneille toissijaisten palvelimien kautta. Tämä tarkoittaa, että jokainen kone kokee tietyn poikkeaman tarkasta ajasta.

Tilannetta pahentaa se, että sovellukset ja tietokannat sijaitsevat usein eri koneilla (elleivät eri datakeskuksissa). Siten aika ei eroa vain DB-solmuissa, jotka on jaettu eri koneille. Se on myös erilainen sovelluspalvelimella.

Google TrueTime käyttää täysin erilaista lähestymistapaa. Useimmat ihmiset uskovat, että Googlen edistyminen tähän suuntaan selittyy banaalilla siirtymisellä atomikelloihin ja GPS-kelloihin, mutta tämä on vain osa kokonaisuutta. Näin TrueTime toimii:

  • TrueTime käyttää kahta eri lähdettä: GPS:ää ja atomikelloa. Näillä kelloilla on ei-korreloituvia vikatiloja. [katso lisätietoja sivulta 5 täällä - noin käännös.), joten niiden yhteinen käyttö lisää luotettavuutta.
  • TrueTimella on epätavallinen API. Se palauttaa ajan intervallina, johon on sisäänrakennettu mittausvirhe ja epävarmuus. Todellinen ajanhetki on jossain intervallin ylä- ja alarajojen välissä. Spanner, Googlen hajautettu tietokanta, yksinkertaisesti odottaa, kunnes on turvallista sanoa, että nykyinen aika on alueen ulkopuolella. Tämä menetelmä tuo järjestelmään jonkin verran latenssia, varsinkin jos isäntälaitteiden epävarmuus on suuri, mutta varmistaa oikeellisuuden myös globaalisti hajautetussa tilanteessa.

Useampien kehittäjien pitäisi tietää tämä tietokannoista
Spanner-komponentit käyttävät TrueTimea, jossa TT.now() palauttaa intervallin, joten jakoavain vain nukkuu siihen pisteeseen asti, jossa se voi olla varma, että nykyinen aika on ylittänyt tietyn pisteen

Pienentynyt tarkkuus nykyisen ajan määrittämisessä tarkoittaa avaimen toiminnan keston pidentymistä ja suorituskyvyn heikkenemistä. Tästä syystä on tärkeää säilyttää suurin mahdollinen tarkkuus, vaikka täysin tarkkaa kelloa on mahdotonta saada.

Viiveellä on monia merkityksiä

Jos kysyt kymmeneltä asiantuntijalta, mitä viivästys tarkoittaa, saat todennäköisesti erilaisia ​​vastauksia. DBMS:ssä viivettä kutsutaan usein "tietokannan latenssiksi" ja se eroaa asiakkaan havaitsemasta. Tosiasia on, että asiakas tarkkailee verkkoviiveen ja tietokantaviiveen summaa. Kyky eristää latenssityyppi on kriittinen, kun etsitään kasvavia ongelmia. Kun keräät ja näytät mittareita, yritä aina pitää silmällä molempia tyyppejä.

Suorituskykyvaatimukset tulee arvioida tietyn tapahtuman osalta

Joskus DBMS:n suorituskykyominaisuudet ja sen rajoitukset määritellään kirjoitus-/lukunopeuden ja latenssin suhteen. Tämä antaa yleiskatsauksen tärkeimmistä järjestelmäparametreista, mutta uuden DBMS:n suorituskykyä arvioitaessa paljon kattavampi lähestymistapa on arvioida kriittiset toiminnot erikseen (jokaiselle kyselylle ja/tai tapahtumalle). Esimerkkejä:

  • Kirjoita suoritusteho ja viive, kun lisäät uuden rivin taulukkoon X (jossa on 50 miljoonaa riviä) määritetyillä rajoituksilla ja rivin täyttöillä liittyvissä taulukoissa.
  • Viivästyy tietyn käyttäjän ystävien ystävien näyttämisessä, kun ystävien keskimääräinen lukumäärä on 500.
  • Viive haettaessa 100 suosituinta merkintää käyttäjän historiasta, kun käyttäjä seuraa 500 muuta käyttäjää X merkinnällä tunnissa.

Arviointi ja kokeilu voivat sisältää tällaisia ​​kriittisiä tapauksia, kunnes olet varma, että tietokanta täyttää suorituskykyvaatimukset. Samanlainen nyrkkisääntö ottaa myös tämän jaottelun huomioon, kun kerätään latenssimittareita ja määritetään SLO:ita.

Ole tietoinen suuresta kardinaalisuudesta, kun keräät mittareita jokaiselle toiminnolle. Käytä lokeja, tapahtumakeräystä tai hajautettua jäljitystä saadaksesi tehokkaita virheenkorjaustietoja. Artikkelissa "Haluatko tehdä virheenkorjauksen latenssista?» voit tutustua viiveen virheenkorjausmenetelmiin.

Sisäkkäiset tapahtumat voivat olla vaarallisia

Kaikki DBMS-järjestelmät eivät tue sisäkkäisiä tapahtumia, mutta kun ne tukevat, tällaiset tapahtumat voivat johtaa odottamattomiin virheisiin, joita ei aina ole helppo havaita (eli pitäisi olla selvää, että kyseessä on jonkinlainen poikkeama).

Voit välttää sisäkkäisten tapahtumien käyttämisen käyttämällä asiakaskirjastoja, jotka voivat havaita ja ohittaa ne. Jos sisäkkäisiä tapahtumia ei voida hylätä, ole erityisen huolellinen niiden toteutuksessa välttääksesi odottamattomia tilanteita, joissa valmiit tapahtumat keskeytyvät vahingossa sisäkkäisten tapahtumien takia.

Tapahtumien kapselointi eri kerroksiin voi johtaa odottamattomiin sisäkkäisiin tapahtumiin, ja koodin luettavuuden kannalta se voi vaikeuttaa kirjoittajan aikomusten ymmärtämistä. Tutustu seuraavaan ohjelmaan:

with newTransaction():
   Accounts.create("609-543-222")
   with newTransaction():
       Accounts.create("775-988-322")
       throw Rollback();

Mikä on yllä olevan koodin tulos? Peruuttaako se molemmat tapahtumat vai vain sisäisen? Mitä tapahtuu, jos luotamme useisiin kirjastokerroksiin, jotka kapseloivat tapahtumien luomisen puolestamme? Pystymmekö tunnistamaan ja parantamaan tällaisia ​​tapauksia?

Kuvittele tietokerros, jossa on useita toimintoja (esim. newAccount) on jo otettu käyttöön sen omissa tapahtumissa. Mitä tapahtuu, jos käytät niitä osana korkeamman tason liiketoimintalogiikkaa, joka toimii omassa tapahtumassaan? Mikä olisi eristyneisyys ja johdonmukaisuus tässä tapauksessa?

function newAccount(id string) {
  with newTransaction():
      Accounts.create(id)
}

Sen sijaan, että etsit vastauksia tällaisiin loputtomiin kysymyksiin, on parempi välttää sisäkkäisiä tapahtumia. Loppujen lopuksi tietokerrossi voi helposti suorittaa korkean tason toimintoja luomatta omia tapahtumiaan. Lisäksi liiketoimintalogiikka itse pystyy käynnistämään tapahtuman, suorittamaan sille toimintoja, sitomaan tai keskeyttämään tapahtuman.

function newAccount(id string) {
   Accounts.create(id)
}
// In main application:
with newTransaction():
   // Read some data from database for configuration.
   // Generate an ID from the ID service.
   Accounts.create(id)
   Uploads.create(id) // create upload queue for the user.

Tapahtumat eivät saa olla sidoksissa sovelluksen tilaan

Joskus on houkuttelevaa käyttää tapahtumissa sovelluksen tilaa tiettyjen arvojen muuttamiseksi tai kyselyparametrien säätämiseksi. Kriittinen vivahde, joka on otettava huomioon, on oikea sovellusalue. Asiakkaat käynnistävät usein tapahtumat uudelleen, kun verkkoon tulee ongelmia. Jos tapahtuma sitten riippuu tilasta, jota jokin muu prosessi muuttaa, se voi valita väärän arvon datakilpailun mahdollisuudesta riippuen. Tapahtumissa on otettava huomioon datakilpailuolosuhteiden riski sovelluksessa.

var seq int64
with newTransaction():
    newSeq := atomic.Increment(&seq)
    Entries.query(newSeq)
    // Other operations...

Yllä oleva tapahtuma kasvattaa järjestysnumeroa joka kerta, kun se suoritetaan, lopputuloksesta riippumatta. Jos toimitus epäonnistuu verkko-ongelmien vuoksi, pyyntö suoritetaan eri järjestysnumerolla, kun yrität uudelleen.

Kyselysuunnittelijat voivat kertoa paljon tietokannasta

Kyselysuunnittelijat määrittävät, kuinka kysely suoritetaan tietokannassa. He myös analysoivat pyynnöt ja optimoivat ne ennen niiden lähettämistä. Suunnittelijat voivat tarjota vain joitain mahdollisia arvioita käytettävissään olevien signaalien perusteella. Mikä on esimerkiksi paras hakutapa seuraavalle kyselylle?

SELECT * FROM articles where author = "rakyll" order by title;

Tulokset voidaan hakea kahdella tavalla:

  • Täysi taulukon skannaus: Voit tarkastella taulukon jokaista merkintää ja palauttaa artikkeleita vastaavan tekijän nimellä ja tilata ne.
  • Hakemiston skannaus: Voit käyttää hakemistoa löytääksesi vastaavat tunnukset, hakeaksesi kyseiset rivit ja järjestääksesi ne.

Kyselysuunnittelijan tehtävänä on määrittää, mikä strategia on paras. On syytä ottaa huomioon, että kyselysuunnittelijoilla on vain rajalliset ennustusominaisuudet. Tämä voi johtaa huonoihin päätöksiin. DBA:t tai kehittäjät voivat käyttää niitä huonosti toimivien kyselyiden diagnosointiin ja hienosäätöön. DBMS:n uudet versiot voivat määrittää kyselysuunnittelijoita, ja itsediagnostiikka voi auttaa tietokannan päivityksessä, jos uusi versio johtaa suorituskykyongelmiin. Hitaat kyselylokit, viiveongelmaraportit tai suoritusaikatilastot voivat auttaa tunnistamaan optimointia vaativat kyselyt.

Jotkin kyselysuunnittelijan esittämät mittarit voivat olla kohinallisia (etenkin arvioitaessa latenssia tai suoritinaikaa). Hyvä lisä ajoittajiin ovat työkalut suorituspolun jäljittämiseen ja seurantaan. Niiden avulla voit diagnosoida tällaiset ongelmat (valitettavasti kaikki tietokantajärjestelmät eivät tarjoa tällaisia ​​​​työkaluja).

Verkkosiirto on vaikeaa, mutta mahdollista

Online-siirto, reaaliaikainen siirto tai reaaliaikainen siirto tarkoittaa siirtymistä tietokannasta toiseen ilman seisokkeja tai tietojen vioittumista. Reaaliaikainen siirto on helpompi suorittaa, jos siirto tapahtuu samassa tietokantajärjestelmässä/moottorissa. Tilanne muuttuu monimutkaisemmaksi, kun on tarpeen siirtyä uuteen DBMS:ään, jolla on erilaiset suorituskyky- ja skeemavaatimukset.

On olemassa erilaisia ​​​​verkkosiirtomalleja. Tässä on yksi niistä:

  • Ota kaksoissyöttö käyttöön molemmissa tietokantoissa. Uudessa tietokannassa ei tässä vaiheessa ole kaikkia tietoja, vaan se hyväksyy vain uusimmat tiedot. Kun olet varma tästä, voit siirtyä seuraavaan vaiheeseen.
  • Ota lukeminen käyttöön molemmista tietokannoista.
  • Määritä järjestelmä siten, että lukeminen ja kirjoittaminen suoritetaan ensisijaisesti uudessa tietokannassa.
  • Lopeta kirjoittaminen vanhaan tietokantaan ja jatka tietojen lukemista siitä. Tässä vaiheessa uudesta tietokannasta puuttuu vielä joitakin tietoja. Ne tulee kopioida vanhasta tietokannasta.
  • Vanha tietokanta on vain luku -tilassa. Kopioi puuttuvat tiedot vanhasta tietokannasta uuteen. Kun siirto on valmis, vaihda polut uuteen tietokantaan, pysäytä vanha ja poista se järjestelmästä.

Lisätietoja varten suosittelen ottamaan yhteyttä статье, joka kertoo Stripen tähän malliin perustuvasta siirtostrategiasta.

Tietokannan merkittävä lisäys lisää ennakoimattomuutta

Tietokannan kasvu johtaa arvaamattomiin ongelmiin, jotka liittyvät sen mittakaavaan. Mitä enemmän tiedämme tietokannan sisäisestä rakenteesta, sitä paremmin voimme ennustaa, kuinka se skaalautuu. Joitakin hetkiä on kuitenkin mahdotonta ennakoida.
Kantavuuden kasvaessa aikaisemmat oletukset ja odotukset datamäärästä ja verkon kaistanleveysvaatimuksista voivat vanhentua. Tällöin herää kysymys laajoista suunnittelun uudistuksista, laajamittaisista toiminnallisista parannuksista, käyttöönottojen uudelleenarvioinnista tai siirtymisestä muihin tietokantajärjestelmiin mahdollisten ongelmien välttämiseksi.

Mutta älä ajattele, että nykyisen tietokannan sisäisen rakenteen erinomainen tuntemus on ainoa tarpeellinen asia. Uudet vaa'at tuovat mukanaan uusia tuntemattomia. Ennalta arvaamattomat kipukohdat, epätasainen tiedon jakautuminen, odottamattomat kaistanleveys- ja laitteistoongelmat, jatkuvasti kasvava liikenne ja uudet verkkosegmentit pakottavat sinut harkitsemaan uudelleen tietokantaasi lähestymistapaa, tietomallia, käyttöönottomallia ja tietokannan kokoa.

...

Kun aloin miettimään tämän artikkelin julkaisemista, alkuperäisellä listallani oli jo viisi muuta kohdetta. Sitten tuli valtava määrä uusia ideoita siitä, mitä muuta voidaan kattaa. Siksi artikkelissa käsitellään vähiten ilmeisiä ongelmia, jotka vaativat mahdollisimman paljon huomiota. Tämä ei kuitenkaan tarkoita, että aihe olisi loppunut, enkä enää palaa siihen tulevissa materiaaleissani enkä tee muutoksia nykyiseen.

PS.

Lue myös blogistamme:

Lähde: will.com

Lisää kommentti