레디스 사용법, 복구, 자료구조 같은 건 알고 있었지만 조금 더 딥한 내부 동작 원리를 알고 싶었다.
*3 // 인자의 갯수
$3 // 인자 1의 바이트 수
set // 인자 1
$5 // 인자 2의 바이트 수
mykey // 인자 2
$6 // 인자 3의 바이트 수
value1 // 인자 3
이런 식으로 이루어져 있다.
앞의 1바이트 값이 응답 데이터 종류를 의미한다.
+ : 상태 응답- : 에러 응답: : 숫자 응답$ : 단일 벌트 응답* : 멀티 벌크 응답응답 예시는 아래와 같다.
+OK
:10
우선 Redis는 ANSI C로 개발 되어 있다.
레디스에서 저장된 데이터를 관리하기 위해서는 redisObject라는 객체를 통해 관리된다.
문자열 데이터와 해시 데이터는 모두 redisObject 객체를 사용해서 저장한다.
아래와 같은 정보가 포함되어 있다.
너무 지협적인 내용이 많아 개발자가 알아야할 내용만 간단히 요약한다.


샤딩은 데이터를 나누어 저장하는 것을 의미한다.
이로 인해 얻게 되는 것은 다음과 같다.
레디스 클라이언트의 샤딩 방법은 다음과 같다.
샤딩을 하며 샤딩 단위로 마스터 슬레이브를 만들 수 있다.
근데 좀 아쉬운 점은 이런것들을 모두 클라이언트 단에서 처리해야한다는 것이다.
그래서 보통은 헬퍼클래스를 만들어서(유틸성)이를 처리한다고 한다.
그러니까 즉 샤딩이던 복제던 10개의 인스턴스가 띄워져 있으면, 클라이언트 앱이 이를 인식하고 분산해서 읽고 써야 한다는 것이다. 🤔
알다 싶이 레디스는 단일 쓰레드로 동작한다. 따라서 여러개의 코어가 있는 서버에 띄워도 하나의 코어만 사용한다.
따라서 멀티 코어 서버에서 실행을 고려한다면 코어 수만큼 여러개의 레디스를 띄우는 것을 고려할 있다.
위와 같은 이유로 단일 머신에서 여러대의 레디스 인스턴스를 수행할 때, 각 프로세스가 동시에 메모리를 접근하려고 시도하게 된다. 이 때 각 프로세스가 메모리 버스 대역폭을 소모하므로, 병목현상이 발생한다.
redis.conf의 maxmemory 설정을 하지 않고 사용하는 경우
운영체제에 계속해서 추가적인 메모리를 요청하게 되고, 스왑메모리라는 가상 메모리를 생성하여 사용한다.
이 때 레디스의 응답시간은 수 십배에서 수 백배까지 늘어나게 된다.
이 스왑까지도 충분하지 않으면, 운영체제가 실행 중인 프로세스를 kill해서 메모리를 확보하게 된다. 이것이 그 유명한 OOM 킬러라고 한다.
그래서 OOM 킬러를 피하려면 꼭 maxmemory를 물리메모리 이내의 값으로 설정해야한다.
maxmemory 설정값은 데이터만을 위한 것 뿐만 아니라 키라던지 부가적인 용량이 포함된다. 따라서 4GB로 설정한다면 실제 저장가능한 데이터는 이보다 작다.
일반적으로 운영체제는 설치된 메모리의 두배 만큼 스왑공간을 확보한다.
하지만 요즘같이 메모리 크기가 커진 상황에서는 이 값을 설정할수 있게 하는 경우가 있다.
만약 레디스에서 AOF나 스냅샷같은 영구 저장소 기능을 사용한다면, 스왑영역은 최소한 물리메모리 크기만큼은 확보되도록 설정해야 한다. 그 이유는 AOF나 RDB을 위한 fork()함수가 실행되면 현재 레디스가 사용하고 있는 만큼의 메모리를 확보하려고 시도하게된다.
이 두가지 상황을 잘 고려해야한다. 즉 이러한 과정속에서 네트워크 대역폭이 심하게 점유당한다.
따라서 네트워크 허브를 두개로 분리해서, 복제를 위해 사용하는 대역폭과 레디스 접속에 사용하는 대역폭을 분리하는게 중요하다.