# Redis 서버 데몬으로 실행, 보호모드 비활성화
# 보호모드가 활성화 되면 로컬외 외부 클라이언트가 shutdown 할수 없음.
redis-server --daemonize yes --protected-mode no
# 기본 redis.conf 복사
sudo /etc/redis.conf ./
chown ysoftman:ysoftman ./redis.conf
# 클러스터 구성을 위해서 최소 3개의 노드(redis-server 인스턴스)가 있어야 한다.
# 포트 설정 별로 디렉토리 생성
mkdir 7001 7002 7003
##########
# cluster 구성
# 클러스터 활성화
cluster-enabled yes
# 클러스터 노드 상태를 기록하는 파일로 노드가 자동 생성하고 사용자 수정하면 안된다.
cluster-config-file /home/ysoftman/7001/nodes-7001.conf
# 클러스터 노드 타임아웃 : 단위는 ms, 노드가 살아있는지/내려갔는지 체크
cluster-node-timeout 15000
# 워킹 디렉토리 설정
dir /home/ysoftman/7001
# 로그 파일 위치
logfile /home/ysoftman/7001/redis_7001.log
# pid 파일 위치
pidfile /home/ysoftman/7001/redis_7001.pid
# redis 는 다음 2가지 모드로 파일로 백업한다.
# append 모드 : 노드가 내려갔다 다시 시작할때 데이터를 추가하는 방식으로 설정
appendonly yes
# rdb 모드 : 파일명(경로가 아닌 파일명만 명시해야 한다. 경로는 dir 로 설정된 곳을 사용한다.)
dbfilename dump_7001.rdb
# append 모드 비활성화
appendonly no
# rdb 모드 비활성화
save ""
##########
# 위 설정으로 포트별로 디렉토리에 복사하고 포트별로 redis-server 시작
./bin/redis-server ./7001/redis-7001.conf
./bin/redis-server ./7002/redis-7002.conf
./bin/redis-server ./7003/redis-7003.conf
# --replicas n 으로 master 당 사용할 slave 개수를 지정한다.
# 그러면 현재 노드들에서 적절한 master - slave 를 구성한다.
# 디폴트는 --replicas 0 으로 모든 노드가 master 가 된다.
# echo yes 는 (type 'yes' to accept) 를 자동 입력하기 위해 사용
echo yes | ./redis-4.0.8/src/redis-trib.rb create --replicas 1 10.10.10.1:7001 10.10.10.1:7002 10.10.10.1:7003 10.10.10.2:7001 10.10.10.2:7002 10.10.10.2:7003
# 10.10.10.1:7001 노드에 10.10.10.1:7004 노드 master 로 추가
redis-trib.rb add-node 10.10.10.1:7004 10.10.10.1:7001
# slave 로 추가시
redis-trib.rb add-node --slave 10.10.10.1:7004 10.10.10.1:7001
# 10.10.10.1:7004 노드 삭제
redis-trib.rb del-node 10.10.10.1:7004 노드_ID
# ERR Slot 0 is already busy (Redis::CommandError) 에러 발생시
# cluster 를 다시 시작할 경우 기존 .rdb node*.conf .aof 파일은 삭제해야 한다.
# redis 시작시 설정에 따라 .rdb 또는 .aof 파일로 복구를 시도하면 에러가 발생할 수 있으니 필요없다면 삭제하도록 한다.
find . -name dump*.rdb -exec rm -rfv {} \;
find . -name nodes-*.conf -exec rm -rfv {} \;
find . -name *.aof -exec rm -rfv {} \;
##########
# redis 5.0 부터는 redis-cli 에서 redis-trib.rb 의 기능을 사용할 수 있다.
# Redis 동작 확인
redis-cli -h 10.10.10.1 -p 7001 ping
# 클러스터를 사용하는 경우 -c 옵션 사용
# moved x 는 호스트x에 데이터가 저정되어 있다는 의미고
# ask x 는 호스트x에 다시 물어(질의)야 한다는 의미다.
# -c 는 moved, ask 대상을 따라가서 (질의하게) 된다.
redis-cli -h 10.10.10.1 -p 7001 -c
# 키 scan
redis-cli -h 10.10.10.1-p 7001 -c --scan
# 특정패턴의 키 scan
redis-cli -h 10.10.10.1-p 7001 -c --scan --pattern "*ysoftman"
# 또는 다음처럼 접속해서 커맨드만 실행시켜 끝낼 수도 있다.
redis-cli -h 10.10.10.1 -p 7001 -c cluster info
# 노드 정보(myself 표시는 현재 접속한 노드), ip 로 정렬해서 보자.
redis-cli -h 10.10.10.1 -p 7001 -c cluster nodes | sort -k 2
# 노드 정보(myself 표시는 현재 접속한 노드)
# slave 에 master 노드 id 가 명시되어있어
# master-slave 연결 순서로 정렬해서 보자.
redis-cli -h 10.10.10.1 -p 7001 -c cluster nodes | sort -k 4
# 노드별 할당된 슬롯 정보
redis-cli -h 10.10.10.1 -p 7001 -c cluster slots
# ysoftman으로 시작하는 키만 노드에서 삭제하기
# 각 노드에 del 커맨드를 실행해야 한다.
# del 는 정규식이나 와일드카드를 사용할수 없고 exact 키 매칭이 되야 한다.
# 따라서 scan, pattern 으로 키이름을 파악해 xargs 로 넘겨야 한다.
# 삭제시 에러가발생하면 조회한 key를 파일로 저장해 하나씩 삭제하는 스크립트를 작성하자.
redis-cli -h 10.10.10.1 -p 7001 -c --scan --pattern "ysoftman*" | xargs redis-cli -h 10.10.10.1 -p 7001 -c del
redis-cli -h 10.10.10.1 -p 7002 -c --scan --pattern "ysoftman*" | xargs redis-cli -h 10.10.10.1 -p 7002 -c del
redis-cli -h 10.10.10.1 -p 7003 -c --scan --pattern "ysoftman*" | xargs redis-cli -h 10.10.10.1 -p 7003 -c del
##########
# 클러스터 정보 확인
redis>cluster info
# 클라이언트에서 set
redis>set nickname ysoftman
# 클라이언트에서 get
redis>get nickname
# Redis 서버 종료
# protected-mode 가 비활성화된 redis-server 만 가능
redis>shutdown
# 또는 각 서버 redis-cli 로 종료
redis-cli -h 10.10.10.1 -p 7001 shutdown
redis-cli -h 10.10.10.1 -p 7002 shutdown
redis-cli -h 10.10.10.1 -p 7003 shutdown
##########
# 장애 복구 과정(failover)
# 10.10.10.1:7001 master 노드가 죽었을때(kill -9 PID)
# 10.10.10.1:7002 slave 노드를 master 로 변환
redis-cli -h 10.10.10.1 -p 7002 -c cluster failover
# 10.10.10.1:7001 master 죽은 노드를 클러스터에서 제거
# 60초 안에 모든 노드들에서 forget 을 실행주지 않으면 정상 노드가
# 연결을 시도하기 때문에 죽은 노드가 handshake 상태가 된다.
# handshake 상태의 죽은 노드는 계속해서 id 가 변경된다.
# 다음과 같이 한번에 살아 있는 노드에서 죽은 노드를 제거해야 한다.
# 죽은 노드가 n개라면 n번만큰 살아 있는 노드에서 forget 해야 한다.
redis-cli -h 10.10.10.1 -p 7002 -c cluster forget 죽은_노드_ID
redis-cli -h 10.10.10.1 -p 7003 -c cluster forget 죽은_노드_ID
... 여러 노드에서 죽은 노드 만큼 수행
# 계속 변하는 handshake 노드도 다음의 쉘 스크립트로 한번에 정리할 수 있다.
https://github.com/antirez/redis/issues/2965#issuecomment-233779778# 죽은 노드를 정리하고 클러스터 상태를 보면
# 죽은 노의 슬롯들이 처리되지 않아 클러스터 상태가 fail 로 나온다.
redis-cli -h 10.10.10.1 -p 7001 -c cluster nodes
cluster_state:fail
# 죽은 노드가 관리하던 슬롯(nodes 정보로 봤을때 마지막 필드에 나온 숫자-숫자)
# 참고로 슬롯범위를 알지 못할때 실패 슬롯 개수를 파악하고
# 노드들을 slots 로 정렬하고 연속적이지 않은 부분이나, 끝이
# cluster_slots_fail 개수 만큼이 범위가 된다.
redis-cli -h 10.10.10.1 -p 7001 -c cluster info | grep cluster_slots_fail
redis-cli -h 10.10.10.1 -p 7001 -c cluster nodes | sort -k 9
# 슬롯들을 7001 에 추가(이관)해준다.
# 위에서 죽은 노드를 빼줘야지 슬롯을 이관할 수 있다.
# 참고로 {a..b} 범위는 쉘 명령으로 스크립트파일.sh 을 만들어 사용하는 경우
# 아래 명령줄 앞에 eval 을 사용해야 한다.
redis-cli -h 10.10.10.1 -p 7001 -c cluster addslots {10000..12000}
# 노드를 다시 추가할 경우
# redis 노드 시작
./bin/redis-server ./7003/redis-7003.conf
# 신규 노드가 기존 노드(ip로 명시해야 한다.)를 meet 하도록 한다.
redis-cli -h 10.10.10.1 -p 7003 -c cluster meet 10.10.10.1 7001
# addslot 대신 reshard 로 슬롯을 재분배 할 수 도 있다.
# redis 4.x 는 redis-trib.rb rehsard 사용
redis-cli -h 10.10.10.1 -p 7001 -c cluster reshard