Po wielu testach porównawczych z sysbench doszedłem do tego wniosku:
Aby przeżyć (pod względem wydajności) sytuację, w której
- zły proces kopiowania zalewa brudne strony
- i sprzętowa pamięć podręczna zapisu jest obecna (być może również bez tego)
- a synchroniczne odczyty lub zapisy na sekundę (IOPS) są krytyczne
po prostu zrzuć wszystkie windy, kolejki i brudne pamięci podręczne stron. Prawidłowe miejsce dla brudnych stron znajduje się w pamięci RAM tego sprzętowego bufora zapisu.
Dostosuj dirty_ratio (lub nowe dirty_bytes) tak nisko, jak to możliwe, ale miej oko na sekwencyjną przepustowość. W moim szczególnym przypadku 15 MB było optymalne ( echo 15000000 > dirty_bytes
).
Jest to bardziej hack niż rozwiązanie, ponieważ gigabajty pamięci RAM są teraz używane tylko do buforowania odczytu zamiast brudnej pamięci podręcznej. Aby brudna pamięć podręczna działała dobrze w tej sytuacji, moduł czyszczący w tle jądra systemu Linux musiałby uśredniać, z jaką prędkością urządzenie bazowe akceptuje żądania i odpowiednio dostosowywać czyszczenie tła. Niełatwe.
Dane techniczne i testy porównawcze:
Testowany podczas dd
zerowania dysku, sysbench wykazał ogromny sukces , zwiększając 10 wątków fsync zapisuje przy 16 kB z 33 do 700 IOPS (limit bezczynności: 1500 IOPS) i pojedynczy wątek od 8 do 400 IOPS.
Bez obciążenia IOPS pozostały bez zmian (~ 1500), a przepustowość nieznacznie zmniejszona (z 251 MB / s do 216 MB / s).
dd
połączenie:
dd if=/dev/zero of=dumpfile bs=1024 count=20485672
w przypadku sysbench plik_pliku testowego.0 został przygotowany do rozrzedzenia za pomocą:
dd if=/dev/zero of=test_file.0 bs=1024 count=10485672
sysbench call dla 10 wątków:
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
wywołanie sysbench dla jednego wątku:
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
Mniejsze rozmiary bloków pokazały jeszcze bardziej drastyczne liczby.
- file-block-size = 4096 z 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 z 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 z 15 MB dirty_bytes w bezczynnym systemie:
sysbench 0.4.12: test porównawczy wielowątkowej oceny systemu
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
System testowy:
- Adaptec 5405Z (to 512 MB pamięci podręcznej zapisu z ochroną)
- Intel Xeon L5520
- 6 GiB RAM przy 1066 MHz
- Płyta główna Supermicro X8DTN (chipset 5520)
- 12 dysków Seagate Barracuda o pojemności 1 TB
- 10 w oprogramowaniu Linux RAID 10
- Jądro 2.6.32
- System plików XFS
- Debian niestabilny
Podsumowując, jestem teraz pewien, że ta konfiguracja będzie działać dobrze w sytuacjach bezczynności, dużego obciążenia, a nawet pełnego obciążenia dla ruchu w bazie danych, który w innym przypadku byłby zagłodzony przez ruch sekwencyjny. Przepustowość sekwencyjna jest wyższa niż dwa łącza gigabitowe, które i tak można dostarczyć, więc nie ma problemu, aby ją nieco zmniejszyć.