Storage

A Unix/Linux szerverek üzemeltetése wikiből
(Változatok közti eltérés)
(zh-kérdések)
a (Gyakorlati problémák: linkek helyesbítése)
149. sor: 149. sor:
 
Ezeket a problémákat próbálja több-kevesebb sikerrel orvosolni a [[RAID]].
 
Ezeket a problémákat próbálja több-kevesebb sikerrel orvosolni a [[RAID]].
   
Kapcsolódó problémák: a diszkek és a partíciórendszer rugalmatlanok, a [[filerendszerek]] dinamikus növelése nehézkes. Megoldás: [[logikai kötetkezelés]] ill. [[ZFS]].
+
Kapcsolódó problémák: a diszkek és a partíciórendszer rugalmatlanok, a [[Filerendszerek|filerendszerek]] dinamikus növelése nehézkes. Megoldás: [[Logikai kötetkezelés|logikai kötetkezelés]] ill. [[ZFS]].
   
 
== Az SSD-kről ==
 
== Az SSD-kről ==

A lap 2012. december 21., 11:15-kori változata

A számítógépek sokféle adattárolót használnak; ezeket egy hierarchia elemeiként szokás ábrázolni/elképzelni.

  1. A hierarchia csúcsát a processzor regiszterei képezik: ezek nagyon kevés adatot tudnak tárolni (max. pár száz byte), de az elérésük nagyon gyors (tipikusan egyetlen órajelciklus).
  2. A regisztereknél pár nagyságrenddel több adat fér a CPU cache-be.
    • A cache még mindig elég gyors és még mindig elég drága, emiatt általában elég kicsi. Nem címezhető közvetlenül, csak az alatta/mögötte levő memóriát cache-eli.
    • CPU cache-ből esetleg több szint is van (nem ritkán három; a magasabb szint az alacsonyabbat cache-eli).
      • Az L1 cache mérete tipikusan néhányszor tíz KiB; elérési ideje néhány ciklus.
      • Az L2 cache általában legalább 512KiB-os, elérési ideje akár egy nagyságrenddel rosszabb, mint az L1 cache-é.
      • Az L3 cache általában legalább 2MiB-os és még lassúbb.
  3. Az operatív tár már viszonylag nagy, viszonylag olcsó, közvetlenül címezhető, ám -- a processzorhoz képest -- rendkívül lassú (ciklusok százai kellenek), és a sebességkülönbség egyre nő (1986 és 2000 között a CPU-k sebessége évi 55%-kal nőtt, a memóriáké csak 10%-kal).
  4. A következő szint lehet a háttértár és a diszk közötti cache; ez is lehet többszintű (pl. SSD a RAID-tömb előtt ill. a RAID-vezérlőre integrált cache).
  5. Nagyon fontos szint -- és jelen szócikk fő témája -- a háttértár maga: általában merevlemez. Olcsó, de lassú; míg a memória elérési ideje nanoszekundumos nagyságrendű, a merevlemezé milliszekundumos (ez hat nagyságrend különbség).
    • Létezik olyan megoldás, amelyben a háttértárak is saját hierarchiába szervezhetők: pl. egy SSD cache-el egy 15k rpm-es merevlemezekből álló RAID0-tömböt, az pedig egy 7200rpm-es merevlemezekből álló RAID6-ot.
    • Mivel a virtuális memóriát az operációs rendszerek a háttértárak segítségével biztosítják, bizonyos értelemben az operatív tár is csak cache-eli a háttértárat.
  6. A hierarchia alja lehet a tape library ("szalagkönyvtár"?), amelyben kis robot rakosgatja a szalagos egységbe mindig a megfelelő szalagot.
    • A véletlen elérési idő nyilván katasztrofális, cserébe sok adat tárolható viszonylag olcsón viszonylag kis helyen.

Tartalomjegyzék

1 Memória

Elképesztő tempóban lesz egyre olcsóbb:

  • "Prediction: The cost for 128 kilobytes of memory will fall below U$100 in the near future." -- Creative Computing magazine, December 1981, page 6
    • Jelenértéken (2012-ben) 100 1981-es dollár kb. 260 dollár.
    • 8 GB RAM, ha 128k 100 dollárba kerül, 6.553.600 dollárba került volna; ez jelenértéken kb. 17 millió dollár.
    • 2012-ben 8 GB RAM valójában kb. 40 dollárba kerül.
    • 2001-ben 40 2012-es dollárért még csak kb. 128MB-ot kaptunk.

2 Merevlemezek

2.1 Történetük röviden

  • 1953-ban készítette az elsőt az IBM.
    • Ipari áram, mosógépszerű doboz, ~60 centis átmérőjű korongok (és ilyenből 50db az 5MB-os kapacitáshoz); drága (1956-ban kb. 10.000$/MB), érzékeny.
  • 1980-ban jelent meg az első 5.25"-es, a Seagate (akkori nevén Shugart) ST-506:
    • 1500$ (jelenértéken kb. 4400$), 5MB
    • Itt van két, mai szemmel vicces korabeli reklám.
  • 1981: ST-412, 10MB
  • 1987: kb. 45-90$/MB, jellemző méret 10-40MB.
  • 1995 körül: jellemzően kb. 1GB
  • 2007: első 1TB-os diszk (Hitachi Deskstar)
  • 2012: 1-4TB

2.2 Kapacitásnövekedés

2.3 Sebességnövekedés

Üteme jelentősen elmarad a kapacitásnövekedés ütemétől.

Néhány jellemző adat:

  • 1991: lineáris olvasás 0,7MB/s, átlagos elérési idő 27ms
  • 1995: 7,6MB/s, 14-15ms
  • 1998: 9,5MB/s, 13-15ms
  • 2002: 36MB/s, 13-15ms
  • 2006: 64MB/s, 7-13-15ms (10k, 7200, 5400rpm)
  • 2012: 120MB/s, 7-13-15ms
  • A kapacitás kb. 60-szor gyorsabban nőtt, mint a lineáris olvasás sebessége.
    • Vagyis: egy átlagos mai diszket sokkal-sokkal több idő végigolvasni, mint egy átlagos régi diszket. Ez nem intuitív.
      • Ha az ST506 kapacitását és sebességét egységnyinek tekintjük (a fenti grafikon szerint 1s alatt végigolvasható volt az 5MB -- ezt azért kezeljük fenntartásokkal), akkor mára a jellemző kapacitások több százezer egységnyiek, a jellemző átviteli sebesség viszont alig néhány tucat egységnyi (15k rpm-es diszknél is csak 40-45 egység; SSD-nél sem több 150-nél).
    • Súlyos következmény: az adatok mennyiségének növekedése miatt ma sokkal lassúbb egy backup (és egy visszaállítás!), mint egykor.
    • További következmény: a néhány diszknél többet tartalmazó rendszereket majdnem mindig alulméretezik I/O-átbocsátóképesség szempontjából.
      • Nem meglepő: a gyors I/O nagyon drága. Egy elfogadható vezérlőkártya 8 diszkhez, 1GB cache-sel, akku nélkül, 600 euró körül van. "Mások ennyiből egy egész szervert megvesznek."
      • Még ott is, ahol sokat költenek I/O-ra, gyakori, hogy a SAN és a szerver közötti kapcsolatot alulméretezik: pl. 4Gbit/s-os FibreChannel esetén legjobb esetben is csak kb. 400MB/s-mal tudunk olvasni a diszkekről.
        • Egy jobb SSD önmagában tud ennyit.
        • Egy 100GB-os adatbázistábla végigolvasása több, mint 4 perc, és akkor más I/O-t ki sem szolgáltunk közben.

2.4 IOPS

  • I/O [operations] Per Second. Legalább olyan fontos adat, mint a lineáris írás/olvasás sebessége. Miért?
  • Mert a legtöbb esetben a terhelés nem lineáris, hanem véletlen jellegű; így (forgó merevlemezek esetén) nem az effektív írás/olvasás, hanem az adatelérés ideje dominál a kiszolgálás idejében.
  • Az sem mindegy, hogy egyszálú vagy többszálú a terhelés:
    • Egyszálú terhelés esetén a következő igény nem válik ismertté az előző igény kiszolgálásáig (a processz vár, amíg az egyik művelet befejeződik, és csak utána kezdeményezi a következőt).
    • Többszálú terhelés esetén keletkezhetnek új igények a folyamatban levők kiszolgálása közben is. Ez nyilván ütemezési kihívás:
      • Nem szabad kiéheztetni egyik processzt sem;
      • ugyanakkor érdemes lenne a fej alatt amúgy is elsuhanó szektorok közül azokat, amikkel csinálni kell valamit, fejmozgatás közben kezelésbe venni;
      • de pl. az ugyanazt a szektort érintő írások és olvasások sorrendje nem variálható szabadon.
      • Ilyesmi feladatokat old meg a command queueing (SATA-ban Native CQ, SAS-nál Tagged CQ; lehetséges házi feladat: miben különböznek ezek?).
        • A diszkekbe épített NCQ/TCQ ütemezők minőségén nagyon sok múlik.
    • Megjegyzés: az IOPS-t néha MB/s-ban adják meg. A MB/s-ban megadott érték úgy jön ki, hogy az egy másodperc alatt elvégzett műveletek számát összeszorozzák az egyes műveletek során átvitt (olvasott vagy írt) adatok mennyiségével.

Az IOPS analitikus meghatározása

Fő tényezők:

  • átlagos késleltetés (ennyi ideig tart, amíg a keresett szektor befordul a fej alá; nyilván egy teljes fordulathoz szükséges idő fele);
    • (10k rpm esetén 3ms, mert 1 perc, vagyis 60000ms alatt fordul 10000-et, tehát egy fél fordulat 3ms)
    • (15k rpm esetén 2ms)
  • átlagos elérési idő (ennyi ideig tart, amíg a fej a megfelelő sáv fölé mozog).
    • (egy átlagos mai 10k rpm-es diszknél pl. kb. 4,45ms)
  • Az effektív írás/olvasás idejét elhanyagoljuk.

Képlet: IOPS=1/(átlagos késleltetés+átlagos elérési idő)

Így egy 10k rpm-es diszk elvileg kb. 133 IOPS-re képes (1/(0.003 + 0.0045)=~133).

Ökölszabályként használhatjuk az alábbi adatokat (ezek inkább alsó, mint felső becslések; a tomshardware-en közölt adatok ennél valamivel jobb képet festenek):

  • 7200rpm -- 75 IOPS
  • 10k rpm -- 125 IOPS
  • 15k rpm -- 175 IOPS
  • 2012 körüli SATA SSD -- 10000+ IOPS, nem ritkán 50-100k IOPS
  • 2012 körüli PCIe SSD -- 100k-1M IOPS
  • Érdekesség: ha tudjuk, hova esnek az egyes szektorok a diszken (pl. hogy az alsó 50%-nyi sorszámokat viselő terület valóban a tányérok egyik "felére" esik -- a határvonal nyilván nem a sugár felénél lesz, körök területéről beszélünk), akkor egy aránylag lassú diszkből készíthetünk sokkal gyorsabbat úgy, hogy csak az elejét, vagy csak a végét használjuk. Ha a fejmozgások maximális terjedelmét felezzük, akkor azzal várhatóan az átlagos elérési idő is feleződik; így lehetséges, hogy egy elvileg lassúbb diszkből több IOPS-t tudunk kihozni, mint egy elvileg gyorsabból -- ráadásul kevesebb vagy alig több pénzért nagyobb kapacitást is kapunk (a pluszkapacitást viszont természetesen csak akkor használhatjuk, amikor éppen nem kell a sok IOPS: pl. éjjel, mentésekhez).
  • Még drámaibb a hatás, ha negyedeljük a diszket (így akár 7200rpm-es diszkkel is elérhetünk 125+ IOPS-t).
  • Elvileg az alacsony sorszámú szektorok szoktak a diszk külső részén lenni (és, mivel a lineáris sebesség itt a legnagyobb, ezek a leggyorsabb részek).
  • Fontos: nyilván más IOPS-értékeket fogunk kapni, ha az effektív I/O ideje már nem hanyagolható el!
    • Egy komoly méréssorozat során legalább az alábbiakat vizsgálni kell:
      1. 0 byte-os IOPS (tehát csak az elérési idő számítson) és ennek függése a használt szálak számától;
      2. 1 szektoros IOPS, egy és több szál esetén;
      3. 4k-s IOPS, egy és több szál esetén;
      4. 32k-s IOPS, egy és több szál esetén;
      5. további blokkméretek;
      6. mindez külön írásra és olvasásra is.
      • Tetszőlegesen elbonyolítható a mérés: adhatunk hozzá szekvenciálisan író vagy olvasó szálakat, keverhetjük a véletlen írásokat és olvasásokat különböző arányokban, vegyíthetjük az egyes blokkméreteket stb.

2.5 Gyakorlati problémák

  1. A merevlemezek hazudnak arról, mikor végeztek az írással.
    • A jobb teljesítmény érdekében íráskor csak a diszkre integrált cache-be írják az adatot, mielőtt azt mondanák az OS-nek, hogy kész.
    • Ennek az az előnye, hogy ha a következő írás a következő szektorra vonatkozik (ami, lássuk be, gyakori), akkor nem kell megvárni, amíg az a szektor újra bepördül a fej alá, hanem lehet szépen gyorsan lineárisan írni.
    • Csakhogy: ez azt jelenti, hogy egy fsync() vagy sync() visszatérhet úgy, hogy az adatok nincsenek tartós tárba írva.
    • Ezt a problémát is enyhíti a command queueing: az OS elküldheti az összes írást egyszerre, a diszk végrehajtja őket a neki tetsző sorrendben, és mindegyik teljesüléséről egyenként küld értesítést.
    • A tuti az, ha kikapcsoljuk az írás cache-t a diszkeken (pl. hdparm -W0 /dev/sd?), de ez nyilván hátrányosan befolyásolja a teljesítőképességet.
      • Főként olcsó diszkeknél mindenképpen érdemes azonban megtenni, mert elő-előfordul, hogy a diszk firmware-je lefagy és újraindítja magát, közben pedig rossz esetben eldobja a cache tartalmát.
    • Ha megbízhatóságot és teljesítőképességet is akarunk, kénytelenek vagyunk mélyen a zsebünkbe nyúlni és olyan vezérlőkártyát venni, amelyen akkumulátorról táplált cache van. A diszkek írás-cache-ét természetesen ekkor is ki kell kapcsolnunk.
    • Használható írás-cache nélkül a szinkron írások nagyon lassúak lesznek.
  2. A merevlemezek időnként arról is hazudnak, mekkora a fizikai szektorméretük (512 byte-ot mondanak akkor is, ha a szektorok valójában 4k-sak).
    • Ha rossz helyen (egy 4k-s szektor közepén) kezdjük az írást, a diszk először beolvassa az eredeti 4k-s szektort, módosítja, majd visszaírja.
    • Így egy műveletből kettő lett, vagyis legalább 50%-os sebességveszteséget szenvedtünk el.
    • A valóságban a lassulás ennél is nagyobb lehet, mert elképzelhető, hogy a visszaírás előtt meg kell várni, amíg a kérdéses szektor megint a fej alá ér.
    • Emiatt a fájlrendszereket mindenképpen fel kell készíteni arra, hogy ha csak lehet, 4k-s határon kezdjék az írásokat (pl. minden file 4k-s határon kezdődjön).

A legfontosabb gyakorlati problémák azonban a következők:

  1. A diszkek lassúak.
  2. A diszkek megbízhatatlanok.

Ezeket a problémákat próbálja több-kevesebb sikerrel orvosolni a RAID.

Kapcsolódó problémák: a diszkek és a partíciórendszer rugalmatlanok, a filerendszerek dinamikus növelése nehézkes. Megoldás: logikai kötetkezelés ill. ZFS.

3 Az SSD-kről

  • Az SSD-k "szektormérete" (amit page size-nak hívnak és az a legkisebb egybefüggő terület, amit egy művelettel írni vagy olvasni lehet), általában 2k és 32k között van.
    • Mivel az SSD 512 byte-os szektorokat használó SATA merevlemeznek hazudja magát, természetesen elfogadja és végrehajtja az 512 byte-os "szektorra" vonatkozó parancsot is, ám ez -- legalábbis olvasás esetén, l. lejjebb -- ugyanannyi időbe kerül, mint a teljes "lap" (page) kiolvasása.
  • Az SSD-k, működési elvükből adódóan, minden felülíráskor egy viszonylag nagy egybefüggő területet (egy "erase block"-nyit) törölnek, majd beleírják az új tartalmat.
    • Gyakran 128k-s "erase block"-okat használnak (ekkora egységeket írnak felül egyszerre). Egy 1k-s írás végrehajtásához tehát be kell olvasni 127k-t, törölni egy 128k-s blokkot, majd kiírni az új blokkot (valószínűleg máshova, mint ahol eredetileg volt).
      • Léteznek 512k-s erase blockokat használó SSD-k is (pl. az OCZ Vertex szériának legalább bizonyos darabjai); sőt 1-4MB méretű erase blockról is lehet olvasni.
        • Itt talán félreértésről van szó: a nagyobb SSD-k gyakran 4MB-os "szegmensekbe" szervezik az erase blockokat és a szegmenseket kezelik atomi logikai egységként.
    • Az SSD-k azokat a blokkokat, amelyekről tudják, hogy szabadok, a háttérben törölgetik, amikor nincs más dolguk; egy ilyen előtörölt blokk írása gyorsabb.
    • Emiatt fontos (lenne), hogy az SSD tudja, melyik blokkban nincs már értékes adat (pl. mert töröltük a file-t, amihez tartozott). Erre szolgál az ATA TRIM parancs.
      • A használatát Linux alatt (legalábbis ext4-en és xfs-en) a discard mount opcióval kapcsolhatjuk be, de pl. az xfs.org szerint ez jelentős lassulást okozhat, mert -- egyelőre -- meg kell várni hozzá, amíg az összes sorbaálló I/O végez. Azt javasolják, inkább az fstrim programmal TRIMmeljünk, mondjuk naponta futtatva cronból.
    • A partíciókat mindig 128k-s blokkhatárra (vagy ennek többszörösére) tegyük és a fájlrendszereinket is próbáljuk úgy létrehozni, hogy lehetőleg szintén 128k-s blokkhatárokon kezdjék a fájlokat; így nagyobb esély van arra, hogy egy-egy kis írás nem két, hanem csak egy erase blockot érint.
      • ext4:
        • mkfs -t ext4 -E stripe-width=32 (ha minden más értéket az alapértelmezésen hagytunk és olyan architektúrán vagyunk, ahol a kernel 4k-s lapmérettel dolgozik; ilyen pl. az i386 és az amd64).
        • ext4 mountolásakor adjuk meg a stripe=32 opciót.
          • És a discard-ot is, hogy használja a TRIM parancsot.
      • xfs:
        • mkfs.xfs -d su=128k -d sw=1 /dev/sda1
        • mount -o sunit=256,swidth=256 (igen, tényleg ezekkel a számokkal; itt ugyanis 512byte-os egységekben kell megadni)
    • Valószínűleg általában túl pazarló lenne a fájlrendszer blokkméretét 128k-ra állítani (és némelyik fs-nél nem is tudjuk nagyobbra venni a kernel és az architektúra által meghatározott lapméretnél, ami a gyakori esetekben 4k).
    • Mindez még egy kicsit bonyolultabb, ha valamilyen RAID-elrendezést használunk; ilyenkor általában nem úszható meg, hogy gondolkodjunk rajta.
    • Ha a partíció eleje rossz helyen van, kis ügyeskedéssel még jó helyre tehetjük a partícióban levő LVM PV elejét.
    • Ha csak egyetlen partíciót csinálnánk, talán az a legegyszerűbb, ha egyet sem csinálunk, hanem az egész diszket egyben használjuk LVM PV-ként vagy fájlrendszer tárolására.
  • Probléma lehet az alacsony szintű fragmentáció (a wear leveling mellékhatása). Az ATA Secure Erase parancs segíthet, de egyáltalán nem veszélytelen.
  • A Linux alapból entrópiaforrásnak használja a diszkek seekeléssel töltött idejét. SSD-k esetén ez nem túl értelmes dolog, kapcsoljuk ki: echo 0 > /sys/block/sda/queue/add_random.
  • Ha msdos típusú partíciós táblát csinálunk (és nem pl. GPT-t), érdemes az alapértelmezett emulált geometriát átállítani: fdisk -H 32 -S 32 /dev/sda, így minden cilinder 512k hosszú lesz, és mivel a partíciók cilinderhatáron kezdődnek, az elsőt kivéve mindegyik 128k-s határon is kezdődik majd.
    • Azért az elsőt kivéve, mert az első partíció előtt egy "track" szabadon marad (ide kerül pl. a bootloader, meg maga a partíciós tábla is).
    • Szerintem jobb GPT-t használni és ügyelni arra, hogy 256-tal osztható sorszámú szektorban kezdődjenek a partícióink (512 byte-os szektorokat feltételezve).
    • Egy 256GB-os SSD-re pl. az alábbiakat mondja az fdisk a fenti parancssor hatására:
# fdisk -H 32 -S 32 /dev/sda
[...]
Using /dev/sda
Command (m for help): p                                                   

Disk /dev/sda: 256 GB, 256060162048 bytes
32 heads, 32 sectors/track, 488396 cylinders
Units = cylinders of 1024 * 512 = 524288 bytes
    • 4k-s szektorokat használó HDD-k esetén használhatunk 128 fejet és 32 szektoros trackeket: fdisk -H 128 -S 32, így elvileg 4k-s határokon kezdődnek majd a partícióink.
    • Fontos, hogy ezeknek a geometriai adatoknak a világon semmi szerepük nincs azon kívül, hogy ha jól adjuk meg őket, akkor az fdisk program magától is olyan partíciókat csinál, amelyek jó helyen kezdődnek.
  • Ha a partícióban LVM PV-t hozunk létre, arra is figyelnünk kell, hogy az LVM meta-adatok után az első PE 128k-s határon kezdődjön; erre szolgál a --dataalignment 128k kapcsoló. A pvs /dev/sda2 -o+pe_start paranccsal ellenőrizhetjük, sikerült-e.
  • Érdemes noatime opcióval mountolni az SSD-inken levő fájlrendszereket, hogy csökkentsük a felesleges (ráadásul kicsi) írások számát.
  • Noha csábító SSD-re swapelni, valószínűleg használ az SSD élettartamának, ha nem tesszük (persze üzleti szempontból megérheti SSD-re swapelni: max. néhányévente veszünk egy újat).
  • Ha munkaállomáson használunk SSD-t, érdemes lehet az elhasználódás csökkentése érdekében
    • a Firefoxot rávenni, hogy ritkábban mentse a sessiont. about:config, majd növeljük meg (pl. 60000-re) a browser.sessionstore.interval értékét;
    • a /tmp-t, a /var/tmp-t és hasonlókat tmpfs-re tenni (így a memóriában lesznek, nem az SSD-n);
    • esetleg ugyanígy járni el a /var/loggal is.

Források:

4 Potenciális zh-kérdések

  • Hogyan, mire érdemes SSD-t használni és mire nem?
  • Mi az ATA TRIM parancs értelme? Mikor és miért kell használni?
  • Milyen nehézsége(ke)t okoznak a 4k-s szektorokat használó "advanced format" merevlemezek?
  • Hogyan becsülhető meg, hány IOPS-re képes egy merevlemez?
  • Készíthető-e egyetlen 7200rpm-es merevlemezből 125 IOPS-re képes tároló? Ha igen, hogyan? Ha nem, miért nem?
  • Mi a TCQ/NCQ a háttértárolók kontextusában? Kb. hogyan működik?
  • Mi az IOPS-érték és miért fontos?
  • Milyen alkalmazásnál fontosabb az IOPS, mint a szekvenciális írás/olvasás sebessége? Milyen alkalmazásnál kevésbé fontos?
  • Milyen módszerekkel növelhető egy háttértár-rendszer írás/s-ban mért teljesítőképessége? Válaszában külön térjen ki a szinkron és az aszinkron írásokra is!
  • Mik a merevlemezek alkalmazásával összefüggő főbb gyakorlati problémák?
Személyes eszközök