[REDIS] Redis Cluster 구현

D A S H B O A R D
D E V E L O P
S E C U R I T Y
 Sentinel
 Cluster
 결론
주요내용

 Redis Cluster Architecture

REDIS 클러스터는 항상 인스턴스 3개 단위로 생성한다.
아래 그림을 보면 master와 slave 전체를 이어두지 않고 각각의 master는 다른 인스턴스에 있는 slave에 붙어 있기 때문 (redis cluster는 기본이 3개 이상의 master 노드가 필요)
Redis UI (Redis Commander)는 선택사항
인스턴스 구조는 설계자가 적절히 변경하여도 무방 (But 반드시 redis master 노드는 3개 이상)

 Redis Instance 생성

수정 없이 각 EC2 인스턴스마다 실행

실행 명령어

chmod +x redis-install.sh ./redis-install.sh
Bash
복사

redis-install.sh

#!/bin/bash REDIS_NODE_TYPE=("master" "slave") sudo apt-get update sudo apt install -y curl make gcc # Redis-Stable 바잔 살치 curl "https://download.redis.io/redis-stable.tar.gz" -o /home/ubuntu/redis.tar.gz tar -xvf /home/ubuntu/redis.tar.gz -C /home/ubuntu/ cd redis-stable mkdir logs make sudo make install cp redis.conf redis-master.conf cp redis.conf redis-slave.conf # master 노드 및 slave 노드 설정 for TYPE in "${REDIS_NODE_TYPE[@]}" ; do sed -i "s/bind 127.0.0.1 -::1/bind 0.0.0.0 -::1/" redis-${TYPE}.conf sed -i "s/daemonize no/daemonize yes/" redis-${TYPE}.conf sed -i "s/pidfile \/var\/run\/redis_6379.pid/pidfile \/var\/run\/redis_${TYPE}.pid/" redis-${TYPE}.conf sed -i "s/logfile \"\"/logfile logs\/redis_${TYPE}.log/" redis-${TYPE}.conf sed -i "s/appendonly no/appendonly yes/" redis-${TYPE}.conf sed -i "s/appenddirname \"appendonlydir\"/appenddirname \"aof\"/" redis-${TYPE}.conf sed -i "s/appendfilename \"appendonly.aof\"/appendfilename \"aof_${TYPE}.aof\"/" redis-${TYPE}.conf sed -i "s/protected-mode yes/protected-mode no/" redis-${TYPE}.conf echo -e "cluster-enabled yes\n\ cluster-node-timeout 3000\n\ cluster-config-file nodes-${TYPE}.conf\n\ maxmemory 6gb\n\ maxmemory-policy volatile-ttl\n\ " >> redis-${TYPE}.conf done # slave 노드 설정 sed -i "s/port 6379/port 6380/" redis-slave.conf # Redis cluster Warning 해결 sudo bash -c 'echo tsc > /sys/devices/system/clocksource/clocksource0/current_clocksource' sudo sysctl vm.overcommit_memory=1 # Redis node 실행 sudo src/redis-server redis-master.conf
Shell
복사

REDIS PROXY 생성

위에서 생성한 각 인스턴스의 REDIS_IP 수정 후 사용
사용 이유
Cluster를 구성하는 Redis의 개수 또는 Cluster Client의 개수가 늘어날수록 Network Connection은 기하급수적으로 증가하는 단점 해결
redis cluster에서 key 가 분산돼서 저장될 때, 클라이언트가 키가 어디 있는지 찾을 필요 없이 Predixy 가 전부 해줌

실행 명령어

chmod +x redis-proxy-install.sh ./redis-proxy-install.sh
Bash
복사

redis-proxy-install.sh

#!/bin/bash # 수정 핊수! REDIS_IP=("10.0.45.XXX" "10.0.40.XXX" "10.0.37.XXX") REDIS_PORT=("6379" "6380") REDIS_CLUSTERS="" for IP in "${REDIS_IP[@]}" ; do for PORT in "${REDIS_PORT[@]}" ; do REDIS_CLUSTERS+="+ ${IP}:${PORT}\n\t" done done REDIS_CLUSTERS="${REDIS_CLUSTERS%\\n\\t}" git clone https://github.com/joyieldInc/predixy.git cd predixy mkdir logs make sudo cp src/predixy /usr/local/bin # Predexiy 설정 sed -i "s/Name PredixyExample/Name AEIT-REDIS-PROXY/" conf/predixy.conf sed -i "s/WorkerThreads 1/WorkerThreads 4/" conf/predixy.conf sed -i "s/Include try.conf/#Include try.conf/" conf/predixy.conf echo -e "\ Bind 0.0.0.0:7617\n\ MaxMemory 0\n\ Include cluster.conf\n\ LogRotate 1d\n\ Log ./logs/predixy.log " >> conf/predixy.conf # Cluster 설정 echo -e "\ ClusterServerPool {\n\ MasterReadPriority 60\n\ StaticSlaveReadPriority 50\n\ DynamicSlaveReadPriority 50\n\ RefreshInterval 1\n\ ServerTimeout 1\n\ ServerFailureLimit 10\n\ ServerRetryTimeout 1\n\ KeepAlive 120\n\ Servers {\n\ ${REDIS_CLUSTERS} }\n\ }\n\ " >> conf/cluster.conf # Auth 파일 수정 sed -i "s/\"#a complex password#\"/redis.123/" ./conf/auth.conf nohup predixy conf/predixy.conf & exit 0
Shell
복사

 Redis Clustering 설정

사용 위치는 Redis 인스턴스, Proxy 인스턴스 등 무관함 (어디서든 사용하면 됨)
위에서 생성한 각 인스턴스의 REDIS_IP 수정 후 사용

실행 명령어

chmod +x redis-cluster-config.sh ./redis-cluster-config.sh
Bash
복사

redis-cluster-config.sh

#!/bin/bash REDIS_IP=("10.0.45.89" "10.0.40.232" "10.0.37.150") REDIS_MASTER_PORT="6379" REDIS_SLAVE_PORT="6380" sudo apt update sudo apt install -y redis-tools g++ make CREATE_REDIS_MASTER_CLUSTER="" for IP in "${REDIS_IP[@]}" ; do CREATE_REDIS_MASTER_CLUSTER+="${IP}:${REDIS_MASTER_PORT} " done redis-cli --cluster create $CREATE_REDIS_MASTER_CLUSTER for (( i = 0 ; i < ${#REDIS_IP[@]} ; i++ )) ; do IP=${REDIS_IP[$i]} NEXT_INDEX=$((($i + 1) % ${#REDIS_IP[@]})) NEXT_IP=${REDIS_IP[$NEXT_INDEX]} # Add nodes and set them as slaves redis-cli --cluster add-node "$NEXT_IP:$REDIS_SLAVE_PORT" "$IP:$REDIS_MASTER_PORT" --cluster-slave done
Shell
복사

 Redis UI (Redis Commander)

REDIS_IP 만 변경 후 사용 접속 포트는 8081
#!/bin/bash REDIS_IP=("10.0.45.XXX" "10.0.40.XXX" "10.0.37.XXX") REDIS_PORT=("6379" "6380") REDIS_CLUSTERS="" for IP in "${REDIS_IP[@]}" ; do for PORT in "${REDIS_PORT[@]}" ; do REDIS_CLUSTERS+="AEIT:${IP}:${PORT}," done done REDIS_CLUSTERS="${REDIS_CLUSTERS%,}" # docker sudo apt update sudo apt-get install -y ca-certificates curl software-properties-common apt-transport-https gnupg lsb-release curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt-get install -y docker-ce docker-ce-cli containerd.io sudo groupadd docker sudo usermod -aG docker ${USER} sudo service docker restart docker -v # docker-compose sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose cat <<EOF > docker-compose.yml # docker-compose.yml version: "3.8" services: redis-commander: container_name: redis-commander hostname: redis-commander image: ghcr.io/joeferner/redis-commander:latest restart: always environment: - TZ=Asia/Seoul - REDIS_HOSTS=${REDIS_CLUSTERS} network_mode: host EOF sudo docker compose up -d
Shell
복사