답변1
cp
첫 번째 작업 중에 데이터가 디스크에 플러시되지 않았지만 두 번째 작업 중에 디스크에 플러시되었을 가능성이 있습니다 .
vm.dirty_background_bytes
이 경우에 해당하는지 확인하려면 1048576(1MiB)과 같은 더 작은 값으로 설정해 보십시오 . sysctl -w vm.dirty_background_bytes=1048576
그러면 첫 번째 cp
장면에 I/O가 표시되어야 합니다.
여기서 무슨 일이 일어나고 있는 걸까요?
동기식 및/또는 직접 I/O의 경우를 제외하고 디스크에 대한 쓰기는 임계값에 도달할 때까지 메모리에 버퍼링되며, 임계값에 도달하면 백그라운드에서 디스크에 플러시가 시작됩니다. 이 임계값에는 공식적인 이름이 없지만 vm.dirty_background_bytes
에 의해 제어 되므로 vm.dirty_background_ratio
"더티 백그라운드 임계값"이라고 부르겠습니다.커널 문서에서:
vm.dirty_background_bytes
백그라운드 커널 플러시 스레드가 쓰기를 시작할 더티 메모리의 양을 포함합니다.
노트:
dirty_background_bytes
응 상대편dirty_background_ratio
. 한 번에 하나만 지정할 수 있습니다. 하나의 sysctl이 작성되면 평가를 위해 더티 메모리 제한이 즉시 고려되는 반면, 다른 sysctl은 읽을 때 0을 표시합니다.
dirty_background_ratio
백그라운드 커널 새로 고침 스레드가 더티 데이터 쓰기를 시작하는 페이지 수를 포함합니다(사용 가능한 페이지와 회수 가능한 페이지를 포함한 총 여유 메모리의 백분율).
사용 가능한 총 메모리는 총 시스템 메모리와 동일하지 않습니다.
vm.dirty_bytes
그리고vm.dirty_ratio
이 임계값 외에도 두 번째 임계값이 있습니다. 음, 이는 한계라기보다는 임계값이 아니며 vm.dirty_bytes
및 에 의해 제어 됩니다 vm.dirty_ratio
. 다시 말하지만, 공식적인 명칭이 없으므로 "더티 리미트"라고 부르겠습니다. 충분한 데이터가 "기록"되었지만 기본 블록 장치에 커밋되지 않은 경우 추가 시도는 write
쓰기 I/O가 완료될 때까지 기다려야 합니다. (나는 그들이 기다려야 하는 데이터에 대한 정확한 세부 사항을 모릅니다. 아마도 I/O 스케줄러의 기능일 것입니다. 모르겠습니다.)
왜?
디스크 속도가 매우 느립니다. 회전하는 녹의 경우 특히 그렇습니다. 따라서 디스크의 읽기/쓰기 헤드가 읽기 요청을 충족하기 위해 움직일 때 읽기 요청이 완료되고 쓰기 요청이 시작될 수 있을 때까지 쓰기 요청을 처리할 수 없습니다. (반대로)
능률
그렇기 때문에 쓰기 요청을 메모리에 버퍼링하고 읽은 데이터를 캐시합니다. 작업을 느린 디스크에서 더 빠른 메모리로 옮깁니다. 마침내 데이터를 디스크에 커밋하면 작업할 데이터의 양이 많아지고 탐색 시간을 최소화하는 방식으로 데이터를 쓸 수 있습니다. (SSD를 사용하는 경우 디스크 탐색 시간 개념을 SSD 블록 재플러시로 바꾸십시오. 재플러시는 SSD의 수명을 소모하며 SSD가 자체 쓰기로 숨기려고 시도하는 느린 작업입니다(성공 정도는 다양함). ).
vm.dirty_background_bytes
커널이 디스크에 데이터를 쓰려고 시도하기 전에 커널이 버퍼링하는 데이터의 양을 사용하고 조정할 수 있습니다 vm.dirty_background_ratio
.
버퍼링된 쓰기 데이터가 너무 많습니다.
기록하는 데이터의 양이 디스크에 도달할 수 있는 속도에 비해 너무 크면 결국 시스템 메모리를 모두 사용하게 됩니다. 첫째, 읽기 캐시가 사라질 것입니다. 즉, 메모리에서 제공되는 읽기 요청이 줄어들고 디스크에서 제공되어야 하므로 쓰기 속도가 더욱 느려집니다! 쓰기 압력이 여전히 완화되지 않으면 결국 메모리 할당은 쓰기 캐시가 일부를 확보할 때까지 기다려야 하며 이는 훨씬 더 혼란스러울 것입니다.
그래서 우리는 "잠깐만 요. 데이터가 더 나빠지기 전에 디스크에 데이터를 쓸 시간입니다."라고 말할 수 있습니다 vm.dirty_bytes
.vm.dirty_ratio
아직도 데이터가 너무 많아요
그러나 I/O의 하드 중지는 매우 지장을 줍니다. 디스크의 읽기 프로세스가 이미 매우 느려서 몇 초에서 몇 초 정도 걸릴 수 있습니다.분이 데이터를 새로 고치려면 vm.dirty_bytes
기본값 20을 고려하세요. 시스템에 16GiB RAM이 있고 스왑 영역이 없는 경우 3.4GiB의 데이터가 디스크에 플러시될 때까지 기다리는 동안 I/O가 차단될 수 있습니다. 128GiB RAM이 있는 서버에서 사용하시나요? 27.5GiB의 데이터를 기다리는 동안 서비스 시간이 초과됩니다!
vm.dirty_bytes
따라서 (또는 vm.dirty_ratio
원하는 경우) 꽤 낮게 유지하는 것이 도움이 됩니다 .이기다이 엄격한 임계값은 서비스에 최소한의 피해만 입힙니다.
좋은 가치란 무엇인가?
이러한 조정 가능한 매개변수를 사용하면 항상 처리량과 대기 시간 사이에서 균형을 유지하게 됩니다. 버퍼링이 너무 많으면 처리량은 높지만 대기 시간은 끔찍합니다. 버퍼가 너무 적으면 처리량이 떨어지지만 대기 시간이 길어집니다.
단일 디스크가 있는 워크스테이션과 노트북에서는 vm.dirty_background_bytes
약 1MiB, vm.dirty_bytes
8MiB에서 16MiB 사이의 설정을 선호합니다. 단일 사용자 시스템이 16MiB 이상의 처리량을 달성하는 경우는 거의 본 적이 없지만 웹 브라우저 데이터 스토리지와 같은 동기식 워크로드의 경우 지연 시간이 매우 길어질 수 있습니다.
스트라이프 패리티 배열이 있는 모든 항목에서 배열 스트라이프 너비의 배수가 좋은 시작 값이라는 것을 알았습니다. vm.dirty_background_bytes
그러면 패리티 가능성을 업데이트할 때 읽기/업데이트/쓰기 시퀀스를 수행할 필요성이 줄어들어 배열 처리량이 늘어납니다.
의 경우 vm.dirty_bytes
서비스가 겪을 수 있는 지연 시간에 따라 달라집니다. 나 자신은 블록 장치의 이론적 처리량을 계산하고 이를 사용하여 약 100밀리초 내에 얼마나 많은 데이터가 이동할 수 있는지 파악하고 vm.dirty_bytes
그에 따라 설정하는 것을 좋아합니다. 100ms의 대기 시간은 엄청나지만 (내 환경에서는) 치명적이지는 않습니다.
그러나 이 모든 것은 환경에 따라 다르며 이는 귀하에게 가장 적합한 것을 찾기 위한 시작점일 뿐입니다.