Docker-compose로 Redis-Cluster구성(with Predixy)

김예지·2024년 2월 29일
0

23-2 캡스톤 디자인

목록 보기
8/8

클러스터 환경에서 Redis Streams의 효용을 확인하고자 Redis Cluster를 구성하였다.

Predixy란

Predixy는 레디스 클러스터 앞단에서 프록시 기능을 지원한다.

  • redis cluster에서 key가 분산되어 저장될 때, 클라이언트 키가 어디 있는지 찾을 필요 없이 Predixy가 처리
  • master/slave 읽기 처리 비율 조정 가능

구성

디렉토리 구조도

1) .conf 파일

opt
├── predixy
│   └── conf
│       ├── auth.conf
│       ├── cluster.conf
│       ├── latency.conf
│       └── predixy.conf
└── redis
    ├── 7000
    │   ├── 7000.conf
    │   ├── 7001.conf
    │   └── 7002.conf
    └── 7100
        ├── 7100.conf
        ├── 7101.conf
        └── 7102.conf

2) docker-compose 관련 및 로그

home
└── ubuntu
    └── ${원하는 dir}
        ├── docker-compose.yml
        ├── predixy.log
        └── start.sh
  • log는 보통 /etc 하위에 작성하나, 편의를 위해 docker-compose 파일과 같은 곳에 위치하였다.

파일 내용

Configuration 파일

1) master node config

port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000

세개의 master 노드와 3개의 slave 노드로 구성하였다.
master 노드는 7000,7001,7002 포트를 가지므로 7000.conf, 7001.conf, 7002.conf를 작성한다.

2) slave node config

port 7100
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 3000
cluster-replica-validity-factor 10

slave 노드는 7100, 7101, 7102 포트로 구성하였다. 이 또한 포트별로 config 파일을 작성한다.

cluster-replica-validity-factor: master 노드와 통신한지 오래된 replica가 failover를 수행하지 않게 하기 위한 설정으로, (cluster-node-timeout * factor)만큼 master 노드와 통신이 없었던 레플리카 노드는 failover 대상에서 제외된다.

  • Fail over: Master가 죽었을 때, Replica가 Master가 되는 것.

3) predixy.conf

################################### GENERAL ####################################
## Predixy configuration file example

## Specify a name for this predixy service
## redis command INFO can get this
Name Predixy

## Default is 0.0.0.0:7617
Bind 0.0.0.0:7617

## Worker threads
WorkerThreads 4

MaxMemory 0

ClientTimeout 3000

Log /etc/logs/predixy.log

LogVerbSample 0
LogDebugSample 0
LogInfoSample 10000
LogNoticeSample 1
LogWarnSample 1
LogErrorSample 1


################################### AUTHORITY ##################################
Include auth.conf

################################### SERVERS ####################################
Include cluster.conf
# Include sentinel.conf
# Include try.conf

################################### LATENCY ####################################
## Latency monitor define, see latency.conf
Include latency.conf

클러스터를 구성해야 하므로 Include cluster.conf는 꼭 필요하다.

4) cluster.conf

## redis cluster server pool define

ClusterServerPool {
    MasterReadPriority 60
    StaticSlaveReadPriority 50
    DynamicSlaveReadPriority 50
    RefreshInterval 1
    ServerTimeout 1
    ServerFailureLimit 10
    ServerRetryTimeout 1
    KeepAlive 120
    Servers {
        + master1:7000
        + master2:7001
        + master3:7002
        + slave1:7100
        + slave2:7101
        + slave3:7102
    }
}

docker-compose로 구성한다면, Servers{}구성할 컨테이너 이름과 포트번호를 작성한다. 컨테이너 이름 대신 localhost를 작성하면 동작하지 않는다.

5) auth.conf & latency.conf

Authority {
    Auth {
        Mode write
    }
    Auth "원하는 비밀번호" {
        Mode admin
    }
}

predixy.conf에서 해당 파일들을 Include 했기 때문에, 없으면 오류가 발생한다.
latency.conf는 내용 없이 파일만 생성해 주었으며, 추후 공부를 통해 더 채워야 할 듯 하다.
predixy.log 파일도 생성만 해주었다.

Docker-compose

1) docker-compose.yml

version: "3"

services:
  predixy:
    image: haandol/predixy
    container_name: predixy
    hostname: predixy
    command: predixy etc/predixy/conf/predixy.conf
    volumes:
      - /opt/predixy/conf:/etc/predixy/conf
      - ./predixy.log:/etc/logs/predixy.log
    ports:
      - "7617:7617"
    networks:
      - redis-net

  master1:
    image: redis:latest
    container_name: master1
    volumes:
      - /opt/redis/7000/7000.conf:/usr/local/etc/redis_7000.conf
      - ./start.sh:/start.sh
    command: sh -c "redis-server /usr/local/etc/redis_7000.conf" 
    ports:
      - "7000:7000"
      - "17000:17000"
    networks:
      - redis-net

  master2:
    image: redis:latest
    container_name: master2
    volumes:
      - /opt/redis/7000/7001.conf:/usr/local/etc/redis_7001.conf
    command: sh -c "sleep 3 && redis-server /usr/local/etc/redis_7001.conf"
    ports:
      - "7001:7001"
      - "17001:17001"
    networks:
      - redis-net

  master3:
    image: redis:latest
    container_name: master3
    volumes:
      - /opt/redis/7000/7002.conf:/usr/local/etc/redis_7002.conf
    command: sh -c "sleep 3 && redis-server /usr/local/etc/redis_7002.conf"
    ports:
      - "7002:7002"
      - "17002:17002"
    networks:
      - redis-net

  slave1:
    image: redis:latest
    container_name: slave1
    volumes:
      - /opt/redis/7100/7100.conf:/usr/local/etc/redis_7100.conf
    command: sh -c "sleep 3 && redis-server /usr/local/etc/redis_7100.conf"
    ports:  
      - "7100:7100"
      - "17100:17100"
    networks:
      - redis-net

  slave2:
    image: redis:latest
    container_name: slave2
    volumes:
      - /opt/redis/7100/7101.conf:/usr/local/etc/redis_7101.conf
    command: sh -c "sleep 3 && redis-server /usr/local/etc/redis_7101.conf"
    ports:
      - "7101:7101"
      - "17101:17101"
    networks:
      - redis-net

  slave3:
    image: redis:latest
    container_name: slave3
    volumes:
      - /opt/redis/7100/7102.conf:/usr/local/etc/redis_7102.conf
    command: sh -c "sleep 3 && redis-server /usr/local/etc/redis_7102.conf"
    ports:
      - "7102:7102"
      - "17102:17102"
    networks:
      - redis-net

networks: 
  redis-net: 
    driver: bridge
  • Predixy7617번 포트를 열어놓았다.
  • Redis cluster의 노드들은 외부와의 연결에서는 기본 포트를, 클러스터 내부의 통신은 기본 포트+10000번으로 통신한다. 예시로써 master1를 보면 7000번과 17000번 포트 두개를 열어놓은 것을 확인할 수 있다.
  • 노드 간 네트워크를 묶어주어야 서로의 존재를 인식할 수 있다.
    redis-net으로 연결해주었다.
  • 이후에 master1에서 cluster를 구성할 것이므로 ./start.sh:/start.sh 볼륨 마운트를 추가한다.
  • sleep 3은 임의로 설정한 것으로 없어도 무방하다.

2) start.sh

#!/bin/bash

# Redis 노드가 시작되고 서비스가 완전히 준비되기를 기다린다.
sleep 1

redis-cli --cluster call master1:7000 flushall
redis-cli --cluster call master1:7000 cluster reset

# 마스터 설정하기
echo "yes" | redis-cli --cluster create master1:7000 master2:7001 master3:7002

# 슬레이브 등록하기
echo "yes" | redis-cli --cluster add-node slave1:7100 master1:7000 --cluster-slave
echo "yes" | redis-cli --cluster add-node slave2:7101 master2:7001 --cluster-slave
echo "yes" | redis-cli --cluster add-node slave3:7102 master3:7002 --cluster-slave

# 노드만 만들고 클러스터 구성 안 한 상태로 Master-slave 한번에 구성하기
#echo "yes" | redis-cli --cluster create master1:7000 master2:7001 master3:7002 slave1:7100 slave2:7101 slave3:7102 --cluster-replicas 1

# 클러스터 정보 확인
redis-cli --cluster check master1:7000

# redis-stat
#java -jar redis-stat-0.4.14.jar localhost:7000 localhost:7001 localhost:7002 localhost:7100 localhost:7101 localhost:7102 --server=8888

Slot이 Master에 할당된 후 confirm할 때, yes를 입력하지 않아 제대로 진행되지 않던 문제가 있었다.
.sh파일로 한번에 cluster를 구성할 때는 echo "yes" |를 꼭 추가하도록 하자.

실행 순서

#1. docker-compose 실행
docker-compose up

#2. start.sh 실행
docker exec -it master1 bash /start.sh

기타

레디스 노드 생성 시 ubuntu 22.x를 사용하는 경우 클럭 소스가 xen으로 되어있어, 주의가 필요하다는 경고가 발생할 수 있다.

이 경우 아래의 링크를 따라 해결한다.
https://repost.aws/ko/knowledge-center/manage-ec2-linux-clock-source

실행 결과

master-slave 구성 확인

docker exec -it master1 redis-cli --cluster check ${마스터 노드 중 하나}:${port}

각 Master에 slave(replica)가 예쁘게 하나씩 할당된 것을 확인할 수 있다.

Predixy

redis-cli -h ${IP} -p ${port} info

로컬에서 해당 클러스터에 접근이 가능한지 확인하였다.
(참고로 로컬에서 접근할 때, ec2 인바운드 규칙 추가하는 것 잊지 말기)
Predixy가 Proxy로 잘 설정되어있다.

데이터 입출력

어차피 테스트용 ec2 쓸때마다 껐다 키니까 IP 그냥 안지움. 돈이 없어요..

외부에서 Predixy 포트번호로 요청을 하면, 데이터가 잘 저장되고 다시 잘 불러와지는 모습이다.

0개의 댓글

관련 채용 정보