ZFS ARC thrashing 현상 대응 방법

computerphilosopher·2025년 6월 28일
0
post-thumbnail

정의

캐시는 히트에 실패할 시, 원본에서 읽은 내용을 새로 적재한다. 이 때 적재할 공간이 모자라면 최근에 조회되지 않았거나(LRU), 자주 조회되지 않는(LFU) 아이템을 제거해서(eviction) 공간을 확보한다. 그런데 캐시 히트에 계속 실패할 경우 기존 아이템을 제거하고 새 아이템을 적재하는 현상이 계속 발생하면서 오히려 캐시를 사용하지 않을 때보다 성능이 크게 떨어지는 현상이 발생한다. 이러한 현상을 캐시 스래싱(Cache thrashing) 이라 한다. 스래싱은 하드웨어의 캐시 메모리, memcached나 redis 등의 어플리케이션용 캐시 등 캐시라면 어디서나 발생할 수 있는 현상이다.

ZFS ARC(Adaptive Replacement Cache)는 ZFS 파일시스템 에서 파일 조회 성능을 높이기 위해 사용하는 캐시 메모리 공간이다. 여기서도 캐시 스래싱 현상이 발생할 수 있다. ZFS는 주로 고성능 io를 요구하는 데이터베이스 서버에서 주로 사용하므로 캐시 스래싱이 바로 심각한 서비스 장애를 유발할 수 있다.

진단

다음 증상이 나타날 때 ARC의 캐시 스래싱을 의심할 수 있다. 진단에 쓰이는 메트릭들에 미리 알림을 걸어놓자.

  • CPU iowait 수치가 20% 이상으로 유지된다.
  • CPU system mode 사용률이 이전에 비해 높아진다.
  • arc_stat 등의 명령어로 조회했을 때 캐시 히트율이 평소에 비해 떨어진다. (이 방법을 통해 감지하려면 평상시의 캐시 히트율을 모니터링하고 있어야 한다.)
  • arc_prune, arc_evict 라는 커널 스레드가 CPU를 90% 이상 사용한다.

제일 확실한 감지 방법은 arcstat 명령어로 캐시 히트율을 확인해보는 것이다. arcstat의 출력은 버전마다 조금씩 다른데, miss%나 ddh% 컬럼을 보면 된다. 미스 비율이 10%가 넘어가는 것은 일반적이지 않다.

대응

터미널에 다음의 명령어를 입력한다.

echo 3 > /proc/sys/vm/drop_caches

리눅스 커널은 이 파일에 쓰이는 값을 감지해 파일 시스템 관련 캐시들을 제거한다. 출력 내용이 1, 2, 3 일때 각각 동작이 다르다.

-echo 1: 페이지 캐시 제거

  • echo 2: slab 객체(메모리를 일정한 크기의 블록으로 나누어 할당하는 slab allocator에 의해 할당된 객체) 캐시 제거
  • echo 3: 페이지 캐시와 slab 객체 모두 제거

리눅스 커널 문서에서는 이 명령어를 비파괴적(non-destructive) 이라고 명시하고 있다. 파일을 삭제하거나 파일 시스템의 정합성을 깨트리지 않는다는 뜻이다. 파일시스템의 캐시에는 프로세스가 쓰기를 요청하긴 했으나 아직 디스크에 반영되지 않은 아이템(dirty item)도 있는데, 이런 아이템들은 제거하지 않는다. 따라서 캐시를 비웠다고 해서 데이터가 손실되는 현상은 발생하지 않는다.

그러나 비워진 캐시를 다시 적재하기 전까지 CPU 사용량과 Disk IO가 증가하면서 성능 저하가 발생할 수 있다. 캐시 스래싱이 문제가 될 정도로 IO가 잦은 시스템에서는 성능 저하가 거의 필연적으로 발생한다고 봐야 한다. 그러나 한 번 스래싱이 발생하면 언제 해소될지 알 수 없다. 일시적인 성능 저하를 감수하고서라도 캐시를 초기화 하는 것이 좋다.

예방

원론적으로는 스래싱 예방을 위해 캐시에 더 큰 메모리 공간을 할당해야 한다. 하지만 ARC가 사용하는 기본 공간이 워낙 커서 더 키우는 것은 쉽지 않다.

ARC의 크기는 arc_max 설정으로 조절할 수 있는데 OpenZFS 공식 문서에서 나오는 기본값은 다음과 같다.

  • 리눅스: 시스템 메모리의 1/2
  • FreeBSD: max(시스템 메모리 - 1GB, 5/8 * 시스템 메모리)

보다시피 별 설정을 하지 않아도 ARC는 이미 시스템 메모리를 최소 절반은 사용한다. 서버 OS가 FreeBSD 라면 더 이상의 공간을 할당하기가 불가능한 수준(메모리가 32G라면 약 96% 이상 사용)이다.

공식 문서에서는 서버의 다른 어플리케이션이 메모리를 많이 사용하면 경쟁을 방지하기 위해 ARC를 줄이라고 권하고 있다.

Reduce if ARC competes too much with other applications, increase if ZFS is the primary application and can use more RAM

즉 커널 OOM의 리스크를 부담하기 싫다면 스케일업 밖에 답이 없다.

참고 자료

리눅스 커널 문서 중 drop_caches에 대한 설명

ZFS 문서 중 zfs_arc_max에 대한 설명

0개의 댓글