
Jag heter Yuri och Àr chef för systemadministrationsteamet pÄ Citymobil. Idag ska jag dela med mig av mina erfarenheter av att arbeta med thin provisioning-teknik för filsystem. Linux Jag ska förklara hur det kan tillÀmpas i ett företags CI/CD-processer. Vi ska undersöka en situation dÀr vi, för att automatiskt testa kod nÀr den levereras till produktion, behöver lÀs- och skrivkopior av en MySQL-databas som ligger sÄ nÀra produktionsversionen som möjligt.
Inledning: Varför ge dÄliga rÄd?
En logisk frÄga, eftersom det finns beprövade mekanismer för att migrera databasscheman till testmiljöer. Varför ens utöka det huvudsakliga icke-skÀrda DBMS till sÄdana volymer? Och inte all data behövs för testning. Jag ska försöka förklara.
För ungefÀr ett Är sedan, mot bakgrund av den aktiva tillvÀxten av vÄr taxiaggregator (under 2018 ökade genomförda resor cirka 15 gÄnger), ökade datavolymen, belastningen pÄ servrarna och frekvensen av utrullningar. Vi hamnade i följande situation:
- Den huvudsakliga MySQL-databasen vÀxte till cirka 1000 tabeller pÄ totalt 2,5 TB och fortsatte att vÀxa.
- Det fanns inget sÀtt att snabbt bli skÀrrad och förstöra basen. Detta var inte tillÄtet av det gamla tillvÀgagÄngssÀttet "Jag skriver in i databasen vad jag vill och hur jag vill", ett gÀng JOINs och interna tabellberoenden.
- Det fanns ingen mekanism för att migrera databasschemat till testmiljöer.
- Det gjordes ingen automatisk testning av koden under distributionen.
Jag ville lösa det sista problemet sÄ snabbt som möjligt. Postman-tester hade redan skrivits för att testa den huvudsakliga PHP-monoliten, men saknade en uppdaterad databas. Samtidigt kunde vi inte skapa en replik pÄ natten, göra den till en mÀstare och lÄta den rivas i stycken under dagen: ett mycket stort antal utrullningar och Àndringar, inklusive i data- och databasschemat, skulle ha gjorts stativet obrukbart mitt pÄ dagen. Och att begrÀnsa lanseringarna till bara en arbetsdag skulle vara ineffektivt.
ĂndĂ„ var uppgiften klar: vi fick den första arbetsmontern inom tvĂ„ veckor. Den har genomgĂ„tt mĂ„nga förĂ€ndringar under det senaste Ă„ret och fortsĂ€tter att anvĂ€ndas.
DÀrefter kommer jag att beskriva i detalj alla steg och stadier i utvecklingen av vÄr lösning. Du kommer att se att denna metod förtjÀnar sin rÀtt att existera.
Vad Àr "tunn redundans"?
Detta Àr en hÄrd- eller mjukvaruteknik (ett annat namn Àr glesa volymer) som gör att du kan allokera mer av den nödvÀndiga resursen Àn vad som Àr tillgÀngligt. I det hÀr fallet mÄste den tilldelade volymen uppfylla kriterierna precis-tillrÀckligt (sÄ mycket som behövs) och just-in-time (för den tid som krÀvs). I grund och botten anvÀnds tunn reservation i olika lagringssystem för att tillhandahÄlla diskutrymme i de erforderliga volymerna, som överstiger de som faktiskt Àr tillgÀngliga. Tekniken stöds av olika filsystem, till exempel LVM2, ZFS, BTRFS. Det anvÀnds ofta i virtualiseringshypervisorer. Tunn sÀkerhetskopiering gjorde att vi snabbt kunde skapa frÄn ögonblicksbilder av huvudsektionen med data sÄ mÄnga kopior av detta avsnitt som vi behövde (datakatalogen för MySQL DBMS).
Första stativ, Thin LVM-teknik
Det hÀr kapitlet kan ocksÄ kallas "Hur man gör de snabbaste ögonblicksbilderna av stora datamÀngder med hjÀlp av , vilket minskar stabiliteten i filsystemet och MySQL DBMS till oanstÀndiga nivÄer."
Eftersom vi redan anvÀnde LVM för att bygga de viktigaste OS-partitionerna, bestÀmde vi oss för att börja med det. Till att börja med behövde vi en separat fysisk maskin - en kopia av vÄr huvudsakliga MySQL-databas, pÄ vilken vi kunde skapa en ögonblicksbild av repliken pÄ begÀran och höja den bredvid en separat MySQL-instans. Under testningen tillÀt vi modifieringsoperationer att anvÀndas pÄ den hÀr instansen, och efter att testerna slutförts tog vi bort den pÄ ett sÀkert sÀtt. Serverkonfigurationen var sÄ hÀr:
- 2 x Intel Silver 4114 (10x2,2 GHz HT)
- 8 x 32 GB DDR4
- 8 x 1920 GB Intel SSD i Adaptec RAID-kontroller i RAID-10
Du kan skriva en separat artikel om Àmnet att vÀlja mellan en RAID-kontroller och programvara RAID MD. LÄt mig bara sÀga att vÄrt val pÄverkades av tvÄ faktorer:
- NÀr problemet formulerades installerade vi alla DBMS pÄ RAID-kontroller, sÄ vi kan sÀga att detta hÀnde historiskt.
- Skillnaden i prestanda mellan syntetiska filsystemtester och tester med olika MySQL-operationer var minimal.
Vi delade upp den resulterande RAID-10: vi skapade en enda volymgrupp (VG) för hela volymen (med overhead pĂ„ cirka 6,7 ââGB) och skapade en logisk partition (Logical Volume, LV) för ett 50 GB-system. I en normal situation definierar vi resten av utrymmet som MySQL-sektionen. Men vi behövde tunn backup, sĂ„ först skapade vi en sĂ„ kallad pool, i vilken vi skapade en sektion för /var/lib/mysql med 3,5 TB (baserat pĂ„ de uppskattade databasvolymerna):
lvcreate -l 100%FREE -T vga/thin
lvcreate -V 3.5T -T vga/thin -n mysqlVi formaterade partitionen i ext4, monterade den, spelade in en replik och fick originalstativet. Sedan gjorde vi en bindning i form av ett API, som ska skapa ögonblicksbilder, höja en MySQL-databasinstans pĂ„ en given port och radera den skapade instansen. Eftersom detta uteslutande anvĂ€nder systemanrop, valde vi vanlig bash som skriptsprĂ„k och implementerade en lösning med öppen kĂ€llkod för att ansluta HTTP â bash API , skrivet i Go.
NÄgon gÄng kommer vi att slÀppa vÄra bash-skript till öppen kÀllkod, men för tillfÀllet kommer jag helt enkelt att beskriva huvudalgoritmen:
Skapa huvudsnapmain för ögonblicksbild:
- Stoppar huvudrepliken.
- Vi sÀtter ett block pÄ operationer med snapmain ögonblicksbilden.
- Skapa en ny ögonblicksbild.
- Starta MySQL och ta bort lÄset.
Skapa en databas pÄ en godtycklig port frÄn snapmain:
- Vi sÀtter ett lÄs pÄ en specifik databasinstans (port).
- Vi kontrollerar om skapandet av huvudögonblicksbilden Àr blockerad. Om det finns dÀr, vÀntar vi och kontrollerar igen var 5:e sekund.
- Vi kontrollerar om det finns en gammal LV-del av instansen.
3.1 Om det finns, anvÀnd kill -9 för att stoppa MySQL-instansen och ta bort LV-partitionen. - Vi skapar en ny instans frÄn snapmain.
- Vi förbereder och monterar kataloger för detta fall.
- Vi tar bort attributen för slaven (filerna) och startar MySQL-instansen.
- LÄt oss göra honom till en mÀstare.
- Vi tar bort blockeringen.
Ta bort en databas pÄ en slumpmÀssig port:
- Vi sÀtter ett lÄs pÄ en specifik databasinstans (port).
- Döda MySQL-instansen med kill -9.
- LÄt oss avmontera katalogerna.
- Vi tar bort LV-partitionen och tar bort lÄset.
Exempelkommandon för kloning av partitioner av en ny databasinstans:
lvcreate -n stage_3307 -s vga/snapmain
lvchange -ay -K vga/stage_3307
mount -o noatime,nodiratime,data=writeback /dev/mapper/vga-stage_3307 /mnt/stage_3307Nu ska jag berÀtta om huvudproblemet som vi stötte pÄ nÀr vi anvÀnde tunn redundans. Vi har fastnat för prestanda hos SSD-enheter. Detta hÀnde pÄ grund av funktionerna i Thin LVM: den fungerar i princip pÄ enhetsnivÄ med lÄgnivÄbitar med en standardstorlek pÄ 4 MB. Hur det sÄg ut:
- Skapa en ögonblicksbild frÄn huvudsektionen /var/lib/mysql.
- Vi börjar replikera för att komma ikapp med mastern.
- Varje förÀndring i replikatabellerna tvingar gamla, oförÀndrade databitar att lagras i ögonblicksbildssektionen.
- Varje Àndring av en upphöjd testinstans gör att gamla, omodifierade databitar lagras i en klonad ögonblicksbildssektion för den instansen.
- Vi fÄr en belastning pÄ 100 % I/O-operationer pÄ enheten, en avmattning av alla operationer och en gradvis fördröjning av repliken.
- I slutet av arbetsdagen fÄr vi en monter som ligger flera timmar efter.
Hur vi hanterade detta för att fÄ ett mer vettigt resultat (huvudpunkter):
RAID-kontroller:
- Alla typer av cachning Àr inaktiverade som standard.
- StÀll in Äterskrivning (nÀr data kommer in i bufferten slutförs skrivningen innan den faktiska lagringen pÄ disken utförs).
Filsystem:
- Vid monteringspunkten /var/lib/mysql skrev vi noatime,nodiratime,data=Äterskrivning
- Inaktiverade ext4-loggning med tune2fs.
MySQL:
- Förskrivet innodb_flush_method = O_DSYNC (ökad inspelningshastighet, vilket minskar tillförlitligheten).
- Loggning Àr inaktiverad, vi behöver inga loggar.
- Förskrivet innodb_buffer_pool_size = 4G (Ju mindre InnoDB-poolstorleken Àr, desto snabbare stÀngs MySQL av nÀr den stoppas, och desto snabbare skapar vi en ögonblicksbild).
Detta Àr inte en komplett lista, speciellt för MySQL. De ÄterstÄende Àndringarna Àr dock mindre och Àr ofta inte alltid eller exakt tillÀmpliga. Till exempel, i ett försök att ladda ur diskarna, tog vi till och med bort innodb_parallel_doublewrite_path i /dev/shm, vilket i vissa fall sparade oss upp till 5 sekunder nÀr vi startade en felaktigt avslutad instans.
Varför stoppar vi MySQL innan vi tar en ögonblicksbild? NÀr allt kommer omkring kan vi ta bort det frÄn en fungerande replik. Det stÀmmer, men den nya databasinstansen pÄ denna ögonblicksbild kommer att anses vara skadad som standard och kommer att krÀva en fullstÀndig genomsökning vid start. Att stoppa en replik Àr definitivt snabbare, Àven om det blir den lÀngsta operationen i hela processen.
Som ett resultat fick vi mer acceptabla tidpunkter och ett fĂ€rdigt stĂ€ll. Ăven om, som kan ses frĂ„n den mest vĂ€ltaliga grafen över replikeringsfördröjningen för huvudrepliken, Ă€r situationen fortfarande lĂ„ngt ifrĂ„n idealisk:

Bland andra brister Àr det vÀrt att notera den praktiska omöjligheten att övervaka Thin LVM-poolen: förutom systemstandardens iostatfunktioner Àr det omöjligt att förstÄ till exempel vilket poolelement som för nÀrvarande producerar den största belastningen pÄ filsystemet.
Separat Àr det vÀrt att notera en stor nackdel i samband med optimeringen som beskrivs ovan: vi fick ett YOLO-stÀll. UngefÀr en gÄng var eller varannan mÄnad kunde ext4 inte motstÄ sÄdant missbruk och gick sönder irreparabelt, vilket krÀvde omformatering och Äteruppladdning av repliken. Efter att ha vunnit i fart förstörde vi hopplöst stabiliteten.
Vilka mÀtvÀrden ska du övervaka nÀr du anvÀnder Thin LVM:
- Tunn pool data %
- Tunn pool metadata %
Om vÄr monter överlever att utrymmet för data tar slut (det rÀcker för att rengöra diskarna), kommer det slut pÄ utrymme för metadata att leda till en fullstÀndig kollaps av poolen och behovet av att bygga om den frÄn grunden.
Filsystemet i poolen blir mycket fragmenterat med tiden. Jag rekommenderar att du kör cron-kommandot en gÄng om dagen fstrim -v /var/lib/mysql.
Delsummor:
- Tekniken Àr enkel att tillÀmpa, precis som LVM sjÀlv, och krÀver inga speciella ingenjörsbehörighet.
- Den Àr vÀl lÀmpad för smÄ och inte alltför laddade databaser. Ju mindre databasen Àr, desto fÀrre bitar rör sig i filsystemet i poolen, och desto lÀgre belastning pÄ diskarna.
- För vÄr uppgift började vi leta efter andra lösningar, som kommer att diskuteras i nÀsta avsnitt.
Andra stativ, ZFS-teknik
Jag arbetade med ZFS-filsystemet för lÀnge sedan, men pÄ den tiden fungerade ZFS pÄlitligt och bra pÄ sin ursprungliga Solaris-operativsystemfamilj. Det fanns en portering till FreeBSD med en ganska bra implementeringsnivÄ. Det fanns ocksÄ en oavslutad portering till Linux, vilket fÄ personer anvÀnde. PÄ grund av sin B-trÀdsstruktur för datalagring (för övrigt har MySQL:s InnoDB samma lagringsstruktur) presterade ZFS dÄligt pÄ installationer med ett mycket stort antal filer. Detta, i kombination med behovet av att lÀra sig allt innan anvÀndning, ledde till att jag anvÀnde detta filsystem under lÄng tid. Ext4 och xfs dök upp och blev standarden. Men med tanke pÄ att ZFS Àr mer Àn lÀmpligt för vÄra behov, och Linux-versionen, att döma av recensionerna, har vuxit till en helt vettig produkt (Àven om den inte stöds fullt ut, vilket Àr anledningen till att det bara Àr möjligt att installera ett system pÄ ZFS frÄn grunden med hjÀlp av olika voodoo-tekniker), bestÀmde vi oss för att prova.
Av uppenbara skÀl valdes stativet med en liknande konfiguration (med undantag för RAID-kontrollern). Vi installerade Ätta 1920 GB SSD-enheter. Det fanns ingen lust att skriva vÄr egen nÀtverksbild för att ladda upp servern till blotta ZFS, sÄ vi bet av 50 GB av alla diskar och gjorde MD RAID-10 pÄ dem för systemet. De ÄterstÄende 1950 GB pÄ varje disk kombinerades till en ZFS-analog av RAID-10:
zpool create zpool mirror /dev/sda2 /dev/sdb2 mirror /dev/sdc2 /dev/sdd2 mirror /dev/sde2 /dev/sdf2 mirror /dev/sdg2 /dev/sdh2Vi skapade sektioner för MySQL:
zfs create zpool/mysql
zfs set compression=gzip zpool/mysql
zfs set recordsize=128k zpool/mysql
zfs set atime=off zpool/mysql
zfs create zpool/mysql/data
zfs set recordsize=16k zpool/mysql/data
zfs set primarycache=metadata zpool/mysql/data
zfs set mountpoint=/var/lib/mysql zpool/mysql/dataObservera att vi har aktiverat inbyggd gzip-datakomprimering. Vi har mÄnga processorresurser pÄ servern och de anvÀnds inte fullt ut. Som ett resultat av detta förvandlades 3 TB av vÄr databas till 1,6 TB, och eftersom den svaga lÀnken, som i föregÄende fall, Àr den maximala diskprestandan. mindre data desto bÀttre, vi Vi fÄr en fantastisk bonus frÄn ZFS frÄn första början! Under rusningstid vid full belastning tar det upp till 4 kÀrnor för att hÄlla gzip igÄng, men vi har inget emot det.
DÄ gick implementeringen snabbare. MySQL-replikinstÀllningarna överfördes frÄn LVM-stativet som en kopia. Jag var tvungen att lÀgga lite tid pÄ att skriva om skripten med hjÀlp av ZFS-kommandon, men i allmÀnhet förblev algoritmerna desamma. Ett exempel pÄ hur du skapar en ögonblicksbild:
zfs set snapdir=visible zpool/mysql/data
zfs create zpool/stage_3307
zfs clone zpool/mysql/data@snapmain zpool/stage_3307/data
zfs set mountpoint=/mnt/stage_3307 zpool/stage_3307/dataFrÄn ytterligare justering: vi flyttade ZFS-partitioner med metadata och l2arc- och zil-loggar till minnet. För vÄr uppgift, som det visade sig senare, var detta överflödigt, men för nÀrvarande lÀmnade vi denna optimering, det Àr lÀtt att Àndra om det behövs. En av de negativa effekterna Àr att efter omstart av servern mÄste du Äterskapa motsvarande minnesomrÄden. Ingen data gÄr förlorad. Zpool-statusklipp:
logs
/dev/shm/zil_slog.img ONLINE 0 0 0
cache
/dev/shm/l2arc.img ONLINE 0 0 0I den hÀr konfigurationen började vi testa stativet och fick utmÀrkta resultat: med tvÄ simultant körande databasinstanser (och en aktiv huvudreplik) i ögonblicksbilder fick vi 50-60% diskutnyttjande.
Vi blev av med vÄrt huvudproblem, som kan ses i grafen för replikeringsfördröjning (jÀmför med föregÄende graf i avsnittet Thin LVM):

Utöver och tack vare detta har vi pÄskyndat alla operationer avsevÀrt: att helt skapa en ögonblicksbild med att stoppa och starta en replik tar upp till 40 sekunder, att distribuera en ny MySQL-instans frÄn en ögonblicksbild tar upp till 20 sekunder. Vilket Àr mer Àn tillfredsstÀllande för bÄde oss och vÄra programkodstester.
Delsummor:
- Resultaten tillfredsstÀllde helt vÄrt behov av att skaffa en kopia av produktionsdatabasen för att testa koden.
- Tekniken krÀver intrÀde: du mÄste förstÄ vad ZFS Àr och hur du arbetar med det.
- Vi har inte kontrollerat den aktuella statusen för ZFS med ett stort antal (över 1 miljon) smÄ filer. Men vi antar att problemet kvarstÄr, sÄ jag skulle inte rekommendera detta filsystem för nÄgon fillagring.
Vad hÀnder nu?
Det finns inget annat att göra inom ramen för montern vi Àr nöjda med resultatet. Kanske kommer vi i framtiden att lÀgga till uteslutningar av tabeller som inte behövs för testning till monterreplikeringen, vilket kommer att minska storleken pÄ databasen ytterligare. Vi har inte testat BTRFS-systemet och dess implementering av tunn redundansteknologi. En sÄdan uppgift Àr dock inte lÀngre vÀrt det, eftersom huvudmÄlet har uppnÄtts. Generellt sett skulle jag naturligtvis vilja gÄ bort frÄn det tillvÀgagÄngssÀtt som beskrivs ovan - implementera fungerande databasmigreringar till en testmiljö, skapa en separat testdatabaskrets och börja skÀrpa huvuddatabasen. Vi omsÀtter redan mycket av detta i praktiken, vilket vi definitivt kommer att prata om i framtida artiklar.
Resultat av
Det ursprungliga problemet löstes, om Àn pÄ ett ovanligt sÀtt. De mellanliggande slutsatserna beskrev fördelarna och nackdelarna med var och en av de anvÀnda teknikerna, sÄ lÄt oss bestÀmma vilken teknik som kan anvÀndas och nÀr:
- Tunn LVM - för smÄ databaser och nÀr du inte vill eller inte har tid att lÀra dig ZFS.
- ZFS - om du har erfarenhet av att arbeta med det eller möjlighet att Àgna tid Ät att studera det i alla situationer.
PÄ en högre presentationsnivÄ Àr den hÀr artikeln inte bara en jÀmförelse av tekniken för de tvÄ filsystemen. Huvudtanken som jag skulle vilja förmedla och förstÀrka Àr att man inte ska vara rÀdd för att tÀnka utanför ramarna i affÀrskritiska situationer och bara ta fÀrdiga recept. En gÄng i tiden kunde vi skaka pÄ huvudet som helhet pÄ den tekniska avdelningen och sÀga att uppgiften att skapa tre terabyte kopior av en databas pÄ mindre Àn en minut Àr omöjlig, och vi behöver ingen riskfylld teknik, lÄt oss göra det Àr rÀtt. Det var möjligt, men vi skulle ha förlorat ungefÀr sex mÄnader till ett Är och mÄnga kundresor (resor Àr vÄr huvudsakliga affÀrsindikator) utan testning och under implementering. Genom att agera utanför ramarna förlorade vi inte mycket tid pÄ implementeringen, fick erfarenhet av nya och bortglömda gamla tekniker och testade vid en tidpunkt dÄ vi verkligen behövde det. Detta hade utan tvekan en positiv inverkan pÄ alla vÄra indikatorer. Valet Àr alltid ditt, och vi för vÄr del kommer att fortsÀtta prata om intressanta nuvarande och framtida prestationer i vÄr blogg.
KĂ€lla: will.com
