본문 바로가기
언어 & 라이브러리/레디스

[레디스] 레디스 클러스터를 도커에서 구성해보자

by illlilillil 2022. 3. 17.

레디스 클러스터란?


센티넬보다 발전된 형태로 멀티 마스터 구조를 지원합니다.

샤딩을 지원해 데이터 분산으로 가용성을 높입니다.

Failover 기능으로 센티넬 없이 자동으로 노드 관리를 해줍니다.

cluster는 스케일 아웃이 가능합니다. 확장성이 좋습니다.

 

[Deprecated]

스케일 아웃 시에 해시 알고리즘의 이슈를 피하기 위해 Consistent Hashing을 적용해 모든 키의 재매핑을 막고 평균적인 키만 재매핑 시켜줍니다.

 

레디스 클러스터와 Consistent Hashing

Tech Note 정보 stdio.h 님이 작성하신 글입니다. 카테고리: [ NoSQL ] 게시됨: 03 December 2019 작성됨: 03 December 2019 최종 변경: 03 December 2019 조회수: 6438 1. 개요 2. 레디스 고가용성 2.1. failover 기본적인 Auto f

sarc.io

요즘은 해시 슬롯을 이용해 문제를 해결하고 있다고 합니다.

 

본론으로 돌아와 도커에 클러스터를 구성하고 설정 정보들을 확인해볼게요.

 

[Redis Cluster at Docker]


이번에도 docker-compose.yml를 이용해서 쉽게 컨테이너를 올려보겠습니다.

총 6개의 노드로 3개의 클러스터를 구성해보겠습니다.

1번 클러스터: master-7001, slave-7101

2번 클러스터: master-7002, slave-7102

3번 클러스터: master-7003, slave-7103

그 아래 17001~17103 포트는 클러스터 간 통신을 위해 열어두어야 합니다.

version: '3'
services:
  redis-master-1:
    container_name: redis-master-1
    image: redis
    network_mode: "host"
    command: redis-server /etc/redis.conf
    volumes:
      - ./redis-master-1.conf:/etc/redis.conf
    restart: always
    ports:
      - 7001:7001
      - 17001:17001

  redis-master-2:
    container_name: redis-master-2
    image: redis
    network_mode: "host"
    command: redis-server /etc/redis.conf
    volumes:
      - ./redis-master-2.conf:/etc/redis.conf
    restart: always
    ports:
      - 7002:7002
      - 17002:17002

  redis-master-3:
    container_name: redis-master-3
    image: redis
    network_mode: "host"
    command: redis-server /etc/redis.conf
    volumes:
      - ./redis-master-3.conf:/etc/redis.conf
    restart: always
    ports:
      - 7003:7003
      - 17003:17003

  redis-slave-1:
    container_name: redis-slave-1
    image: redis
    network_mode: "host"
    command: redis-server /etc/redis.conf
    volumes:
      - ./redis-slave-1.conf:/etc/redis.conf
    restart: always
    ports:
      - 7101:7101
      - 17101:17101

  redis-slave-2:
    container_name: redis-slave-2
    image: redis
    network_mode: "host"
    command: redis-server /etc/redis.conf
    volumes:
      - ./redis-slave-2.conf:/etc/redis.conf
    restart: always
    ports:
      - 7102:7102
      - 17102:17102

  redis-slave-3:
    container_name: redis-slave-3
    image: redis
    network_mode: "host"
    command: redis-server /etc/redis.conf
    volumes:
      - ./redis-slave-3.conf:/etc/redis.conf
    restart: always
    ports:
      - 7103:7103
      - 17103:17103

추가로 각 노드들의 설정을 위해 redis.conf 파일도 경로 내에 있어야 합니다.

# vi redis-master-1.conf로 따로 만드셔야 합니다.

# redis-master-1.conf
port 7001
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
appendonly yes

# redis-master-2.conf
port 7002
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
appendonly yes

# redis-master-3.conf
port 7003
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
appendonly yes

# redis-slave-1.conf
port 7101
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
appendonly yes

# redis-slave-2.conf
port 7102
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
appendonly yes

# redis-slave-3.conf
port 7103
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
appendonly yes

 

완성된 폴더 구조

컨테이너 띄우기

docker compose up -d
//버전에 따라 다를 수 있습니다.
docker-compose up -d

성공입니다. 하지만 아직 끝이 아니에요

 

쉘에 진입하겠습니다.

docker exec -it redis-master-1 bash

클러스터를 생성해줘야 합니다.

redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003

 

명령어를 입력하면 3개의 마스터 노드에 자동 샤딩이 적용되어 해시 값에 따라 저장되는 슬롯이 다르게 됩니다.

그러나 여기서 마스터가 죽게 된다면 어떻게 될까요 ? 대체할 데이터가 없어 데이터 손실이 발생합니다.

따라서 Master의 값을 읽어오는 Slave가 필요합니다.

 

아래 코드로 slave를 추가해주세요.

[slave 추가]
redis-cli --cluster add-node 127.0.0.1:7101 127.0.0.1:7001 --cluster-slave
redis-cli --cluster add-node 127.0.0.1:7102 127.0.0.1:7002 --cluster-slave
redis-cli --cluster add-node 127.0.0.1:7103 127.0.0.1:7003 --cluster-slave

Cluster 정보 확인을 위해 redis-cli에 진입해보겠습니다.

redis-cli -c -p 7001

 

cluster info

클러스터에 설정된 정보들을 확인할 수 있습니다.

 

cluster nodes

명령어로 master slave들의 관계 파악이 가능합니다.

 

값을 넣어 데이터가 어디로 저장되는지 확인해보겠습니다.

set cluster1 hello
set cluster2 hello
set cluster3 hello

해시가 적용된 값에 따라 각기 다른 노드에 적용된 점을 확인하실 수 있습니다.

코드를 보면 cluster2, cluster3은 7001번 노드에 저장됐습니다. 그러면 slave 노드인 7101에도 저장이 되는지 확인해볼까요 ?

docker exec -it redis-slave-1 bash

redis-cli -c -p 7101

정상적으로 Replication이 된 것을 볼 수 있습니다.

 

[FailOver]

만약 마스터1 노드가 죽는다면 레디스가 어떻게 대응하는지 알아보도록 하겠습니다.

아래는 slave-1 노드의 로그입니다. 

마스터 노드와의 연결 요청을 수차례 요청하고 연결이 안될땐 Failover 임을 확인하고 해당 slave 노드를 Master 노드로 바꿔줍니다.

 

만약 장애 복구가 되어 원래의 Master가 복구되면 어떻게 되는지 궁금했습니다. 다시 살려보겠습니다.

아래는 Master node였던 노드의 로그입니다.

알아서 설정 파일을 읽고 현재의 마스터 노드의 데이터를 읽어와 동기화를 수행하는 모습을 확인할 수 있습니다.

 

cluster nodes 명령어로 확인해도 자동으로 클러스터 노드로 재등록됩니다.

 

이렇게 레디스 클러스터에서 해주는 일이 많아 개발자가 복구해야 할 부분이 많이 줄어들었다고 생각합니다.

하지만 여전히 문제는 있습니다.

Redis Master 서버에 데이터가 들어오고 Slave에 아직 데이터가 들어오지 않은 상황에서 Master 노드가 ShutDown이 된다면 데이터를 받지 못한 Slave가 Master로 승격됩니다. 따라서 데이터 정합성에 문제가 생길 것 입니다.

 

 

 

[참조 링크]

 

2. Redis 샤딩

서론 이전 포스팅에서 Redis의 기본적인 구조와 복제(Replication)에 대해서 살펴봤습니다. 잠시 복기해보자면, 복제는 Master의 데이터를 Replica에 모두 저장하여 가용성과 읽기 작업의 성능을 높일 수

cla9.tistory.com

 

댓글