본문 바로가기

Software Engineering/Redis

[Redis] redis replication, sentinel 테스트 구성 해보기

사진: Unsplash 의 Michel Sibold

 

Redis의 replication과 sentinel 구성을 테스트 해보기 위해, 샘플 클러스터를 구성해보았습니다. 실제 운영 환경에는 사용할 수 없지만, fail-over, bench-mark 테스트에 활용할 수 있도록 1개의 VM에서 redis 인스턴스 3개, sentinel 인스턴스 3개가 동작하도록 구성하였습니다.

실행 환경

  • Ubuntu 20.04
  • Redis 6.2.7
  • PC: N100, 8GB

클러스터 구성

여기서 클러스터는 다수의 master-replica로 구성된 redis cluster가 아닌, master-replica-replica로 구성된 하나의 세트를 의미합니다. 아래와 같이 클러스터를 구성하고, 필요한 파일을 먼저 정리해 봅니다.

script 준비 항목 정리

각 인스턴스를 실행하기 위한 script를 먼저 작성합니다. 실제 운영 환경에서 하나의 VM에 한 개의 인스턴스가 동작한다면 아래와 같이 포트 이름을 기준으로 설정 파일을 구분하지 않아도 좋습니다. 각 항목에 대한 파일을 미리 작성해 둡니다.

redis 서비스 실행

redis를 소스코드 기반으로 빌드 후 /usr/local/bin 경로에 실행 파일이 있다는 것을 전제로 실행 스크립트를 작성하였습니다. 다음은 작성 후 ChatGPT에게 리팩토링을 요청한 결과 입니다.

#!/bin/bash

# Configuration
REDIS_GROUP="redis"
REDIS_USER="redis"
DIRECTORIES=(
  "/etc/redis"
  "/var/log/redis"
  "/var/lib/redis"
)
CONFIG_FILES=(
  "./redis-6379.conf:/etc/redis/redis-6379.conf"
  "./redis-server-6379.service:/etc/systemd/system/redis-server-6379.service"
)
SERVICE_NAME="redis-server-6379"

# Utility function to log messages
log() {
    echo "[INFO] $1"
}

error_exit() {
    echo "[ERROR] $1"
    exit 1
}

# Ensure group exists
log "Checking if group $REDIS_GROUP exists..."
if ! getent group "$REDIS_GROUP" > /dev/null; then
    log "Group $REDIS_GROUP does not exist. Creating the group."
    groupadd "$REDIS_GROUP" || error_exit "Failed to create group $REDIS_GROUP."
    log "Group $REDIS_GROUP successfully created."
else
    log "Group $REDIS_GROUP already exists."
fi

# Ensure user exists
log "Checking if user $REDIS_USER exists..."
if ! id "$REDIS_USER" > /dev/null 2>&1; then
    log "User $REDIS_USER does not exist. Creating the user."
    useradd -r -g "$REDIS_GROUP" -M "$REDIS_USER" || error_exit "Failed to create user $REDIS_USER."
    log "User $REDIS_USER successfully created."
else
    log "User $REDIS_USER already exists."
fi

# Ensure directories exist and set ownership
for DIR in "${DIRECTORIES[@]}"; do
    log "Checking if directory $DIR exists..."
    if [ ! -d "$DIR" ]; then
        log "Directory $DIR does not exist. Creating the directory."
        mkdir -p "$DIR" || error_exit "Failed to create directory $DIR."
        log "Directory $DIR successfully created."
    else
        log "Directory $DIR already exists."
    fi

    log "Changing ownership of $DIR to $REDIS_USER..."
    chown -R "$REDIS_USER:$REDIS_GROUP" "$DIR" || error_exit "Failed to change ownership of $DIR to $REDIS_USER."
    log "Ownership of $DIR successfully changed to $REDIS_USER."

done

# Copy configuration files
for FILE_PAIR in "${CONFIG_FILES[@]}"; do
    IFS=":" read -r SRC DEST <<< "$FILE_PAIR"
    log "Checking if source file $SRC exists..."
    [ -f "$SRC" ] || error_exit "Source file $SRC does not exist."

    log "Copying $SRC to $DEST..."
    cp -f "$SRC" "$DEST" || error_exit "Failed to copy $SRC to $DEST."
    log "File successfully copied from $SRC to $DEST."

done

# Manage systemd service
log "Stopping service $SERVICE_NAME if running..."
systemctl stop "$SERVICE_NAME" || log "Service $SERVICE_NAME is not running or failed to stop."

log "Reloading systemd daemon..."
systemctl daemon-reload || error_exit "Failed to reload systemd daemon."

log "Enabling service $SERVICE_NAME..."
systemctl enable "$SERVICE_NAME" || error_exit "Failed to enable service $SERVICE_NAME."

log "Starting service $SERVICE_NAME..."
systemctl start "$SERVICE_NAME" || error_exit "Failed to start service $SERVICE_NAME."

log "Setup completed successfully!"

설치 결과

3개의 redis 인스턴스를 실행 후 아래와 같이 프로세스가 정상 동작하는 것을 확인 할 수 있습니다.

$ ps aux | grep redis
redis      62492  0.2  0.0  97356  5748 ?        Ssl  11:36   0:00 /usr/local/bin/redis-server 0.0.0.0:6379
redis      62683  0.3  0.0 183380  5736 ?        Ssl  11:39   0:00 /usr/local/bin/redis-server 0.0.0.0:6380
redis      62841  0.4  0.0 189524  5748 ?        Ssl  11:40   0:00 /usr/local/bin/redis-server 0.0.0.0:6381

$ redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=126,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=126,lag=1
master_failover_state:no-failover
master_replid:af64936f5e41517acecdeda2798f47fb3ed55048
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:126
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:16777216
repl_backlog_first_byte_offset:1
repl_backlog_histlen:126
127.0.0.1:6379>