Eksterne komprimeringer i RocksDB-Cloud (Norsk)

(Hieu Pham) (10. juni , 2020)

Innledning

RocksDB er en LSM-lagringsmotor hvis vekst har spredt seg enormt de siste årene . RocksDB-Cloud er åpen kildekode og er fullt kompatibel med RocksDB, med tilleggsfunksjonen at all data blir holdbar ved automatisk å lagre den i skylagring (f.eks. Amazon S3).

Vi på Rockset bruker RocksDB-Cloud som en av byggesteinene i Rocksets distribuerte Converged Index . Rockset er designet med sky-native prinsipper, og et av de primære designprinsippene i en cloud-native database er å ha separasjon av beregning fra lagring. Vi vil diskutere hvordan vi utvidet RocksDB-Cloud til å ha en ren skille mellom lagringsbehov og databehov.

En komprimator, betjent av US Navy Seabees, som utfører jordpakking

RocksDBs LSM-motor

RocksDB-Cloud lagrer data i lokalt tilkoblet SSD eller spinnende disker. SSD eller spinndisken gir lagring som er nødvendig for å lagre dataene den serverer. Nye skriv til RocksDB-Cloud skrives til et minnetabell i minnet, og når memtabellen er full, skylles den til en ny SST-fil i lagringen.

Å være en LSM-lagringsmotor, et sett av bakgrunnstråder brukes til komprimering, og komprimering er en prosess for å kombinere et sett med SST-filer og generere nye SST-filer med overskrevne nøkler og slettede nøkler renset fra utdatafilene. Komprimering trenger mye beregningsressurser. Jo høyere skrivehastighet i databasen, jo flere beregningsressurser er nødvendig for komprimering, fordi systemet bare er stabilt hvis komprimering er i stand til å holde tritt med nye skrivinger til databasen din.

Problemet når beregning og lagring er ikke disaggregerte

I en typisk RocksDB-basert system, komprimering skjer på CPUer som er lokale på serveren som også er lagringsplass. I dette tilfellet er ikke beregning og lagring oppdelt. Og dette betyr at hvis skrivehastigheten din øker, men den totale størrelsen på databasen din forblir den samme, må du dynamisk skaffe flere servere, spre dataene dine på alle disse serverne og deretter utnytte den ekstra beregningen på disse serverne for å holde tritt med komprimeringsbelastning.

Dette har to problemer:

  • Å spre dataene dine på flere servere er ikke øyeblikkelig fordi du må kopiere mye data for å gjøre det. Dette betyr at du ikke kan reagere raskt på en raskt skiftende arbeidsmengde.
  • Lagringskapasitetsutnyttelsen på hver av serverne dine blir veldig lav fordi du sprer dataene dine til flere servere. Du mister prisen på ytelse på grunn av all ubrukt lagring på serverne dine.

Vår løsning

Den primære grunnen til at RocksDB-Cloud er egnet for å skille ut komprimeringsberegning og lagring er fordi det er en LSM-lagringsmotor. I motsetning til en B-Tree-database oppdaterer RocksDB-Cloud aldri en SST-fil når den er opprettet. Dette betyr at alle SST-filene i hele systemet er skrivebeskyttet, bortsett fra den minste delen av dataene i det aktive minnebordet. RocksDB-Cloud vedvarer alle SST-filer i en skylagringsobjektbutikk som S3, og disse skyobjektene er trygt tilgjengelige fra alle serverne dine fordi de er skrivebeskyttet.

Så, vår idé er at hvis en RocksDB -Cloud server A kan kapsle inn en komprimeringsjobb med settet med skyobjekter og deretter sende forespørselen til en ekstern statsløs server B – og serveren B kan hente de relevante objektene fra skybutikken, gjøre komprimeringen, produsere et sett med utdata SST-filer som skrives tilbake til skyobjektbutikken, og kommuniserer deretter informasjonen tilbake til server A-vi har i hovedsak skilt ut lagringen (som ligger i server A) fra komprimeringsberegningen (som ligger i server B). Server A har lagring, og mens server B ikke har permanent lagring, men bare beregningen som trengs for komprimering. Voila!

RocksDB pluggbar komprimerings-API

Vi utvidet basen RocksDB API med to nye metoder som gjør komprimeringsmotoren i RocksDB eksternt pluggbar. I db.h introduserer vi et nytt API for å registrere en komprimeringstjeneste.

Status RegisterPluggableCompactionService(std::unique_ptr);

Denne API-en registrerer pluginet som brukes til å utføre komprimeringsjobben av RocksDB. Ekstern komprimering skjer i to trinn: Run og InstallFiles. Derfor vil pluginet PluggableCompactionService ha to 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 der komprimeringskjøringen skjer.I vår eksterne komprimeringsarkitektur vil Run sende en RPC til et eksternt komprimeringsnivå, og motta et komprimeringsresultat som blant annet har listen over nylig komprimerte SST-filer.

InstallFiles er der RocksDB installerer de nylig komprimerte SST-filene fra skyen (remote_paths) til sin lokale database (local_paths).

Rocksets komprimeringsnivå

Nå skal vi vise hvordan vi brukte den pluggbare komprimeringstjenesten som er beskrevet ovenfor i Rocksets komprimeringstjeneste. Som nevnt ovenfor sender det første trinnet, Run, en RPC til et eksternt komprimeringsnivå med komprimeringsinformasjon, slik som SST-filnavn og komprimeringsinformasjon. Vi kaller verten som utfører denne komprimeringsjobben en kompaktor em. ghost -modus. Hva dette betyr, RocksDB-Cloud åpner den lokale databasen med bare nødvendige metadata uten å hente alle SST-filer fra skylagringen. Når den åpner RocksDB-forekomsten i ghost -modus, vil den utføre komprimeringsjobben, inkludert å hente de nødvendige SST-filene, komprimere dem og laste opp de nylig komprimerte SST-filene til en midlertidig lagring i skyen.

Her er alternativene for å åpne 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;

Det er flere utfordringer vi møtte under utviklingen av komprimeringsnivået, og våre løsninger:

Forbedre hastigheten på å åpne RocksDB-Cloud i ghost modus

Under åpningen av en RocksDB-forekomst, i tillegg til å hente alle SST-filene fra skyen (som vi har deaktivert med ghost -modus), er det flere andre operasjoner som kan redusere åpningsprosessen, spesielt å få listen over SST-filer og få størrelsen på hver SST-fil. Vanligvis, hvis alle SST-filene ligger i lokal lagring, vil ventetiden til disse get-filstørrelsesoperasjonene være liten. Når komprimatoren åpner RocksDB-Cloud, vil hver av disse operasjonene imidlertid resultere i en ekstern forespørsel til skylagring, og den totale kombinerte ventetiden blir uoverkommelig dyr. Etter vår erfaring, for en RocksDB-Cloud-forekomst med tusenvis av SST-filer, vil det ta opptil et minutt å åpne det på grunn av tusenvis av forespørsler om get-filstørrelse til S3. For å omgå denne begrensningen, introduserte vi forskjellige alternativer i RocksDB-Cloud-alternativene for å deaktivere disse RPC-ene under åpningen. Som et resultat går den gjennomsnittlige åpningstiden fra 7 sekunder til 700 millisekunder.

Deaktiver L0 -> L0 komprimering

Ekstern komprimering er en avveining mellom hastigheten til en enkelt komprimering og muligheten til å kjøre flere komprimeringsjobber parallelt. Det er fordi hver eksterne komprimeringsjobb naturlig nok vil være tregere enn den samme komprimeringen som ble utført lokalt på grunn av kostnadene for dataoverføring i skyen. Derfor vil vi minimere flaskehalsen i komprimeringsprosessen, der RocksDB-Cloud ikke kan parallellisere, så mye som mulig.

I LSM-arkitekturen er L0-> L1-komprimering vanligvis ikke parallelliserbar fordi L0-filer har overlappende områder. Derfor, når en L0-> L1-komprimering oppstår, har RocksDB-Cloud muligheten til også å utføre L0-> L0-komprimering, med målet å redusere antall L0-filer og forhindre skriveboder på grunn av at RocksDB-Cloud treffer L0-filen grense. Avviket er imidlertid at hver L0-fil vil vokse seg større i størrelse etter hver L0-> L0-komprimering.

Etter vår erfaring gir dette alternativet mer problemer enn fordelene det gir, fordi det å ha større L0-filer resulterer i en mye lengre L0-> L1-komprimering, noe som forverrer flaskehalsen på RocksDB-Cloud. Derfor deaktiverer vi L0-> L0-komprimering, og lever med det sjeldne problemet å skrive stall i stedet. Fra eksperimentet vårt fanger RocksDB-Cloud-komprimering innkommende skrivinger mye bedre.

Du kan bruke den nå

RocksDB-Cloud er et åpen kildekildeprosjekt, slik at vårt arbeid kan bli utnyttet av andre RocksDB-utviklere som ønsker å dra fordeler ved å skille ut komprimeringsberegningen fra lagringsbehovet. Vi kjører den eksterne komprimeringstjenesten i produksjon nå. Den er tilgjengelig med 6.7.3-utgivelsen av RocksDB-Cloud. Vi diskuterer alle ting om RocksDB-Cloud i den offentlige Slack-kanalen på http://bit.ly/rockset-community-channel .

Forfattere:

Hieu Pham – Software Engineer, Rockset
Dhruba Borthakur – CTO, Rockset

Opprinnelig publisert på https: // rockset.com 4. juni 2020.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *