백엔드 개발자

Redis 클러스터링 구축하기 본문

CS/데이터베이스

Redis 클러스터링 구축하기

임잠탱 2024. 9. 22. 03:08

프로젝트 성능 개선을 위해 부하테스트 툴인 JMeter를 활용했다.

그리고 특정 API에 대해서만 오류 80% 정도로 아주 높게 측정되었고, 해당 api를 보니 외부 api를 호출하는데 매 요청마다 호출하고 있었다. 이건 그날의 뉴스 정보를 가져오는 api라 캐싱하여 사용하기 위해 Redis를 이용하였다.

그런데 오히려 성능이 더 떨어지고 다른 api들까지 오류가 났다.
Redis를 살펴보니 메모리 사용률이 80퍼 였다....

    // 이 명령어로 메모리 정보를 확인할 수 있다.
    redis-cli info memory

    //대략 이런 정보들을 확인할 수 있다. _human이 붙은게 우리가 보기 쉬운 형태로 변환해 준 값이다. 기본은 바이트 단위이다.
    # Memory
    used_memory:1525296
    used_memory_human:1.45M
    used_memory_rss:3633152
    used_memory_rss_human:3.46M
    used_memory_peak:1888976
    used_memory_peak_human:1.80M
    used_memory_peak_perc:80.75% => 이게 사용률이다.
    used_memory_overhead:1011656
    used_memory_startup:946096
    used_memory_dataset:513640

Redis를 한 대만 사용하고 있어서 나중에 클러스터링 구축해봐야지 했었는데 이김에 구축해보기로 했다.
Redis에서는 클러스터(자동 파티셔닝), 자동 복제 등을 지원해 주기 때문에 쉽게 구축할 수 있다.
클러스터링을 구축할 세 개의 노드와 그 안에서 마스터-슬레이브 구조를 구성하기로 했다.

마스터-슬레이브 구조는 부하분산을 위해 쓰이는데 쓰기 연산은 마스터 노드에서만 일어나고, 읽기는 마스터, 슬레이브가 나눠서 처리한다.
슬레이브 노드에서는 마스터 노드의 변경 사항을 계속 동기화 하여 유지하고, 보통 읽기 연산이 많기 때문에 부하를 줄일 수 있게 된다.

그래서 클러스터를 구축하여 여러 마스터 노드에 샤딩 방식으로 데이터를 나눠 저장하고, 이 마스터 노드 각각은 마스터-슬레이브 구조를 통해
읽기 연산은 분산하여 처리함으로써 높은 가용성과 성능을 향상 시켜준다.

이를 위해 우선 서버를 세 대 준비하고 각각 레디스를 설치해줬다.
서버는 aws ec2서버 사용하였고 t3.small로 세 대 만들었다.

1.  도커를 사용해 레디스를 설치할 것이기 때문에 도커를 설치해줬다.
2.  `sudo apt update sudo apt install docker.io`
3.  클러스터 구축을 위해 redis.conf 파일을 만들어줘야 한다.  


-   도커 볼륨 생성  
    docker volume create redis\_data
-   도커 볼륨 생성 위치 확인  
    docker volume inspect redis\_data

"Mountpoint": "/var/lib/docker/volumes/redis\_data/\_data" => 볼륨이 생성된 경로를 확인할 수 있다.

-   호스트 마운트 된 위치에 redis.conf 파일 생성

sudo vim /var/lib/docker/volumes/redis\_data/\_data/redis.conf

// redis.conf  
port 6379  
cluster-enabled yes  
cluster-config-file nodes.conf  
cluster-node-timeout 15000  
appendonly yes

cluster가 가능하게 해주는 설정들과 데이터 내구성 보장을 위한 백업 기능인 appendonly를 선택적으로 추가할 수 있다.
  1. 이제 redis를 실행해주면 된다.
docker run -d -p 6379:6379 -p 16379:16379 -v redis\_data:/usr/local/etc/redis --name redis-cluster1 redis redis-server /usr/local/etc/redis/redis.conf
  1. 이걸 세 대의 서버에서 모두 진행한다. 클러스터 구축에 최소 3대 이상을 필요로 하기 때문에 더 많은 수를 두어도 되고, 한 서버 안에서 redis를 여러개 띄워도 된다. 하지만 고가용성 보장을 이유로 서버를 다 나눠보고 싶어서 이렇게 했다.
    서버에서 모두 위 과정을 진행한 후, 클러스터 구축을 위해 서로의 서버에서 포트 6379, 16379는 통신을 할 수 있도록 허용해 주어야 한다.

모두 완료하였다면 redis에서 제공해주는 기능으로 간편하게 구축할 수 있다.

-   우선 클러스터에 포함 될 노드 중 하나의 Redis 컨테이너에 접속해주어야 한다.  
    docker exec -it redis-cluster1 bash

redis-cli --cluster create {노드1서버주소}:6379 {노드2서버주소}:6379 {노드3서버주소}:6379

그럼 짜라란


이런 화면이 나올 것이다. (이 사진은 create에 대한 사진이 아닌데 이전 것들이 지워져서 대충 비슷한걸로 대체했다..)
자동으로 쉽게 구축이 됐다.


// 클러스터 구성 노드들을 확인할 수 있다.  
redis-cli cluster nodes

세 개의 노드들이 나올 것이고 마지막에 슬롯 범위도 표시되는데 0부터 X까지는 이 노드에 저장되고, X~ Y는 xx노드에 ....  
이렇게 자동으로 샤딩 기능이 적용된 것이다.

그리고 이제 각각의 슬레이브 노드를 생성해주어야 한다.
이것도 위의 과정과 비슷하다. 각 서버에서 도커로 레디스를 띄워주면 되는데 포트번호를 겹치지 않게 매핑해주면 된다.
나는 6380, 16380을 사용했다.

위에 다시 보면 볼륨 생성하고, 해당 위치에 redis.conf파일 만들고 도커를 실행해주면 된다.
차이가 있는 점은 redis.conf파일에서 슬레이브 노드까지 백업을 할 필요는 없어서 appendonly yes 이 부분을 제거해주었다.


// 그리고 이렇게 실행해주면 된다. redis-slave\_data 이건 생성한 volume 이름을 적어주면 된다.  
docker run -d -p 6380:6379 -p 16380:16379 -v redis-slave\_data:/usr/local/etc/redis --name redis-cluster1-slave redis redis-server /usr/local/etc/redis/redis.conf

3개 서버 모두 완료하였다면 다시 마스터 노드 중 하나에 접속해보자. (이것도 마찬가지로 6380, 16380 포트에서 서로 연결이 가능하도록 해주어야 한다.


docker exec -it redis-cluster1 bash

// 클러스터에 슬레이브 노드를 추가해준다. 우리는 슬레이브 서버와 마스터 서버의 주소가 같을 것이다.  
redis-cli --cluster add-node {슬레이브 서버의 주소}:6380 {마스터 서버의 주소}:6379 --cluster-slave


짜안 이렇게 추가가 되는 것을 확인할 수 있다.


// 명령어를 통해 slave 노드가 하나 연결된 것을 확인할 수 있다.  
redis-cli cluster info

// 마찬가지로 전체 연결된 노드들을 확인할 수 있다.  
redis-cli cluster nodes

info에는 slave연결이 된 것을 확인할 수 있었는데 전체 nodes를 확인하면 그대로 마스터 노드 세 개 밖에 없어서 명시적으로 지정을 해줬다.

redis-cli cluster meet {서버 주소} 6380 => 너 얘 알아 몰라

이렇게 각각 각 서버에 대해 실행해주니 잘 추가되었다.

이제 끝이다 아주 간단하게 구성 완료했다.


// 하나의 레디스 컨테이너 접속 후 해당 명령어를 실행해보면 이런 결과를 볼 수 있다.  
127.0.0.1:6379> get a  
(error) MOVED 15495 15.165.201.149:6379  
127.0.0.1:6379> get b  
(nil)

데이터가 나눠 저장되기 때문에 key a에 대해서는 이 노드가 관리하는 것이 아니라는 것을 알 수 있다.

슬레이브 복제 확인


우선 마스터 노드에 접속한다.

> docker exec -it redis-cluster1 bash  
> redis-cli  
> set b test  
> OK  
> get b  
> test  
> // 데이터가 잘 저장된 걸 확인한다.

다시 슬레이브 노드로 가보자. 슬레이브 노드에서 직접 get을 하여 확인할 수 없다.  
모든 요청은 마스터 노드로 요청되고 관리되기 때문이다. redis.conf 파일에서 읽기 모드 설정해서 가능하게 할 순 있지만 다른 방법으로 확인해보자.

1.  redis-cli info replication

> # Replication
> 
> role:slave  
> master\_host:54.180.130.253  
> master\_port:6379  
> master\_link\_status:up  
> master\_last\_io\_seconds\_ago:1  
> master\_sync\_in\_progress:0  
> slave\_read\_repl\_offset:18715  
> slave\_repl\_offset:18715

이렇게 복제 정보를 확인할 수 있다. 마스터 노드 호스트, 연결 상태 등을 확인하면 잘 연결이 되어 있다.  
로그를 살펴봐도 뭔가를 막 복제하고 있다.

2.  redis-cli info keyspace

> db0:keys=1,expires=0,avg\_ttl=0,subexpiry=0

데이터베이스에 저장된 키 개수를 확인할 수 있다.

이렇게 간접적으로나마 대충 확인을 해 보았다 ㅎㅎ

이 정도로 확인을 해보았는데 이 외에도 레디스는 장애 복구나 노드 추가 시 슬롯 재분배 등 다양한 기능을 지원해준다.
이제 레디스 연결하고 JMeter 통해서 다시 성능 테스트를 진행해 봐야겠다!! 참고로 마스터 노드 중 하나에 연결해서 사용하면 된다. 끝!
```

'CS > 데이터베이스' 카테고리의 다른 글

인덱스  (1) 2025.01.02
DB 트랜잭션과 격리 수준  (0) 2024.11.07
SQL JOIN 종류 [ INNER JOIN, LEFT JOIN, RIGHT JOIN, OUTER JOIN]  (1) 2023.08.31
Comments