Databasservrar och inbäddade databaser: en jämförelse av arkitektur och I/O-egenskaper

Databasserver
En databasserver avser en databas som körs som en fristående serverprocess och hanterar applikationers förfrågningar över nätverket. De flesta RDBMS som vi känner till väl, till exempel MySQL, PostgreSQL och Oracle DB, tillhör denna modell. Databasservrar har följande fördelar.
- Centraliserad hantering: Data hanteras samlat på ett ställe, vilket underlättar konsistens, säkerhet, säkerhetskopiering och återställning.
- Resursoberoende: Servern tilldelas egna CPU-, minnes- och lagringsresurser, vilket garanterar stabil prestanda oavsett applikationens tillstånd.
- Hög samtidighet och skalbarhet: Servern är optimerad för många användares samtidiga åtkomst, och horisontell skalning genom klustring eller replikering är relativt enkel.
Tack vare dessa egenskaper har databasservrar under de senaste decennierna etablerats som standard för mjukvaruinfrastruktur. Till följd av teknisk utveckling och förändrade miljöer har dock databasservrars nackdelar börjat framträda i vissa miljöer, och inbäddade databaser får därför på nytt uppmärksamhet som ett alternativ.
Ett nytt skifte: inbäddad databas
En inbäddad databas är en databasmotor som inte kräver någon separat serverprocess utan ingår i applikationen som ett bibliotek och körs inom samma process. SQLite, LevelDB och RocksDB är typiska exempel på inbäddade databaser. Bakgrunden till att inbäddade databaser har framstått som ett starkt alternativ i moderna teknikmiljöer är följande.
Framväxten av SSD
I tidigare system med HDD som huvudlagring var slumpmässig åtkomst betydligt långsammare än sekventiell läsning och skrivning. Därför var det centralt för prestandaoptimering att minimera diskens I/O och maximera minnescachning. Databasservrar anpassade sig till detta genom att driva omfattande cacheminnen och bearbeta skrivoperationer i batch, vilket gjorde det möjligt att övervinna HDD:ns fysiska begränsningar.
Framväxten av SSD har dock fullständigt förändrat dessa premisser. SSD:er har slumpmässig I/O-prestanda som är tusentals gånger snabbare än HDD:ers och även betydligt kortare latens. Som ett resultat har den tidigare uppfattningen att "diskens I/O är den största flaskhalsen" försvunnit, och i stället har fördröjningen vid åtkomst till en fjärrdatabasserver över nätverket börjat framträda som en ny flaskhals.
MSA och dataoberoende
Tidigare var det vanligt med en struktur där en stor monolitisk applikation var beroende av en enda centraliserad databas. Denna metod är enkel, men när tjänsternas omfattning ökar blir schemaändringar svårare, och eftersom alla tjänster delar samma databas blir kopplingen mellan dem alltför stark.
I moderna mikrotjänstarkitekturer betonas i stället principen "Database per Service" för att lösa detta problem. Genom att varje tjänst äger och kapslar in sitt eget dedikerade datalager säkerställs oberoende mellan tjänsterna, och felisolering och skalning blir enklare. I detta sammanhang blir den inbäddade databasen ett idealiskt val som datalager på tjänstenivå. Den är lätt och snabb och kan distribueras tillsammans med tjänstekoden, vilket passar mycket väl i en MSA-miljö.
Ett typiskt exempel är i Kubernetes-miljöer, där man ofta använder sidecar-mönstret för att placera en inbäddad databas bredvid applikationscontainern och därigenom optimera lokal databehandling. Detta minskar nätverksflaskhalsar och minimerar fördröjningen vid dataåtkomst.
Förenklad driftmiljö
En databasserver kräver komplexa driftsrutiner såsom installation, patchning, säkerhetskopiering, haveriåterställning, replikering och prestandaövervakning, och för detta krävs dedikerade DBA:er och kvalificerad driftpersonal. I synnerhet i storskaliga miljöer är denna administrativa börda mycket stor.
Inbäddade databaser lindrar i hög grad dessa problem. När databasen integreras i applikationen sker enhetstestning, bygge, versionshantering och distribution tillsammans, och någon separat serverdrift behövs därför inte. Dessutom skalas den inbäddade databasen med applikationen när den skalas horisontellt, och automatiserad hantering genom DevOps-kultur och CI/CD-pipelines blir möjlig. Särskilt i startups, småskaliga tjänster och utvecklingsmiljöer för prototyper minskar inbäddade databaser driftkomplexiteten avsevärt och ökar utvecklings- och distributionstakten markant.
Högpresterande systemspråk och ekosystemets utveckling
Tidigare var det vanligt att databasen och applikationen skrevs på olika språk. Till exempel skrevs högpresterande databasmotorer huvudsakligen i C eller C++, medan applikationer utvecklades i språk som Java, Python och PHP. Denna metod var effektiv för prestandaoptimering, men den hade begränsningar i form av minnessäkerhetsproblem, komplex samtidighetshantering, latens samt svårigheter med biblioteksintegration och distribution.
Under senare tid har dock moderna systemprogrammeringsspråk såsom Go och Rust vuxit fram, och dessa begränsningar har i hög grad lindrats. Särskilt Go är lämpligt inte bara för högpresterande applikationer utan även för att skriva lågnivåprogram såsom databasmotorer, vilket gör det möjligt att hantera både databasen och applikationen inom ett och samma språkekosystem.
Faktiskt används högpresterande inbäddade databaser såsom BadgerDB och PebbleDB i stor utsträckning i Golang. Detta innebär att inbäddade databaser inte längre enbart är lättviktiga alternativ till databasservrar, utan har etablerat sig som ett viktigt val med egen konkurrenskraft.
Slutsats
Under förutsättningar som kräver central hantering av storskaliga data, komplexa transaktioner och hög samtidighet är databasservern fortfarande den mest kraftfulla lösningen. I projekt med enskilda tjänster inom MSA-miljöer, IoT-edge-enheter, snabb prototypframtagning och där driftseffektivitet är viktig kan en inbäddad databas dock vara ett effektivare och mer rationellt val. Det avgörande är i slutändan att välja det verktyg som bäst passar den aktuella situationen och kraven, och utvecklingen av inbäddade databaser ger oss ett bredare och mer varierat urval av alternativ.