Operation/System Architecture

대규모 서비스 - I/O 부하 (느려졌다고 무조건 서버 증설? No!)

JaeHoney 2021. 12. 25. 13:35

부하 종류

일반적으로 부하는 크게 두 가지로 분류됩니다. 

  • CPU 부하
  • I/O 부하

 

CPU 부하는 무언가를 계산할 때 일어나는 부하를 말합니다. CPU 부하의  규모조정은 간단합니다. 같은 구성의 서버를 늘리고, 로드밸런서로 분산을 시키면 됩니다.

 

반면, I/O 부하의 규모조정은 어렵습니다. I/O 부하란, 입력, 출력에 생기는 부하를 말합니다. 예를 들어, DB에 접근할 때 DB의 레코드 데이터를 출력하거나, DB에 데이터를 입력할 때 생기는 부하입니다.

 

(I/O 부하를 해결하기 위해서 각 OS마다 캐시를 이용해서 메모리를 추상화 합니다.) 

 

부하 파악

sar 명령어(sar command)로 CPU 사용률과 I/O 대기율을 확인할 수 있습니다. %user는 사용자 모드에서의 CPU 사용률이고, %system은 시스템 모드에서의 CPU 사용률입니다. 따라서, 두 지표가 높다면 CPU 리소스가 부족하다고 판단할 수 있습니다. 반면 I/O 대기율인 %iowait가 높다면 부하의 원인이 I/O 부하라는 판단을 할 수 있습니다.

 

I/O 부하의 특징

I/O 부하는 디스크에 읽고 쓸 때 생기는 부하이므로, 크기가 크다고 할 수 있습니다. CPU는 일반적으로 디스크보다 10^6 ~ 10^7 정도 빠르기 때문이죠. I/O 부하는 분산시키기도 어렵고 까다로운데다가, 서버의 대수를 많이 늘려봐야 디스크의 속도가 태생적으로 느려서 발생되는 문제이므로, 해결되지 않고 오히려 동기화만 어려워질 수 있습니다.

 

따라서, 무작정 서버의 대수를 늘린다면 프로젝트 주체에 큰 손실이 발생할 것입니다. 서버 리소스 중 어디가 병목이 되고 있는지를 정확히 판단하는 것이 중요합니다.

 

해결 방법

CPU 부하의 경우 간단히 서버를 늘리고 로드밸런서로 부하를 분산하면 됩니다. 하지만, 앞서 말씀 드렸다시피 I/O 부하는 서버의 대수를 늘려도 근본적으로 해결할 수 없습니다.

 

어차피 대수를 늘려봐야, 프로젝트에 비해 캐싱할 수 있는 공간이 부족한 점은 동일하기 때문에 늘린 서버도 같은 문제가 발생합니다.

 

디스크 참조가 아니라 캐싱을 이용해서 더 빠른 저장 장치를 이용할 수 있게 해줘야 원천적으로 해결할 수 있습니다.

 

 

1. 메모리를 늘리는 방법

어떤 서비스에서는 RAM을 4GB를 쓰고 있었고, $iowait가 20정도가 나왔었는데, RAM을 8GB로 교체해서 $iowait가 0.7정도로 내려갔다고 합니다. 즉, 원래 캐싱할 수 있는 메모리가 부족해서 디스크를 참조하게 되어서 I/O부하가 발생했던 것이죠.

 

 

2. 데이터 압축 알고리즘 적용

메모리를 늘리지 않고, 보관되는 데이터의 크기를 줄이는 것이죠. LZ법 같은 일반적인 압축 알고리즘을 적용해도 데이터의 크기를 절반 이하로 줄일 수 있습니다. 대신 압축할 때 I/O가 아닌 CPU에서 부하를 조금 사용해야 하겠죠!

 

 

3. 국소성을 고려한 서버 분산

 

국소성을 고려한 서버 분산은 크게 두가지 방법이 있습니다.

 

3-1. 서버의 대수를 늘리고 각 서버가 특정한 범위(특정한 서비스, 특정한 테이블 등)만 담당한다면, 그 특정한 범위의 데이터만 I/O가 발생하므로, 캐싱할 수 있는 가능성이 훨씬 높아진 다는 것을 의미합니다.

 

3-2. 데이터를 해시해서 파티셔닝을 적용하면, 더 작은 범위의 데이터를 담당할 수 있게 됩니다. 따라서, 각 서버가 본인이 분담한 범위의 데이터들만 담당하는거죠!