Eksterne komprimeringer i RocksDB-Cloud

(Hieu Pham) (10. juni , 2020)

Introduktion

RocksDB er en LSM-lagringsmotor, hvis vækst har vokset enormt i de sidste par år . RocksDB-Cloud er open source og er fuldt kompatibel med RocksDB, med den ekstra funktion, at alle data gøres holdbare ved automatisk at gemme dem i skylagring (f.eks. Amazon S3).

Vi på Rockset bruger RocksDB-Cloud som en af ​​byggestenene i Rocksets distribuerede Konvergerede indeks . Rockset er designet med cloud-native principper, og et af de primære designprincipper i en cloud-native database er at have adskillelse af beregning fra lager. Vi vil diskutere, hvordan vi udvidede RocksDB-Cloud til at have en ren adskillelse af dets lagerbehov og dets beregningsbehov.

En komprimator, der drives af US Navy Seabees, der udfører jordpakning

RocksDBs LSM-motor

RocksDB-Cloud gemmer data i lokalt tilsluttet SSD eller roterende diske. SSDen eller den spindende disk giver den nødvendige lagerplads til at gemme de data, den serverer. Nye skrivninger til RocksDB-Cloud skrives til en memebord i hukommelsen, og når memtabellen er fuld, skylles den til en ny SST-fil i lageret.

At være en LSM-lagermotor, et sæt af baggrundstråde bruges til komprimering, og komprimering er en proces til at kombinere et sæt SST-filer og generere nye SST-filer med overskrevne nøgler og slettede nøgler renset fra outputfilerne. Komprimering har brug for mange beregningsressourcer. Jo højere skrivehastigheden i databasen er, jo flere beregningsressourcer er der behov for komprimering, fordi systemet kun er stabilt, hvis komprimeringen er i stand til at holde trit med nye skrivninger til din database.

Problemet ved beregning og lagring er ikke adskilt

I en typisk RocksDB-baseret system, komprimering forekommer på CPUer, der er lokale på den server, der også er vært for lageret. I dette tilfælde er beregning og lagring ikke adskilt. Og det betyder, at hvis din skrivehastighed stiger, men den samlede størrelse af din database forbliver den samme, skal du dynamisk tilvejebringe flere servere, sprede dine data i alle disse servere og derefter udnytte den ekstra beregning på disse servere for at holde trit med komprimeringsbelastning.

Dette har to problemer:

  • At sprede dine data på flere servere er ikke øjeblikkelig, fordi du skal kopiere en masse data for at gøre det. Dette betyder, at du ikke kan reagere hurtigt på en hurtigt skiftende arbejdsbyrde.
  • Udnyttelsen af ​​lagerkapacitet på hver af dine servere bliver meget lav, fordi du spreder dine data til flere servere. Du mister pris / ydelsesforholdet på grund af al ubrugt lagerplads på dine servere.

Vores løsning

Den primære årsag til, at RocksDB-Cloud er egnet for at adskille komprimeringsberegning og lagring er, fordi det er en LSM-lagringsmotor. I modsætning til en B-Tree-database opdaterer RocksDB-Cloud aldrig en SST-fil, når den er oprettet. Dette betyder, at alle SST-filer i hele systemet er skrivebeskyttet undtagen den minimale del af data i din aktive memtable. RocksDB-Cloud fortsætter alle SST-filer i en cloud-lagringsobjekt som S3, og disse skyobjekter er sikkert tilgængelige fra alle dine servere, fordi de er skrivebeskyttede.

Så vores idé er, at hvis en RocksDB -Cloud-server A kan indkapsle et komprimeringsjob med sit sæt skyobjekter og derefter sende anmodningen til en ekstern statsløs server B-og at server B kan hente de relevante objekter fra skybutikken, udføre komprimeringen, producere et sæt output SST-filer, der skrives tilbage til cloud-objektlageret, og derefter kommunikerer disse oplysninger tilbage til server A-vi har i det væsentlige adskilt lageret (som ligger i server A) fra komprimeringsberegningen (som ligger i server B). Server A har opbevaringen, og mens server B ikke har permanent lager, men kun den nødvendige beregning til komprimering. Voila!

RocksDB plugbar kompakterings-API

Vi udvidede basen RocksDB API med to nye metoder, der gør komprimeringsmotoren i RocksDB ekstern tilslutning. I db.h introducerer vi en ny API til at registrere en komprimeringstjeneste.

Status RegisterPluggableCompactionService(std::unique_ptr);

Denne API registrerer det plugin, der bruges til at udføre komprimeringsjobbet af RocksDB. Fjernkomprimering sker i to trin: Run og InstallFiles. Derfor ville pluginet PluggableCompactionService have 2 APIer:

Status Run(const PluggableCompactionParam& job, PluggableCompactionResult* result) std::vector InstallFiles(
const std::vector& remote_paths,
const std::vector& local_paths,
const EnvOptions& env_options, Env* local_env)

Run er, hvor komprimeringsudførelsen sker.I vores fjernkomprimeringsarkitektur ville Run sende en RPC til et fjernkomprimeringsniveau og modtage et komprimeringsresultat, der blandt andet har listen over nyligt komprimerede SST-filer.

InstallFiles er hvor RocksDB installerer de nyligt komprimerede SST-filer fra skyen (remote_paths) til sin lokale database (local_paths).

Rocksets komprimeringsgrad

Nu viser vi, hvordan vi brugte den pluggbare komprimeringstjeneste, der er beskrevet ovenfor i Rocksets komprimeringstjeneste. Som nævnt ovenfor sender det første trin Run en RPC til et eksternt komprimeringsniveau med komprimeringsinformation, såsom input SST-filnavne og komprimeringsinformation. Vi kalder værten, der udfører dette komprimeringsjob, en kompaktor.

komprimatoren , når den modtager komprimeringsanmodningen, åbner en RocksDB-Cloud-forekomst i spøgelse -tilstand. Hvad dette betyder er, at RocksDB-Cloud åbner den lokale database med kun nødvendige metadata uden at hente alle SST-filer fra skylageret. Når det først åbner RocksDB-forekomsten i ghost -tilstand, udfører det derefter komprimeringsjobbet, herunder hentning af de nødvendige SST-filer, komprimere dem og uploade de nykomprimerede SST-filer til en midlertidig lagerplads i skyen.

Her er mulighederne for at åbne RocksDB-Cloud i komprimatoren :

rocksdb::CloudOptions cloud_options; cloud_options.ephemeral_resync_on_open = false; cloud_options.constant_sst_file_size_in_sst_file_manager = 1024; cloud_options.skip_cloud_files_in_getchildren = true;rocksdb::Options rocksdb_options;
rocksdb_options.max_open_files = 0; rocksdb_options.disable_auto_compactions = true; rocksdb_options.skip_stats_update_on_db_open = true; rocksdb_options.paranoid_checks = false; rocksdb_options.compaction_readahead_size = 10 * 1024 * 1024;

Der er flere udfordringer vi stod over for under udviklingen af ​​komprimeringsniveauet og vores løsninger:

Forbedre hastigheden ved åbning af RocksDB-Cloud i ghost mode

Under åbningen af ​​en RocksDB-forekomst udover at hente alle SST-filer fra skyen (som vi har deaktiveret med ghost -tilstand), er der flere andre handlinger, der kan bremse åbningsprocessen, især at få listen over SST-filer og få størrelsen på hver SST-fil. Normalt, hvis alle SST-filerne ligger i lokal opbevaring, ville latenstiden for disse operationer med get-filstørrelse være lille. Men når komprimatoren åbner RocksDB-Cloud, vil hver af disse operationer resultere i en fjernanmodning til skylageret, og den samlede kombinerede latenstid bliver uoverkommeligt dyr. Efter vores erfaring vil det for en RocksDB-Cloud-forekomst med tusindvis af SST-filer tage op til et minut på grund af tusindvis af anmodninger om get-filstørrelse til S3. For at omgå denne begrænsning introducerede vi forskellige muligheder i RocksDB-Cloud-indstillingerne for at deaktivere disse RPCer under åbningen. Som et resultat går den gennemsnitlige åbningstid fra 7 sekunder til 700 millisekunder.

Deaktiver L0 -> L0 komprimering

Fjernkomprimering er en kompromis mellem hastigheden af ​​en enkelt komprimering og muligheden for at køre flere komprimeringsjob parallelt. Det skyldes, at hvert fjernkomprimeringsjob naturligvis ville være langsommere end den samme komprimering, der blev udført lokalt på grund af omkostningerne ved dataoverførsel i skyen. Derfor vil vi gerne minimere flaskehalsen i komprimeringsprocessen, hvor RocksDB-Cloud ikke kan parallelisere så meget som muligt.

I LSM-arkitekturen er L0-> L1-komprimering normalt ikke paralleliserbar, fordi L0-filer har overlappende intervaller. Derfor, når en L0-> L1-komprimering opstår, har RocksDB-Cloud evnen til også at udføre L0-> L0-komprimering med det formål at reducere antallet af L0-filer og forhindre skriveboder på grund af RocksDB-Cloud, der rammer L0-filen begrænse. Afvejningen er dog, at hver L0-fil vil vokse sig større i størrelse efter hver L0-> L0-komprimering.

Efter vores erfaring skaber denne mulighed mere problemer end de fordele, det medfører, fordi det har større L0-filer resulterer i en meget længere L0-> L1-komprimering, hvilket forværrer flaskehalsen i RocksDB-Cloud. Derfor deaktiverer vi L0-> L0-komprimering og lever i stedet med det sjældne problem med skrivebod. Fra vores eksperiment indhenter RocksDB-Cloud-komprimering de indgående skrivninger meget bedre.

Du kan bruge det nu

RocksDB-Cloud er et open source-projekt, så vores arbejde kan være gearet af enhver anden RocksDB-udvikler, der ønsker at få fordele ved at adskille deres komprimeringsberegning fra deres lagerbehov. Vi kører fjernpakningstjenesten i produktion nu. Den er tilgængelig med 6.7.3-udgivelsen af ​​RocksDB-Cloud. Vi diskuterer alle ting om RocksDB-Cloud i den offentlige Slack-kanal på http://bit.ly/rockset-community-channel .

Forfattere:

Hieu Pham – Softwareingeniør, Rockset
Dhruba Borthakur – CTO, Rockset

Oprindeligt offentliggjort på https: // rockset.com den 4. juni 2020.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *