ZFS je jedan mnogo dobar file system, napravljen od strane Sun Microsystems-a. Najavljivan je port za OSX (mada se o tome vise ne prica) a u Linux ga je komplikovano ubaciti zbot kolizije linux kernel licence i licence pod kojom je objavljen ZFS. Sve to u stranu, radi super na Solaris-u i na Open Solarisu, i na sparc i na intel platformi i jedan je od najboljih, ako ne i najbolji file system za rad sa bazama podataka. Kako ovakav jedan file system, koji u sebe inkorporira i lvm funkcionalnost ima velike mogucnosti, samim tim pravilna konfiguracija istog u radu sa odredjenim sistemom moze znatno da utice na performanse. Ovo je jedna kraca prica o tome kako ja to radim … dakle kako ja konfigurisem ZFS kao storage system za InnoDB table space.
1. Pool configuracija – ZIL – SSDs
zpool create datapool mirror c0t2d0s2 c0t3d0s2 mirror c0t4d0s2 c0t5d0s2 mirror c0t6d0s2 c0t7d0s2 mirror c0t8d0s2 c0t9d0s2 log mirror c0t10d0s2 c0t11d0s2
RAID 1+0 pool (stripe size je 4) sa ZIL configurisanim na 2 SSD-a (c0t10d0s2 c0t11d0s2).
ZIL je „ZFS Intent Log“. Koristenjem odvojenih ZIL-ova moze da dovede do 10-20% upbrzanja i preporuceno je kada imamo write heavy aplikaciju.
SSD (solid state disk) ima latencyreda velicine 0.2 ms (obican HDD ima latency reda velicine 10-20 ms).
2. ZFS recordsize
kreiranje pool-a:
zfs create datapool/mysql_data
zfs create datapool/mysql_log
Recordsize za datapool/mysql_data na 16kB:
zfs set recordsize=16k datapool/mysql_data
Najveci performance benefit dobijamo tako sto usaglasimo ZFS record size sa velicinom IO-a. Kako je InnoDB pae 16KB vecina IO paketa je velika 16KB tako da je ovo optimalna vrednost za InnoDB (default vrednost je 128KB sto nije ni blizu onoga sto nam generise InnoDB kao „cest“ IO)
3. disable prefetch (aj da vidim da ovo neko prevede na srpski :( )
set zfs:zfs_prefetch_disable = 1
Kada InnoDB salje prefetch IO zahtev podrazumeva da se fajl na disku fizicki nalazi sortiran po primarnom kljucu. U slucaju ZFS-a fajl nije fizicki takav na disku tako da je ova pretpostavlja InnoDB-a pogreskan. Sam po sebi prefetch, sve i da jeste fajl cuvan sekvencijalno kako to InnoDB pretpostavlja, ima slabe vajde na iole sarolikom DB serveru posto podacima uglavnom pristupamo „haoticno“ a ne sekvencijalno (sekvencijalno realno znaci da radite table scan – ako je to slucaj, optimizujte bazu/aplikaciju).
4. disable cache flush
set zfs:zfs_nocacheflush = 1
ZFS je dizajniran da radi sigurno sa diskovima koji imaju svoj kesh. svaki put kada zelimo da podatke smestimo „sigurno“ na disk ZFS salje komandu disku da flushuje cache (da kesh zapise na disk). Ako imamo disk sa keshom koji je podrzan baterijom (a svi noviji imaju, ako nemate battery backed up cache kontroller/disk, tesko da mozete da imate i sigurnost i performanse) flush cache komanda ne radi nista. Problem ovde je sto jedan dobar broj uredjaja, i onih sa i onih bez battery backed up cache-om ne ume da hendluje „flush cache“ komandu kako treba (posebno ovi „pametni“ battery backed up cache kontroleri jeftinijih proizvodjaca posto oni uopste ne ocekuju da im neko salje flush cache) kako treba, slanje flush cache komande (koja ne radi nista) samo povecava latency – tako da je u slucaju battery backed up cache-a vrlo korisno ugasiti flushovanje od strane ZFS-a
5. limitiranje ARC cache
set zfs:zfs_arc_max = 0x780000000
U ovom primeru ARC kesh je limitiran na 30G. ARC je „where ZFS caches data from all active storage pools“. Ovo je prilicno kompleksan posao posto limitiranje ARC-a u nekom slucaju moze da donese benefit a u drugom da uspori celu pricu, takodje vrednost na koju se ARC limitira nija laka za racunicu.
6. Ugasi Innodb Double write buffer
–skip-innodb_doublewrite
InnoDB koristi „double write buffer“ za sigurno updateovanje strana u tablespace-u. Sve izmene su prvo upisane u double write buffer pre nego su upisane u data page. Na ovaj nacin se sprecava delimicni upis. Kako ZFS sam po sebi ne dozvoljava delimicni upis cela prica sa double write buffer-om je potpuno nepotrebna te se isti moze ugasiti (performance, performance, performance :D – merenja pokazuju ubrzanje od ~5% ).
btw, ista je i konfiguracija sa obicnim HDD-om, SDD je stavljen u [1] posto je to „najbrza varijanta“
[4. disable cache flush] opciju treba iskljuciti samo u slucaju kada disk/kontroler ne radi nista na flush cache komandu… u slucaju da disk/kontroler to ume onda gasenje tog flush-a moze da dovede u nekom slucaju i do usporenja.
O cemu se radi, write cache nam pomaze u nekoliko slucajeva
– pri konstantnom prilivu podataka na disk, smanjuje IO
– uspeva da se izbori sa kratkotrajnim prilivom velike brzine (brze nego sto disk sam za sebe moze da postigne)
Ono gde write cache ne pomaze je konstantan priliv podataka vecom brzinom nego sto disk moze da zapise, u tom slucaju, ako aplikacija ne salje flush cache, kesh ce se prazniti na svakih X sekundi (kada se prepuni) te ce u stvari praviti vece zagusenje nego da ga nema (umesto da pise non stop i da non stop ima po minimalno cekanje na io kesh ce odjednom pisati velike kolicine podataka te ce io wait biti redji ali ce trajati duze sto je mnogo losije po ceo sistem). U ovom slucaju je nekada isplativije skroz ugasiti disk/controller cache.
Dakle, cela prica sa keshom je malo komplikovanija od ovoga napisanog ali kada pricamo o „general case“ onda je prica primenjljiva.