Linux 백그라운드 플러시 제한 (더러운 페이지)


26

Linux에서 백그라운드 플러시는 너무 많은 쓰기 데이터가 보류 중이거나 (/ proc / sys / vm / dirty_background_ratio를 통해 조정 가능) 보류중인 쓰기 시간이 초과 된 경우 (/ proc / sys / vm / dirty_expire_centisecs)에 발생합니다. 다른 한계에 도달하지 않으면 (/ proc / sys / vm / dirty_ratio) 더 많은 쓰기 데이터가 캐시 될 수 있습니다. 추가 쓰기가 차단됩니다.

이론적으로 다른 프로세스를 방해하지 않고 더티 페이지를 작성하는 백그라운드 프로세스를 만들어야합니다. 실제로는 캐시되지 않은 읽기 또는 동기 쓰기를 수행하는 프로세스를 방해합니다. 심하게. 백그라운드 플러시가 실제로 100 % 장치 속도로 쓰며 현재 다른 장치 요청이 지연되기 때문입니다 (도로의 모든 큐와 쓰기 캐시가 채워지기 때문).

플러시 프로세스가 수행하는 초당 요청 량을 제한하거나 다른 장치 I / O의 우선 순위를 효과적으로 지정하는 방법이 있습니까?


아마 이것은 리눅스 커널 메일 링리스트 vger.kernel.org/vger-lists.html#linux-kernel

어떤 IO 스케줄러를 사용하고 있습니까?
3dinfluence

다양한 (cfq, 데드 라인)을 시도했지만 배터리 백업 쓰기 캐시가 포함되지 않은 경우에만 안정적으로 작동합니다. 하나의 디스크 어레이와 마찬가지로 PCIe 버스 속도 (RAM)에서 1GiB의 데이터를 사용한 다음 현실에 부딪칩니다. 모든 LUN에 대해 몇 초 동안 I / O가 없습니다. 실제 장치 속도의 대략적인 추정치로 플러시 (최소한 백그라운드)를 조절하면 혼잡 문제를 해결할 수 있습니다.
korkman

1
최근에 / sys / block / sdX / queue / nr_requests가 주요 조정 가능하다는 것을 알게되었습니다. 최소로 낮추면 (제 경우 = 4) 동시로드 지연 시간이 많이 향상됩니다. Sysbench fsync 임의 쓰기는 초당 dd로 버스 속도로 쓰는 동안 4 (!)에서 80-90으로 점프했습니다. 로드되지 않은 성능은 영향을받지 않습니다. 스케줄러는 모두 동일합니다. noop 또는 데드 라인은 최적 인 것 같습니다. 이것은 대부분의 BBWC 구성에 해당 될 수 있습니다.
korkman

답변:


20

sysbench로 많은 벤치마킹을 한 후 다음과 같은 결론을 얻었습니다.

다음과 같은 상황에서 (성능 측면에서) 생존하기 위해

  • 악의적 인 복사 프로세스가 더러운 페이지를 넘치게합니다
  • 하드웨어 쓰기 캐시가 있습니다 (아마도 없을 수도 있습니다)
  • 동기 읽기 또는 초당 쓰기 (IOPS)가 중요합니다.

모든 엘리베이터, 대기열 및 더티 페이지 캐시를 덤프하십시오. 더티 페이지의 올바른 위치는 해당 하드웨어 쓰기 캐시의 RAM에 있습니다.

dirty_ratio (또는 새로운 dirty_bytes)를 가능한 한 낮게 조정하되 순차적 처리량을 주시하십시오. 필자의 경우 15MB가 최적이었습니다 ( echo 15000000 > dirty_bytes).

기가 바이트의 RAM이 이제 더티 캐시 대신 읽기 캐싱에만 사용되기 때문에 이것은 솔루션보다 해킹입니다. 이 상황에서 더티 캐시가 제대로 작동하려면 Linux 커널 백그라운드 플러 셔는 기본 장치가 요청을 수락하는 속도를 평균화하고 그에 따라 백그라운드 플러싱을 조정해야합니다. 쉬운 일이 아닙니다.


비교를위한 사양 및 벤치 마크 :

dd디스크에 0을 기록 하면서 테스트 한 sysbench는 33 kS 에서 700 IOPS (유휴 한계 : 1500 IOPS)에서 16 kB로 10 스레드 fsync 쓰기를, 8에서 400 IOPS로 단일 스레드를 향상 시켜 큰 성공을 거두었습니다 .

로드가 없으면 IOPS는 영향을받지 않았으며 (~ 1500) 처리량이 약간 감소했습니다 (251MB / s에서 216MB / s로).

dd 요구:

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

sysbench의 경우 test_file.0은 다음과 같이 해석되지 않도록 준비되었습니다.

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

sysbench는 10 개의 스레드를 요구합니다.

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 호출 :

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

블록 크기가 작을수록 더 큰 숫자를 나타 냈습니다.

1GB dirty_bytes의 --file-block-size = 4096 :

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, 15MB 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

유휴 시스템에서 15MB dirty_bytes를 가진 --file-block-size = 4096 :

sysbench 0.4.12 : 멀티 스레드 시스템 평가 벤치 마크

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

테스트 시스템 :

  • Adaptec 5405Z (보호 기능이있는 512MB 쓰기 캐시)
  • 인텔 제온 L5520
  • 6GiB RAM @ 1066MHz
  • 마더 보드 Supermicro X8DTN (5520 칩셋)
  • Seagate Barracuda 1TB 디스크 12 개
    • Linux 소프트웨어 RAID 10에서 10
  • 커널 2.6.32
  • 파일 시스템 xfs
  • 데비안 불안정

요약하면,이 구성이 순차 트래픽으로 인해 굶주린 데이터베이스 트래픽에 대해 유휴, 고부하 및 전체로드 상황에서 제대로 수행 될 것이라고 확신합니다. 순차 처리량은 어쨌든 2 기가비트 링크가 제공 할 수있는 것보다 높으므로 조금 줄어드는 데 아무런 문제가 없습니다.


'dirty_buffers에 최적 인 15MB'부분에 도달하는 방법론은 무엇입니까?
Marcin

1
시행 착오. 마찬가지로 15MB와 OK IOPS로 끝날 때까지 다음 번에 절반의 양을 변경하십시오. 현재 커널 3.2는 BTW와 매우 다르게 동작 할 수 있습니다.
korkman

2
올바른 길로 안내해 주셔서 감사합니다. XenServer 노드와 비슷한 문제가있었습니다. 더티 페이지를 일으키는 PHP-FPM / APC 캐시로 밝혀졌습니다. APC 캐시 메모리 모델을 조정하면 문제가 해결되었습니다. DiskIO은 0으로 20 % 사용률에서 갔다
jeffatrackaid

dirty_bytes프로세스가 디바이스의 처리량 으로 평균적 으로 쓰면 프로세스가 쓰이고있는 동안 CPU를 정지시키지 않을 정도로 논리적으로 높아야합니다 . 애플리케이션 코드가 엄청난 양의 데이터를 작성하고 대량의 계산을 수행하는 경우 단시간 평균이 오랜 시간 평균과 크게 다르기 때문에 최적화하기가 매우 어렵습니다. 올바른 해결책은 프로세스 특정 dirty_bytes설정 을 조정하는 것이지만 Linux는 내가 아는 한 지원하지 않습니다.
Mikko Rantalainen

3

커널 매개 변수를 조정하면 문제가 중지되었지만 실제로 성능 문제는 2012 년 2 월 1 일 펌웨어 업데이트에서 수정 된 Adaptec 5405Z 컨트롤러의 버그로 인한 것일 수 있습니다. 릴리스 노트는 "높은 I / O 스트레스 중에 펌웨어가 멈출 수있는 문제를 해결했습니다."라고 말합니다. 아마도 당신이했던 것처럼 I / O를 퍼뜨리는 것이이 버그가 발생하는 것을 막기에 충분했을 것입니다. 그러나 그것은 단지 추측 일뿐입니다.

릴리스 노트는 다음과 같습니다. http://download.adaptec.com/pdfs/readme/relnotes_arc_fw-b18937_asm-18837.pdf

이것이 귀하의 특정 상황에 해당되지 않더라도 앞으로이 게시물을 방문하는 사용자에게 도움이 될 것이라고 생각했습니다. 우리는 dmesg 출력에서 ​​다음과 같은 메시지를 보았고 결국 펌웨어 업데이트로 이어졌습니다.

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

다음은 I / O 중단 수정이 높은 펌웨어의 릴리스 노트에 나열된 Adaptec RAID 컨트롤러의 모델 번호입니다 : 2045, 2405, 2405Q, 2805, 5085, 5405, 5405Z, 5445, 5445Z, 5805, 5805Q, 5805Z, 5805ZQ, 51245, 51645, 52445.


1
와우, 입력 해 주셔서 감사합니다. 이것은 사실이 아니었지만 HW RAID를 완전히 피하고 HBA 전용 설정으로 넘어 가야 할 또 다른 이유를 제시합니다. HW RAID는 여전히 BBWC의 장점을 가지고 있지만 bcache와 같은 것들이 커널로 이동하면 사라집니다. HW RAID의 단점은 정확히 설명하는 종류의 펌웨어 버그입니다. DRBD 설정 및 높은 I / O로드를 가진 다른 시스템에 펌웨어 리 세트가 발생했기 때문에 이것이 드물지 않습니다 (정확히 버그 일 수 있음).
korkman

1

"WBT"를 포함하는 커널 :

LWN.net 블록 레이어 개선

라이트 백 스로틀을 사용하면 [블록 계층]은 CoDel 네트워크 스케줄러에서 빌린 전략을 사용하여 과도한 I / O 대기 시간없이 최대 성능을 얻으려고합니다. CoDel은 관찰 된 네트워크 패킷의 최소 대기 시간을 추적하고 임계 값을 초과하면 패킷 삭제를 시작합니다. I / O 하위 시스템에서 쓰기 삭제가 찌그러 지지만 커널이 읽기 및 쓰기의 최소 대기 시간을 모니터링하고 임계 값을 초과하면 백그라운드 쓰기 저장량을 줄이기 시작하는 유사한 전략이 따릅니다. 완료되었습니다. 이 동작은 4.10에서 추가되었습니다. Axboe는 꽤 좋은 결과가 나왔다고 말했다.

WBT는 새로운 blk-mq 블록 레이어로 전환 할 필요가 없습니다. 그러나 CFQ 또는 BFQ I / O 스케줄러에서는 작동하지 않습니다. 데드 라인 / mq-deadline / noop / none 스케줄러와 함께 WBT를 사용할 수 있습니다. 새로운 "kyber"I / O 스케줄러와도 작동한다고 생각합니다.

대기 시간을 제어하기 위해 큐 크기를 조정하는 것 외에도 WBT 코드 는 백그라운드 쓰기 저장 요청 수를 계산 된 큐 제한의 비율로 제한합니다.

런타임 구성은입니다 /sys/class/block/*/queue/wbt_lat_usec.

찾을 빌드 구성 옵션은 다음과 같습니다.

/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT=y
/boot/config-4.20.8-200.fc29.x86_64:# CONFIG_BLK_WBT_SQ is not set
/boot/config-4.20.8-200.fc29.x86_64:CONFIG_BLK_WBT_MQ=y

귀하의 문제 진술은 WBT의 저자에 의해 100 % 확인되었습니다.

[PATCHSET] 블록 : 버퍼링 된 쓰기 저장 제한

시간이 시작된 이래로 백그라운드 버퍼링 된 쓰기 저장이 빨라졌습니다. 백그라운드 버퍼 라이트 백을 수행 할 때 포 그라운드 활동에 거의 영향을 미치지 않습니다. 이것이 배경 활동의 정의입니다. 그러나 내가 기억할 수있는 한, 버퍼가 많은 작가들은 그렇게 행동하지 않았습니다. 예를 들어, 내가 이런 식으로하면 :

$ dd if=/dev/zero of=foo bs=1M count=10k

내 랩톱에서 크롬을 시도하고 시작하면 버퍼링 된 쓰기 저장이 완료되기 전에 기본적으로 시작되지 않습니다. 또는 서버 중심 워크로드의 경우 큰 RPM (또는 이와 유사한)을 설치하면 데이터베이스 읽기 또는 동기화 쓰기에 부정적인 영향을 미칩니다. 그런 일이 생기면 사람들이 나에게 소리를 지 릅니다.

최근 테스트 결과는 다음에서 확인할 수 있습니다.

https://www.facebook.com/axboe/posts/10154074651342933

패치 세트에 대한 자세한 설명은 이전 게시물을 참조하십시오.


문제가 인식되어 커널 내부에서 처리되는 것을 보게되어 기쁩니다. blk-mq는 상당히 새롭고 아직 성숙 하지는 않았 음을 명심하십시오 .
korkman

@korkman 한숨, 나는 잘못된 함의를 피하기 위해 따옴표를 엉망으로 만들 것입니다. 지난 2 년 동안 추가 된 내용이며, 여전히 성능 저하 또는 악화가있을 수 있습니다. AFAIR 관리자는 데이터 손상 수정이 우연이라는 의미에서 무시합니다. 경우 당신은 BLK-MQ 개발 된 커널 버전을 사용하고 버그를 피할 것 "레거시"블록 층을 사용하여 얼마나 많은, 그것은 논쟁의 여지가있다. 내가 수정 한 일시 중단 버그는 blk-mq에서 시작된 버그였으며 리팩토링되거나 무언가에 영향을 미쳤으며 둘 다에 영향을 미쳤습니다. github.com/torvalds/linux/commit/1dc3039bc87a
sourcejedi

0

/ proc / meminfo에서 Dirty의 평균은 무엇입니까? 일반적으로 / proc / sys / vm / dirty_ratio를 초과하지 않아야합니다. 전용 파일 서버에서 dirty_ratio를 초과하지 않는 매우 높은 백분율의 메모리 (90)로 설정했습니다. dirty_ration이 너무 낮아서 적중하면 모든 것이 엉망이됩니다.


dirty_ratio에 도달 할 때 프로세스가 차단되지 않습니다. 난 괜찮아 그러나 더티 데이터를 디스크에 기록하는 "백그라운드"프로세스는 자비없이 큐를 채우고 IOPS 성능을 저하시킵니다. 내가 생각하는 IO 기아라고합니다. 실제로 dirty_ratio_bytes를 1MB와 같이 매우 낮게 설정하면 플러시가 거의 즉시 발생하고 대기열이 비어 있기 때문에 많은 도움이됩니다. 단점은 순차 처리 속도가 낮을 ​​수도 있지만 괜찮습니다.
korkman

모든 엘리베이터를 끄셨습니까? 바닐라 시스템에서 또 무엇을 조정 했습니까?
Luke

1
내 답변을 참조하십시오. 이야기의 끝은 더러운 캐싱을 제거하고 해당 부분을 HW 컨트롤러에 남겨 두는 것이 었습니다. 엘리베이터는 HW 쓰기 캐시와 관련이 없습니다. 컨트롤러에는 자체 엘리베이터 알고리즘이 있으므로 소프트웨어에 엘리베이터가 있으면 오버 헤드 만 추가됩니다.
korkman

소프트웨어의 엘리베이터 (elevevator)는 트레이드 오프입니다. 예를 들어, 무작위 순서로 제출 된 소프트웨어 큐에 100K 쓰기 작업이 있다고 가정하십시오. 소프트웨어 엘리베이터가 거대한 버퍼를 사용하여 해당 운영 체제를 주문할 수 있다면 장치에 5K 훨씬 더 큰 요청을 보낼 수 있습니다. 그러나 결과적으로 대기 시간은 100K op 증가해야합니다. 왜냐하면 첫 2K op와 마지막 1K op가 실제로 장치에서 서로 가까이 있기 때문일 수 있습니다. 대기 시간이 추가되지 않으면이를 병합 할 수 없습니다.
Mikko Rantalainen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.