Artikel top billede

(Foto: Computerworld)

Programmering med NoSQL - del 1

En ny type databasemotor er hastigt på vej, NoSQL-databaserne. I denne artikelserie kigger vi nærmer på NoSQL og på, hvordan du programmerer til dem.

Af Kenneth Geisshirt, Alt om Data

Denne artikel er oprindeligt bragt på Alt om Data. Computerworld overtog i november 2022 Alt om Data. Du kan læse mere om overtagelsen her.

Men inden vi kaster os ud i NoSQL, så lad os lige få lidt grundviden genopfrisket, så vi ved, hvad vi snakker om, og hvad forskellen på de forskellige databasetyper er.

Der findes flere forskellige typer databaser. Til almindelige applikationer (herunder dynamiske hjemmesider og webbutikker) er den relationelle database meget udbredt. Men hierarkiske databaser er mere udbredte, end de fleste tror. LDAP og Active Directory er eksempler på hierarkiske databaser.

Den relationelle database er, sammen med søgesproget SQL, meget udbredt. Ideen bag den relationelle database er at opdele al data i en række tabeller. En tabel kaldes for en relation blandt de mere teoretiske personer i databaseverdenen.

Der er med andre ord ikke tale om relationer (forbindelser) mellem data i en relationel database. Forbindelser mellem data specificeres på andre måder, typisk ved brug af primære nøgler og fremmednøgler.

Tabeller og diverse nøgler er datamodellen. Ved komplekse applikationer kan datamodellen blive meget svær at gennemskue, da tabellerne ikke nødvendigvis har en intuitiv forklaring.

Et eksempel er modellering af faktura i et regnskabssystem. Her vil der ofte bruges to tabeller: en til fakturahoved og en tabel til fakturalinjerne. Og det betyder, at programmøren skal have fat i totabellen for at genskabe en faktura.

NoSQL gør det anderledes

I NoSQL går programmøren radikalt anderledes til værks. Her vil en faktura blive gemt samlet. Grunden er, at en faktura ikke skal ændres, når den først er sendt til kunden, og derfor er der ingen grund til at gemme den i forskellige tabeller. Skal applikationen bruge fakturaen igen, skal den bruge både hoved og linjerne.

En anden måde at sige det på: Data splittes ikke op i NoSQL-databaser på samme måde som i en relationel database, og datas egen struktur bruges i stedet for en ”kunstig” struktur, som er påtvunget af en udvikler.

Den relationelle database har en meget vigtig egenskab. Den overholder ACID-betingelserne. ACID er en forkortelse for Atomicity, Consistency, Isolation, Durability. Kort fortalt betyder det, at en transaktion enten gennemføres fuldstændigt eller overhovedet ikke. Der er ikke noget, som gennemføres delvist.

Er transaktionen for eksempel, at gennem en faktura med tre linjer skal der tilføjes én linje til fakturahoved-tabellen og tre linjer til fakuralinje-tabellen, før transaktionen er gennemført (data er gemt på harddisken)? Fejler bare en af disse fire tilføjelser, rulles alle de andre tilbage.

Netop ACID betyder, at det kan være svært at sprede en relationel database ud på flere servere for at give mere ydeevne til en database med mange forespørgsler.

Selvom du har fire servere, som tager sig af hver af de fire tidligere omtalte tilføjelser, skal der være et centralt sted, som koordinerer det hele. Dette centrale sted i databasen bliver hurtigt en flaskehals, og det hjælper ikke at tilføje flere servere.

Mange NoSQL-databaser er distribuerede databasesystemer. Et distribueret system består af to eller flere servere, som er forbundet gennem et netværk. Data ligger lokalt, og hver server har en kopi af enten hele eller dele af databasen.

Med andre ord kan NoSQL-databaserne udnytte, at du tilføjer servere, når antal forespørgsler stiger, og sprede belastningen over flere. Men som du måske allerede har fået en mistanke om: ACID-betingelserne er ikke opfyldt for NoSQL-databaserne. Senere i denne artikel vil du faktisk se, at det bliver værre.

Hvem bruger NoSQL?

Der findes allerede i dag en række eksempler på anvendelsen af NoSQL-databaser. Det er værd at bemærke, at NoSQL er opstået i miljøer, hvor der er mange brugere.

Det er derfor ikke overraskende, at de fleste anvendelser af NoSQL kommer fra miljøer med store datamængder og/eller mange forespørgsler, især i form af mange samtidige brugere.

Der findes i dag en række globale web-applikationer, det vil sige applikationer, som trækker brugere fra store dele af verden. Det betyder, at hvis alle serverne står ét sted i verden, bliver applikationen meget sårbar. Er der en fejl (strømsvigt, oversvømmelse, brand og så videre), vil alle brugere opleve, at applikationen er nede.

Løsningen er at distribuere applikationen ud til mange datacentre rundtomkring i verden. De relationelle databasesystemer har svært ved at håndtere sådan en global situation, og NoSQL træder ind på scenen og overtager. Endvidere har den distribuerede applikation den fordel, at latency giver mindre, da applikationen afvikles tættere på brugerne.

De store applikationer på internettet bruger faktisk alle NoSQL i en eller anden form. Google bruger en NoSQL-database ved navn BigTable. Det er et internt system, det vil sige, du kan ikke købe eller downloade BigTable. Men Google bruger BigTable i flere af sine applikationer, herunder Google Maps og Gmail.

Voldemort (eller rettere Project Voldemort) er LinkedIns distribuerede NoSQL-motor. Du kan downloade kildeteksten fra project-voldemort.com/, idet der er tale om et open source-projekt.

Et firma, som var tidligt ude med et global website med mange brugere, er Amazon. Firmaet har sin egen NoSQL-database ved navn Dynamo. Som kunde hos Amazon vil du ikke opleve Dynamo direkte, men databasen bruges i de indre dele af den globale boghandel.

Facebook har udviklet en NoSQL-database ved navn Cassandra. For et par år siden besluttede Facebook at frigive Cassandra under en open source-licens, og i dag hører Cassandra hjemme hos Apache-projektet. Du kan downloade Cassandra fra cassandra.apache.org/.

CAP-sætningen

Langt de fleste NoSQL-databaser er som sagt distribuerede databasesystemer. Det betyder, at de kan afvikles på flere servere samtidig. Serverne arbejder sammen og giver dermed, forhåbentlig, en højere ydeevne.

I 2000 fremkom den amerikanske datalog Eric Brewer med en formodning (formodning i matematik er en sandhed/sætning uden bevis), som i dag går under navnet CAP-sætningen (CAP theorem) eller Brewers sætning. Formodningen får et formelt matematisk bevis i 2002, da Seth Gilbert og Nancy Lunch udvikler et bevis, og derefter har der været tale om en stærk og formelt korrekt matematisk-datalogisk formuleret sætning.

Sætningen omhandler tre betingelser: konsistens (consistency), tilgængelighed (availability) og tolerance ved opdeling (partition tolerance). Den korte version af CAP-sætningen er, at et distribueret system kun kan garantere, at to betingelser er overholdt til enhver tid og ikke alle tre betingelser hele tiden.

En anden måde at formulere CAP-sætningen på er at sige, at en distribueret database ikke kan opfylde ACID. Det har store konsekvenser for dit design af applikationer, og det er nødvendigt at forstå de tre tilfælde. De forskellige NoSQL-databaser vægter de tre tilfælde forskelligt, og du er nødt til at kende CAP-sætningen for at kunne vælge database.

Tilfældet C+A

Har du et distribueret system, kan du risikere, at det brækker op i mindst to dele. Forestil dig, at dit system består af to servere, som er forbundet med et netværk. Om serveren står fysisk tæt på eller langt fra hinanden, er mindre vigtigt. Går netværket ned, har du et system i to dele (partitions).

Ønsker du, at dit system til enhver tid er konsistent og tilgængeligt, bliver du nødt til at opgive, at dit system er distribueret, idet CAP-sætningen udtaler, at sådan et system ikke kan modstå et netværksnedbrud. Eneste måde, at dit system kan være både konsistent og tilgængeligt på, er, at der er en central instans, som styrer dit system. Og en central instans kan pr. definition ikke være distribueret.

Et eksempel på en applikation, hvor konsistens og tilgængelig er de to vigtigste betingelser, er værdipapirhandel. Her er det vigtigt, at det altid er muligt at afgive ordrer på køb eller salg af aktier og obligationer (tilgængelighed). Det er lige så vigtigt, at ordrerne udføres (konsistens) fuldstændigt, så du ikke ender i den situation, at pengene er trukket fra kontoen, men aktierne ikke er købt.

Med andre ord ender du tilbage med et tilfælde, hvor din applikation ikke kan skaleres ud over én server. Er skalerbarhed nøgleordet for dig, er det ikke i dette tilfælde, at du kan finde hjælp til din arkitektur.

Tilfældet C+P

Har du valgt at lade din applikation være distribueret, er tolerance mod opdeling vigtig for dig. Det kan du opnå på to måder.

Den første måde at sikre, at din applikation kan skalere ud over mere end en server, er at give køb på tilgængeligheden. På den måde arbejder din applikation stadig med konsistente data til enhver tid og kan modstå et nedbrud i netværket.

Ulempen er i dette tilfælde, at du er nødt til at ofre tilgængeligheden, når der opstår en fejl, som nedbrud af netværket. Når din applikation ser, at der er sket en fejl, må applikationen med det samme lukke ned og afvise brugerne.

Mange systemer til high availability (HA) fungerer på den måde. Et stykke software overvåger applikationen og fjerner servere, som ikke kan nås gennem netværket. HA-software kan være mere eller mindre kompleks, men aldrig enkel – både at sætte op og drive.

Et eksempel på et system i dette tilfælde er, hvor serverne er placeret langt fra hinanden (i hver sin landsdel eller på hvert sit kontinent). Så længe netværk og andre komponenter fungerer, er alle servere tilgængelige.

Brugerne får gode/lave svartider, idet de kan bruge den server, som er tættest på dem. Men når et eller andet går ned, lukkes dele af systemet ned, og svartiderne bliver længere, eftersom der nu er mindre hardware til at udføre opgaverne.

Forestil dig en web-applikation, hvor du deler billeder med andre brugere (ja, tænk gerne på Flickr). Du vil gerne styre, hvem som har adgang til de enkelte billeder. Og når du ændrer rettighederne på billederne fra julefrokosten, så din kæreste ikke kan se dem længere, er det vigtigt, at alle servere i systemet ved det med det samme, for tænk nu, hvis din kæreste bruger en server, hvor ændringerne ikke er kommet frem. Konsistensen af data er vigtigere end skalerbarheden af applikationen.

Tilfældet A+P

Det andet tilfælde for et distribueret system er at give køb på konsistensen af data. Din applikation vil altid være tilgængelig, og sker der nedbrud, kan applikationen uden problemer klare det.

Men er det ikke farligt at lade data være inkonsistente i kortere eller længere perioder? Det kommer an på, hvilke data der er tale om. Er der tale om statusmeddelelser på et socialt netværksmedie (tænk bare på Facebook), gør det ikke noget, at ikke alle brugere samtidig kan se din seneste nye status. Men på et eller andet tidspunkt vil de se den – nemlig når data er propageret ud til alle serverne.

I stedet for at tale om et tilfælde med tilgængelighed og opdelingstolerance kan du også tale om, at systemet er ”på sigt konsistent” (eventually consistent). Der er ikke hele tiden konsistens, men data vil fylde ud til alle servere på sigt, og data vil på det tidspunkt være konsistent.

Dokumenthåndtering

I de kommende tre afsnit i denne serie om NoSQL vil tre forskellige databaser blive omtalt: Keyspace, CouchDB og MongoDB. For at give et bedre indtryk af, hvad programmering med NoSQL er, vil du se, hvordan en lille applikation til håndtering af dokumenter i form af et journaliseringssystem kan skrives.

Dokumenter er mange ting: brugsanvisninger, breve (både modtagne og afsendte), timesedler, billeder og så videre. Det er umiddelbart ikke en opgave, som er velegnet for en relationel database. Der vil være forskellige metadata tilknyttet dokumenterne, for eksempel har billederne ofte et »geotag« (længde- og breddegrad), men brugsanvisninger har ikke.

Næste gang

Med de teoretiske overvejelser på plads omkring NoSQL og distribuerede databaser vil næste gang byde på en mere praktisk tilgang til emnet. Databasen Keyspace er et open source-projekt, som kan bruges under Linux/UNIX, Mac OS X og Windows.

[themepacific_accordion]
[themepacific_accordion_section title="Fakta"]

Få mere at vide

[/themepacific_accordion_section]
[/themepacific_accordion]