Dopo molti benchmarking con sysbench, arrivo a questa conclusione:
Sopravvivere (per quanto riguarda le prestazioni) una situazione in cui
- un cattivo processo di copia inonda le pagine sporche
- e la cache di scrittura hardware è presente (possibilmente anche senza quella)
- e letture o scritture sincrone al secondo (IOPS) sono fondamentali
basta scaricare tutti gli ascensori, le code e le cache delle pagine sporche. Il posto corretto per le pagine sporche è nella RAM di quella cache di scrittura hardware.
Regola dirty_ratio (o nuovi dirty_bytes) il più basso possibile, ma tieni d'occhio il throughput sequenziale. Nel mio caso particolare, 15 MB erano ottimali ( echo 15000000 > dirty_bytes
).
Questo è più un trucco che una soluzione perché gigabyte di RAM vengono ora utilizzati solo per la cache di lettura anziché per la cache sporca. Affinché la cache sporca funzioni bene in questa situazione, il flusher in background del kernel Linux dovrebbe fare una media alla velocità con cui il dispositivo sottostante accetta le richieste e regolare di conseguenza il flushing in background. Non facile.
Specifiche e parametri di riferimento per il confronto:
Testato durante dd
l'installazione di zeri su disco, sysbench ha mostrato un enorme successo , aumentando 10 thread scritti da fsync a 16 kB da 33 a 700 IOPS (limite di inattività: 1500 IOPS) e thread singolo da 8 a 400 IOPS.
Senza carico, gli IOPS non sono stati influenzati (~ 1500) e la velocità effettiva è stata leggermente ridotta (da 251 MB / sa 216 MB / s).
dd
chiamata:
dd if=/dev/zero of=dumpfile bs=1024 count=20485672
per sysbench, test_file.0 è stato preparato per essere privo di analisi con:
dd if=/dev/zero of=test_file.0 bs=1024 count=10485672
chiamata sysbench per 10 thread:
sysbench --test=fileio --file-num=1 --num-threads=10 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run
chiamata sysbench per un thread:
sysbench --test=fileio --file-num=1 --num-threads=1 --file-total-size=10G --file-fsync-all=on --file-test-mode=rndwr --max-time=30 --file-block-size=16384 --max-requests=0 run
I blocchi più piccoli hanno mostrato numeri ancora più drastici.
--file-block-size = 4096 con 1 GB dirty_bytes:
sysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.
Operations performed: 0 Read, 30 Write, 30 Other = 60 Total
Read 0b Written 120Kb Total transferred 120Kb (3.939Kb/sec)
0.98 Requests/sec executed
Test execution summary:
total time: 30.4642s
total number of events: 30
total time taken by event execution: 30.4639
per-request statistics:
min: 94.36ms
avg: 1015.46ms
max: 1591.95ms
approx. 95 percentile: 1591.30ms
Threads fairness:
events (avg/stddev): 30.0000/0.00
execution time (avg/stddev): 30.4639/0.00
--file-block-size = 4096 con 15 MB dirty_bytes:
sysbench 0.4.12: multi-threaded system evaluation benchmark
Running the test with following options:
Number of threads: 1
Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.
Operations performed: 0 Read, 13524 Write, 13524 Other = 27048 Total
Read 0b Written 52.828Mb Total transferred 52.828Mb (1.7608Mb/sec)
450.75 Requests/sec executed
Test execution summary:
total time: 30.0032s
total number of events: 13524
total time taken by event execution: 29.9921
per-request statistics:
min: 0.10ms
avg: 2.22ms
max: 145.75ms
approx. 95 percentile: 12.35ms
Threads fairness:
events (avg/stddev): 13524.0000/0.00
execution time (avg/stddev): 29.9921/0.00
--file-block-size = 4096 con 15 MB dirty_bytes su sistema inattivo:
sysbench 0.4.12: benchmark di valutazione del sistema multi-thread
Running the test with following options:
Number of threads: 1
Extra file open flags: 0
1 files, 10Gb each
10Gb total file size
Block size 4Kb
Number of random requests for random IO: 0
Read/Write ratio for combined random IO test: 1.50
Calling fsync() after each write operation.
Using synchronous I/O mode
Doing random write test
Threads started!
Time limit exceeded, exiting...
Done.
Operations performed: 0 Read, 43801 Write, 43801 Other = 87602 Total
Read 0b Written 171.1Mb Total transferred 171.1Mb (5.7032Mb/sec)
1460.02 Requests/sec executed
Test execution summary:
total time: 30.0004s
total number of events: 43801
total time taken by event execution: 29.9662
per-request statistics:
min: 0.10ms
avg: 0.68ms
max: 275.50ms
approx. 95 percentile: 3.28ms
Threads fairness:
events (avg/stddev): 43801.0000/0.00
execution time (avg/stddev): 29.9662/0.00
Test-sistema:
- Adaptec 5405Z (ovvero 512 MB di cache di scrittura con protezione)
- Intel Xeon L5520
- 6 GiB RAM a 1066 MHz
- Scheda madre Supermicro X8DTN (chipset 5520)
- 12 dischi Seagate Barracuda da 1 TB
- 10 nel software Linux RAID 10
- Kernel 2.6.32
- File system xfs
- Debian instabile
In sintesi, ora sono sicuro che questa configurazione funzionerà bene in situazioni di inattività, a carico elevato e persino a pieno carico per il traffico del database che altrimenti sarebbero affamate dal traffico sequenziale. Il throughput sequenziale è superiore a quello che due link gigabit possono fornire comunque, quindi nessun problema a ridurlo un po '.