Auf meinem heimischen Server werden alle Daten in einem ZFS Pool gespeichert. Dieser Server ist mittlerweile ca. 5 Jahre alt und die Hauptlast an IO wird über diesen zpool, bestehend aus 4 WD Red Platten (WDC WD60EFRX-68L), getragen. Da auf die Platten vor allem geschrieben und weniger gelesen wird, wollte ich ein sogenanntes SLOG Device zum zpool hinzufügen um die HDDs zu entlasten. Wenn ein SLOG Device in einem zpool vorhanden ist, gehen alle Writes erst mal auf diese Devices und werden später auf die HDDs geflusht. Deswegen sind hier vor allem SSDs empfehlenswert. Natürlich sollten es SSDs mit Batterie sein damit die Daten bei einem Stromausfall noch weggeschrieben werden können. Sonst risktiert man Datenverlust.
Vorbereitung
Mein bestehender zpool ohne SLOG Device:
root@prox01:~# zpool status -v
pool: vol_raidz1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
vol_raidz1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
wwn-0x50014ee20d05dc08 ONLINE 0 0 0
wwn-0x50014ee2623066ec ONLINE 0 0 0
wwn-0x50014ee2b7b0c6c0 ONLINE 0 0 0
wwn-0x50014ee20cdb1ed3 ONLINE 0 0 0
errors: No known data errors
SLOG Device hinzufügen:
zpool add vol_raidz1 log /dev/disk/by-id/ata-Samsung_SSD_850_EVO_500GB_S2RBNXAH358685D-part1
Oder auch als Mirror, empfehlenswert in einem Enterprise Umfeld:
zpool add vol_raidz1 log mirror /dev/disk/by-id/[SSD1] /dev/disk/by-id/[SSD2]
zpool mit SLOG Device:
root@prox01:~# zpool status -v
pool: vol_raidz1
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
vol_raidz1 ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
wwn-0x50014ee20d05dc08 ONLINE 0 0 0
wwn-0x50014ee2623066ec ONLINE 0 0 0
wwn-0x50014ee2b7b0c6c0 ONLINE 0 0 0
wwn-0x50014ee20cdb1ed3 ONLINE 0 0 0
logs
ata-Samsung_SSD_850_EVO_500GB_S2RBNXAH358685D-part1 ONLINE 0 0 0
errors: No known data errors
SLOG Device entfernen:
zpool remove vol_raidz1 ata-Samsung_SSD_850_EVO_500GB_S2RBNXAH358685D-part1
Benchmark
Für meine Tests habe ich folgendes Skript von https://blog.programster.org/zfs-add-intent-log-device genutzt:
#!/bin/bash
echo "Performing cached write of 100,000 4k blocks..."
/usr/bin/time -f "%e" sh -c 'dd if=/dev/zero of=4k-test.img bs=4k count=100000 2> /dev/null'
rm 4k-test.img
echo ""
sleep 3
echo "Performing cached write of 1,000 1M blocks..."
/usr/bin/time -f "%e" sh -c 'dd if=/dev/zero of=1GB.img bs=1M count=1000 2> /dev/null'
rm 1GB.img
echo ""
sleep 3
echo "Performing non-cached write of 100,000 4k blocks..."
/usr/bin/time -f "%e" sh -c 'dd if=/dev/zero of=4k-test.img bs=4k count=100000 conv=fdatasync 2> /dev/null'
rm 4k-test.img
echo ""
sleep 3
echo "Performing non-cached write of 1,000 1M blocks..."
/usr/bin/time -f "%e" sh -c 'dd if=/dev/zero of=1GB.img bs=1M count=1000 conv=fdatasync 2> /dev/null'
rm 1GB.img
echo ""
sleep 3
echo "Performing sequential write of 1,000 4k blocks..."
/usr/bin/time -f "%e" sh -c 'dd if=/dev/zero of=4k-test.img bs=4k count=1000 oflag=dsync 2> /dev/null'
rm 4k-test.img
echo ""
sleep 3
echo "Performing sequential write of 1,000 1M blocks..."
/usr/bin/time -f "%e" sh -c 'dd if=/dev/zero of=1GB.img bs=1M count=1000 oflag=dsync 2> /dev/null'
rm 1GB.img
Es erstellt im Skriptordner Testdateien, gibt an, wie lange dafür gebraucht wurde und löscht die Testdateien im Anschluss wieder. Die Tests liefen jeweils 3x mit und ohne SLOG Device. Anschließend wurde der Mittelwert ermittelt.
Fazit
Die Ergebnisse können sich sehen lassen. Applikationen, die drauf warten, dass Daten geschrieben wurden, erhalten nun schneller eine Antwort. Zudem ist der txg_sync Thread von durchschnittlich 10% IO auf 5% IO heruntergegangen. Das lässt sich sehr gut mit iotop beobachten:
root@prox01:~# iotop -ao
Total DISK READ: 0.00 B/s | Total DISK WRITE: 11.05 K/s
Current DISK READ: 0.00 B/s | Current DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
1049 be/4 root 0.00 B 0.00 B 0.00 % 4.95 % [txg_sync]
[...]
Allerdings habe ich Mist gebaut als ich das letzte Mal das SLOG Device zum Pool hinzugefügt habe...