Après de nombreuses analyses comparatives avec sysbench, j'arrive à cette conclusion:
Pour survivre (en termes de performances) à une situation où
- un mauvais processus de copie inonde les pages sales
- et le cache d'écriture matériel est présent (peut-être aussi sans cela)
- et les lectures ou écritures synchrones par seconde (IOPS) sont essentielles
il suffit de vider tous les ascenseurs, les files d'attente et les caches de pages sales. L'endroit correct pour les pages sales est dans la RAM de ce cache d'écriture matériel.
Ajustez dirty_ratio (ou les nouveaux dirty_bytes) aussi bas que possible, mais gardez un œil sur le débit séquentiel. Dans mon cas particulier, 15 Mo étaient optimaux ( echo 15000000 > dirty_bytes
).
Il s'agit plus d'un hack que d'une solution car des gigaoctets de RAM sont désormais utilisés uniquement pour la mise en cache de lecture au lieu de cache sale. Pour que le cache sale fonctionne bien dans cette situation, le nettoyeur d'arrière-plan du noyau Linux devrait faire la moyenne de la vitesse à laquelle le périphérique sous-jacent accepte les demandes et ajuster le vidage d'arrière-plan en conséquence. Pas facile.
Spécifications et repères de comparaison:
Testé lors de l'utilisation dd
de zéros sur le disque, sysbench a connu un énorme succès , augmentant 10 threads d'écriture fsync à 16 Ko de 33 à 700 IOPS (limite d'inactivité: 1500 IOPS) et un thread unique de 8 à 400 IOPS.
Sans charge, les IOPS n'étaient pas affectés (~ 1500) et le débit était légèrement réduit (de 251 Mo / s à 216 Mo / s).
dd
appel:
dd if=/dev/zero of=dumpfile bs=1024 count=20485672
pour sysbench, le test_file.0 a été préparé pour ne pas être analysé avec:
dd if=/dev/zero of=test_file.0 bs=1024 count=10485672
appel sysbench pour 10 threads:
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
appel sysbench pour 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
De plus petites tailles de blocs ont montré des nombres encore plus drastiques.
--file-block-size = 4096 avec 1 Go 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 avec 15 Mo 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 avec 15 Mo dirty_bytes sur le système inactif:
sysbench 0.4.12: benchmark d'évaluation de système 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
Système de test:
- Adaptec 5405Z (soit 512 Mo de cache en écriture avec protection)
- Intel Xeon L5520
- 6 Go de RAM à 1066 MHz
- Carte mère Supermicro X8DTN (chipset 5520)
- 12 disques Seagate Barracuda 1 To
- 10 dans le logiciel Linux RAID 10
- Noyau 2.6.32
- Système de fichiers xfs
- Debian instable
En résumé, je suis maintenant sûr que cette configuration fonctionnera bien dans des situations d'inactivité, de charge élevée et même de pleine charge pour le trafic de base de données qui autrement aurait été affamé par le trafic séquentiel. Le débit séquentiel est supérieur à ce que deux liaisons gigabits peuvent fournir de toute façon, donc pas de problème à le réduire un peu.