참고
Redis 공식 scaling 튜토리얼 문서
참고
redis cluster 간단하게 구성해보기
참고
Docker로 Redis 클러스터 구성하기
지난 글에서까지는 Redis를 Master + Slave 구성하여 Spring에서 사용하는 방법을 확인해 보았다. Master + Slave 구조를 이해했으니 이제 Cluster로 구성해보자.
Cluster로 구성하는 이유는 Redis Server를 Mater와 Slave로만 구성했을 때 Master가 죽게되면 read만 가능해지며 다른 작업들은 모두 실행되지 않는다. 이때 Cluster로 여러대의 Master를 구성시켜놓으면 최초의 Master 서버가 죽게된다면 이후 대기중인 서버의 Master Redis Server가 마스터로 승격되어 해당 작업을 이어갈 수 있는 것이다.
그리고 만약 redis의 메모리량을 늘려주어야하는 작업이 필요한데 이 작업을 redis 서버의 크기만 키워서 스케일업
하는 것이 아닌 Cluster로 구성하면 여러대의 Redis 서버를 연결시켜 스케일 아웃
이 쉽게 가능하기 때문이다.
scale-up : 단일 서버의 스펙을 올려 서버 성능을 높힌다.
scale-out : 서버를 추가하여 서버 성능을 높힌다.
cluster 구성을 위해서는 redis server가 최소 3개 이상 있어야하며 배포시에는 6개의 노드(=redis server)로 구성하는 것을 권장한다. 그래서 6개의 서버를 구성하는 방식으로 진행해보자!
먼저 conf 파일을 만들어야한다.
port 7000
#cluster 사용 여부
cluster-enabled yes
#cluster 설정 파일 이름
cluster-config-file node.conf
#timeout 시간 지정 (ms)
cluster-node-timeout 5000
#failover된 redis node 재실행 시 이전 데이터를 다시 로드해올 수 있음
appendonly yes
port 7001
...
port 7002
...
port 7003
...
port 7004
...
port 7005
...
각 파일들을 만들어서 적용한다.
...
은 동일한 내용이라 생략했다.
여기서 중요한 것은 첫번째 redis server는 각 redis들을 묶어줄 cluster의 master 개념이고 나머지 redis들은 저장소의 역할을 할 master-slave관계를 가질 redis들이다.
파일들은 각 폴더에 넣어도 되고 파일로만 해도 된다.
version: '3.7'
services:
node1:
container_name: node1
image: redis
volumes:
- ./conf1:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
ports:
- 7000:7000
- 7001:7001
- 7002:7002
- 7003:7003
- 7004:7004
- 7005:7005
node2:
network_mode: "service:node1"
container_name: node2
image: redis
volumes:
- ./conf2:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
node3:
network_mode: "service:node1"
container_name: node3
image: redis
volumes:
- ./conf3:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
node4:
network_mode: "service:node1"
container_name: node4
image: redis
volumes:
- ./conf4:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
node5:
network_mode: "service:node1"
container_name: node5
image: redis
volumes:
- ./conf5:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
node6:
network_mode: "service:node1"
container_name: node6
image: redis
volumes:
- ./conf6:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
redis-cluster-entry:
network_mode: "service:node1"
image: redis
container_name: redis-cluster
command: redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1 --cluster-yes
depends_on:
- node1
- node2
- node3
- node4
- node5
- node6
내용이 좀 길다. 여기서 중요한 내용만 딱 살펴보자.
node1
잘 살펴보면 node1에만 ports가 적혀있고 network-mode라는 옵션이 없다. 그 이유는 network-mode 옵션으로 다른 node들이 모두 node1 네트워크를 공유해서 사용하기 때문이다.
다른 글을 보면
netowrk_mode: host
옵션을 사용하기도 하는데 해당 옵션은 linux에서는 잘 되지만 window나 mac의 경우 잘 안될 수 있다고 한다.
그래서 network_mode 옵션의 service:node1 이라고 service의 node1 을 명시해준다.
redis-cluster-entry
의 역할은 command에 입력된 명령어를 실행하고 종료되는 역할이다. 해당 명령어를 통해 redis server들을 cluster로 묶어주는 역할을 한다.
여기서 명령어에 --cluster-replicas 1 --cluster-yes
각 옵션이 들어가는데 해당 옵션을 하나 씩 보자.
--cluster-replicas 1
옵션은 cluster를 구성할 때 master-slave 구성을 한다는 의미다. 여기서 1이란건 slave의 갯수이다. 참고로 slave는 cluster를 만들 때 사용한 명령어에 적힌 순서대로 redis가 자동으로 나눠서 붙여준다.
--cluster-yes
위에서 cluster를 구성하며 설정에 대해 묻는데 -yes 옵션을 통해 모두 예로 대답하게 만든다. 이 옵션이 없으면 멈춰있으니 꼭 줘야한다.
docker-compose up -d
명령어를 통해 다음과 같이 node들을 실행시키자.
docker-compose logs
명령어를 통해 로그를 확인하면 다음과 같이 redis에 각 slot을 할당하고 master와 slave 관계를 만들었다는 ok가 뜨면 정상 실행된 것이다.
그럼 이제 데이터를 set해보고 get도 해보자!
나는 master 중 하나인 node2번에 접근해보려고 한다. 여기서 중요한건 redis-cli를 실행시킬 때 -c -p [포트번호]
를 통해 cluster 옵션과 port 옵션을 꼭 주어야한다는 것이다.
그 후에 set a hello
를 통해 set을 진행하면 다음과 같이 7002번에 해당하는 슬롯에 데이터가 저장되었다는 OK와 함께 자동으로 리다이렉트가 된다.
get a
를 통해서 7001번에서 저장한 a의 데이터가 잘 나오는 것도 확인이 가능하다!
그럼 여기서 7002번을 죽여버리면 어떻게 될까?
글이 잘 보일지 모르겠지만 7002번에 해당하는 node2의 slave였던 node5가 연결을 거절당했다는 에러와 함께 자신이 새로운 master가 되었다는 로그가 찍힌다. 그럼 다시 set을 해보자
이번엔 7000번에 해당하는 node1번에서 진행했다.
7000번으로 리다이렉션 되고 데이터가 정상적으로 들어가는 것을 확인할 수 있다!
slave에서 set할 수 있을까?
잘 된다.
그럼 다른 node에서 get도 할 수 있을까?
7002번의 slave였던 node5에서는 자신이 가지고 있던 데이터 a에 대해서는 바로 반환해주며 b를 호출할 경우 데이터가 있는 7000번 node1로 리다이렉션 해주었다.