Redis) 이것이 레디스다 13 - 임계점

논리적으로 스케일 아웃의 한계는 없지만 현실적으로는 네트워크 대역폭 등의 한계가 있는데 이를 임계점이라 한다.

  • 여러개의 인스턴스를 하나의 서버에서 올릴 때

레디스는 하나의 코어(단일 쓰레드)를 사용하기 때문에 코어의 수보다 코어 하나의 성능이 레디스의 성능에 영향을 준다.

그렇다면 멀티코어 시스템에서 성능을 높이기 위해서 인스턴스 여러 개를 실행하는 방안을 생각해볼 수 있다.
CPU 코어의 갯수 만큼 인스턴스를 실행했을 때 첫번째 임계점은 CPU 리소스이다.
레디스에 모든 코어의 리소스가 투입된다면 OS 운용에 필요한 리소스가 부족하게 된다. 이는 OS 작동에 영향을 주게되고 결과적으로는 레디스 인스턴스에 응답 속도에 영향을 주게된다.

  • 메모리 대역폭

메모리 대역폭이란 1초에 전송할 수 있는 데이터의 양으로 정의된다.

레디스는 명령어 처리를 위해 메모리에 접근하고, 조회된 데이터는 메모리 대역폭을 사용해서 데이터 버스를 통해 해당 코어로 전송하게 된다.
여러 인스턴스가 메모리 대역폭을 나누어 사용하므로 병목현상이 발생하게 된다.
이와 같은 이유로 다중의 인스턴스를 실행할 때 메모리 대역폭이 충분해야한다.

  • 메모리 크기

레디스는 메모리에 데이터를 저장하기 때문에 레디스가 사용할 메모리의 크기를 지정하는 것은 성능과 가장 밀접한 관련이 있다.

redis.conf의 maxmemory 설정에 지정된 크기는 키를 위한 공간과 데이터를 위한 공간을 모두 포함한다.
그렇기 때문에 실제로 저장되는 데이터의 크기는 redisObject와 키가 저장된 크기를 뺀 나머지가 된다.
만약 저장되는 데이터가 작은 크기의 문자열일 경우 redisObject의 오버헤드가 더 크게되기 때문에 숫자로 바꾸거나, 다른 데이터타입을 사용하면 더 많은 데이터를 저장할 수 있다.

maxmemory 값을 지정하지 않은 경우
레디스에 데이터가 계속 추가되어 물리 메모리를 모두 사용한 경우,
OS는 애플리케이션이 사용가능한 물리 메모리보다 더 많은 메모리를 사용하려 할 때 swap(하드디스크에 가상 메모리를 생성)을 하게되는데 이때 레디스의 응답시간이 수십, 수백배로 늘어나게 된다.
그렇기 때문에 응답시간이 중요한 서비스의 경우 꼭 maxmemory를 설정하자.

※ swap 영역이 충분하지 않을 경우 OS는 동작 중인 프로세스를 제거하여 메모리를 확보(Out Of Memory Killer)하게 된다.

AOF나 스냅샷 사용을 설정할 경우 이를 위한 fork 함수가 동작하면 운영체제는 레디스가 점유하고 있는 메모리만큼 메모리를 다시 할당하려고 시도하게 된다.
지정된 레디스의 메모리 크기보다 많은 데이터를 저장하려 할 때 레디스는 쓰기 요청을 실패하고 메모리 영역을 확보하기 위해 기존 저장한 데이터를 삭제한다.

  • 네트워크

레디스 클러스터 구성에서 가장 많이 맞닥뜨리는 임계점 중 하나가 네트워크이다.

1Gbps 네트워크 카드의 최대 데이터 전송률은 약 125MB이고 실제로는 약 100MB 정도이다.
만약 각 서비스 사용이 많아져 초당 100MB 이상의 데이터가 요청이 될 경우
네트워크 허브가 처리할 수 있는 데이터 크기를 넘겼기 때문에 모든 노드가 데이터를 전송하기 위해 대기를 하게 될 것이고(병목) 노드 전체의 성능을 사용하지 못하게 된다.

또 추가로 복제를 위한 마스터와 슬레이브 간의 데이터 전송네트워크 단절에 의한 동기화가 있다.
첫째로, 위의 경우 마스터는 2개의 슬레이브를 갖기 때문에 마스터 노드의 쓰기 연산 1번당 복제를 위한 2번의 추가 트래픽이 발생한다.
둘째로, 마스터-슬레이브 연결이 끊어진 후 슬레이브 노드가 마스터 노드로 다시 연결하게되면 마스터 노드의 전체 데이터를 받아 동기화를 수행하게 된다.

이 같은 상황에서 임계점에 다다르는 것을 방지하기 위해서 다음과 같이 구성을 할 수 있다.

노드 서버의 두개의 네트워크 카드를 설치하고 클라이언트에서 읽기, 쓰기를 위해 사용하는 네트워크와 레디스 관리와 복제를 위한 네트워크를 따로 사용하는 것이다.
이와 같이 네트워크 대역폭을 분리하여 네트워크 병목현상을 피할 수 있다.

Share