Frage Linux Hintergrund-Flush begrenzen (Dirty Pages)


Hintergrund-Spülung unter Linux tritt auf, wenn entweder zu viele geschriebene Daten anstehen (einstellbar über / proc / sys / vm / dirty_background_ratio) oder ein Timeout für ausstehende Schreibvorgänge erreicht ist (/ proc / sys / vm / dirty_expire_centisecs). Wenn kein anderes Limit erreicht wird (/ proc / sys / vm / dirty_ratio), können mehr geschriebene Daten zwischengespeichert werden. Weitere Schreibvorgänge werden blockiert.

In der Theorie sollte dies einen Hintergrundprozess erstellen, der schmutzige Seiten ausschreibt, ohne andere Prozesse zu stören. In der Praxis stört es jeden Prozess, der nicht zwischengespeichertes Lesen oder synchrones Schreiben ausführt. Schlecht. Dies liegt daran, dass der Hintergrund-Flush tatsächlich mit 100% Gerätegeschwindigkeit schreibt und alle anderen Geräteanforderungen zu diesem Zeitpunkt verzögert werden (weil alle Warteschlangen und Schreib-Caches auf der Straße gefüllt sind).

Gibt es eine Möglichkeit, die Anzahl der Anfragen pro Sekunde, die der Spülvorgang ausführt, zu begrenzen oder andere Geräte-E / A anderweitig effektiv zu priorisieren?


25
2018-03-25 21:48


Ursprung


Vielleicht wäre das eine gute Frage, um sie an die Linux Kernel Mailingliste zu schicken vger.kernel.org/vger-lists.html#linux-kernel
Welchen IO-Scheduler benutzen Sie? - 3dinfluence
Versucht verschiedene (cfq, Deadline), aber ich denke, diese funktionieren nur zuverlässig, wenn kein batteriegestützter Schreibcache enthalten ist. Wie ein Disk-Array habe ich 1 GiB Daten bei PCIe-Bus-Geschwindigkeit (RAM) und trifft dann auf die Reality-Wall. Mehrere Sekunden null E / A für alle LUNs. Throttling-Spülungen (zumindest im Hintergrund) zu einer groben Schätzung der tatsächlichen Gerätegeschwindigkeit würden dieses Stauproblem lösen. - korkman
Ich habe kürzlich festgestellt, dass / sys / block / sdX / queue / nr_requests ein Haupt-Tunable ist. Wenn ich es auf Minimum (= 4 in meinem Fall) reduziere, erhöht sich gleichzeitig die Lade-Latenz: Sysbench-Fsync-Zufalls-Schreibvorgänge pro Sekunde sprangen von 4 (!) Auf 80-90, während mit dd mit Busgeschwindigkeit geschrieben wurde. Nicht geladene Leistung scheint nicht betroffen zu sein. Scheduler sind alle gleich, Noop oder Deadline scheint optimal. Dies kann für die meisten BBWC-Konfigurationen gelten. - korkman


Antworten:


Nach vielen Benchmarks mit sysbench komme ich zu dieser Schlussfolgerung:

Um (performance-weise) eine Situation zu überleben, in der

  • Ein böser Kopierprozess überschwemmt schmutzige Seiten
  • und Hardware-Schreib-Cache ist vorhanden (möglicherweise auch ohne)
  • und synchrone Lese- oder Schreibvorgänge pro Sekunde (IOPS) sind kritisch

Löschen Sie einfach alle Aufzüge, Warteschlangen und schmutzigen Seitencaches. Der richtige Platz für schmutzige Seiten befindet sich im RAM dieses Hardware-Schreib-Cache.

Passen Sie dirty_ratio (oder neue dirty_bytes) so niedrig wie möglich an, aber behalten Sie den sequenziellen Durchsatz im Auge. In meinem speziellen Fall waren 15 MB optimal (echo 15000000 > dirty_bytes).

Dies ist mehr ein Hack als eine Lösung, da Gigabytes RAM jetzt nur für Lese-Caching anstelle von schmutzigem Cache verwendet werden. Damit ein schmutziger Cache in dieser Situation gut funktioniert, müsste der Hintergrund-Flusher des Linux-Kernels mitteln, mit welcher Geschwindigkeit das zugrunde liegende Gerät Anforderungen annimmt und das Hintergrund-Flushing entsprechend anpasst. Nicht einfach.


Spezifikationen und Benchmarks zum Vergleich:

Getestet während ddNullen auf Platte, zeigte sysbench Riesenerfolg, Boost 10 Threads fsync schreibt bei 16 kB von 33 bis 700 IOPS (Idle-Limit: 1500 IOPS) und Single-Thread von 8 bis 400 IOPS.

Ohne Last wurden IOPS nicht beeinflusst (~ 1500) und der Durchsatz geringfügig reduziert (von 251 MB / s auf 216 MB / s).

dd Anruf:

dd if=/dev/zero of=dumpfile bs=1024 count=20485672

Für sysbench wurde die Datei test_file.0 so vorbereitet, dass sie unparsed ist mit:

dd if=/dev/zero of=test_file.0 bs=1024 count=10485672

sysbench-Aufruf für 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

sysbench-Aufruf für einen 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

Kleinere Blockgrößen zeigten noch drastischere Zahlen.

--file-block-size = 4096 mit 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 mit 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 mit 15 MB dirty_bytes im Leerlauf:

sysbench 0.4.12: Multithread-Systembewertungs-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, 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

Testsystem:

  • Adaptec 5405Z (das ist 512 MB Schreib-Cache mit Schutz)
  • Intel Xeon L5520
  • 6 GiB RAM bei 1066 MHz
  • Hauptplatine Supermicro X8DTN (5520 Chipsatz)
  • 12 Seagate Barracuda 1 TB Festplatten
    • 10 in Linux-Software RAID 10
  • Kernel 2.6.32
  • Dateisystem xfs
  • Debian instabil

Zusammenfassend bin ich jetzt sicher, dass diese Konfiguration bei Leerlauf-, Hochlast- und sogar Volllast-Situationen für Datenbankverkehr, der ansonsten durch sequentiellen Datenverkehr verhungert wäre, gut funktioniert. Sequenzieller Durchsatz ist höher, als zwei Gigabit-Links sowieso liefern können, also kein Problem, es ein bisschen zu reduzieren.


19
2018-04-11 13:03



Was ist Ihre Methode, um den "15 MB für dirty_buffers ist optimal" Teil zu erreichen? - Marcin
Versuch und Irrtum. Zum Beispiel die Hälfte der Menge beim nächsten Mal ändern, bis ich nur 15 MB und OK IOPS habe. Der aktuelle Kernel 3.2 kann sich sehr unterschiedlich verhalten, BTW. - korkman
Ich wollte mich nur dafür bedanken, dass er mich auf den richtigen Weg gebracht hat. Hatte einige ähnliche Probleme mit einem XenServer-Knoten. Es stellte sich heraus, dass PHP-FPM / APC-Cache schmutzige Seiten verursachte. Das Anpassen des APC-Cache-Speichermodells hat das Problem für uns gelöst. DiskIO ging von 20% Auslastung auf 0. - jeffatrackaid
Logisch dirty_bytes sollte kaum hoch genug sein, um CPUs nicht zu blockieren, während Prozesse schreiben, wenn der Prozess schreibt im Durchschnitt mit dem Durchsatz des Geräts. Wenn Ihr Anwendungscode große Rechenvorgänge ausführt und anschließend eine große Menge an Daten schreibt, ist es sehr schwierig, ihn zu optimieren, da sich die kurzen Zeitdurchschnitte stark von den langen Zeitdurchschnitten unterscheiden. Die richtige Lösung wäre, prozessspezifisch anzupassen dirty_bytes Einstellung, aber Linux unterstützt so viel wie ich weiß nicht. - Mikko Rantalainen


Auch wenn das Korrigieren der Kernelparameter das Problem behob, ist es möglich, dass Ihre Leistungsprobleme auf einen Fehler des Adaptec 5405Z-Controllers zurückzuführen sind, der in einem Firmware-Update vom 1. Februar 2012 behoben wurde. In den Versionshinweisen heißt es: "Es wurde ein Problem behoben, bei dem die Firmware bei hoher E / A-Belastung hängen bleiben konnte." Vielleicht reichte es aus, den I / O zu verteilen, wie Sie getan haben, um zu verhindern, dass dieser Fehler ausgelöst wird, aber das ist nur eine Vermutung.

Hier sind die Release Notes: http://download.adaptec.com/pdfs/readme/relnotes_arc_fw-b18937_asm-18837.pdf

Auch wenn dies für Ihre spezielle Situation nicht der Fall war, dachte ich, dass dies den Nutzern, die in Zukunft auf diesen Posten stoßen, zugute kommen könnte. Wir haben in unserem dmesg-Ausgang einige Meldungen wie die folgenden gesehen, die uns schließlich zum Firmware-Update geführt haben:

aacraid: Host adapter abort request (0,0,0,0)
[above was repeated many times]
AAC: Host adapter BLINK LED 0x62
AAC0: adapter kernel panic'd 62.
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000000
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028
Result: hostbyte=DID_OK driverbyte=DRIVER_TIMEOUT,SUGGEST_OK
sd 0:0:0:0: timing out command, waited 360s
sd 0:0:0:0: Unhandled error code
sd 0:0:0:0: SCSI error: return code = 0x06000028

Im Folgenden finden Sie die Modellnummern der Adaptec RAID-Controller, die in den Versionshinweisen für die Firmware aufgeführt sind, die über den High-I / O-Hangfix verfügt: 2045, 2405, 2405Q, 2805, 5085, 5405, 5405Z, 5445, 5445Z, 5805 5805Q, 5805Z, 5805ZQ, 51245, 51645, 52445.


3
2017-07-15 19:08



Wow, danke für deine Eingabe. Obwohl dies bei mir nicht der Fall war, geben Sie mir noch einen weiteren Grund, HW-RAID ganz zu vermeiden und zu HBA-Only-Setups überzugehen. HW-RAID hat immer noch den BBWC-Vorteil, aber wenn Dinge wie bcache in den Kernel eindringen, verschwindet sogar das. Die Konsequenz für HW-RAID ist genau die Art von Firmware-Fehlern, die Sie beschreiben. Ich hatte ein anderes System mit DRBD-Setup und hoher E / A-Last, die Firmware-Rücksetzungen verursacht, so dass dies nicht selten vorkommt (könnte genau dieser Fehler gewesen sein). - korkman


Was ist Ihr Durchschnitt für Dirty in / proc / meminfo? Dies sollte normalerweise nicht Ihr / proc / sys / vm / dirty_ratio überschreiten. Auf einem dedizierten Dateiserver habe ich dirty_ratio auf einen sehr hohen Prozentsatz an Speicher (90) eingestellt, da ich es niemals überschreiten werde. Deine Dirty_Ration ist zu niedrig, wenn du sie triffst, wird alles kaputt gemacht, erhöhe es.


0
2018-04-10 22:37



Das Problem ist nicht, dass Prozesse blockiert werden, wenn Sie auf dirty_ratio treffen. Damit bin ich einverstanden. Aber der "Hintergrund" -Prozess, bei dem schmutzige Daten auf die Festplatten geschrieben werden, füllt Warteschlangen ohne Gnade und zerstört die IOPS-Leistung. Es heißt IO Hunger, denke ich. In der Tat hilft das Festlegen von dirty_ratio_bytes extrem niedrig (wie 1 MB) viel, weil Spülen fast sofort auftritt und Warteschlangen leer bleiben. Nachteil ist möglicherweise niedriger Durchsatz für sequenzielle, aber das ist in Ordnung. - korkman
Sie haben alle Aufzüge ausgeschaltet? Was hast du sonst noch an einem Vanilla-System geändert? - Luke
Siehe meine Selbstantwort. Das Ende der Geschichte war, schmutziges Caching zu entfernen und diesen Teil dem HW-Controller zu überlassen. Aufzüge sind irgendwie irrelevant mit HW-Schreib-Cache an Ort und Stelle. Der Controller hat seine eigenen Aufzugsalgorithmen, so dass jeder Aufzug in der Software nur einen zusätzlichen Aufwand verursacht. - korkman
Elevevator in der Software ist ein Kompromiss: Opferlatenz zur Verbesserung der Bandbreite. Stellen Sie sich zum Beispiel 100K Schreiboperationen in der Softwarewarteschlange vor, die in zufälliger Reihenfolge übergeben werden. Wenn der Software-Aufzug diese Ops mit einem riesigen Puffer bestellen kann, kann es am Ende nur 5K viel größere Anfragen an das Gerät senden. Als Ergebnis muss die Latenz jedoch um 100 K Ops erhöht werden, da es möglich ist, dass die ersten 2 K Ops und die letzten 1 K Ops auf dem Gerät tatsächlich nahe beieinander liegen. Ohne zusätzliche Latenz wird es unmöglich sein, diese zu verschmelzen. - Mikko Rantalainen