redis sentinel 핸즈온

레디스 센티넬 클러스터 구축

Redis

Redis(REmote DIctionary Server)는 오픈 소스, 인메모리 기반키-값(Key-Value) 데이터 저장소입니다.
고속의 데이터 처리를 위해 RAM에 모든 데이터를 저장하며, 다양한 데이터 구조와 영속성 옵션을 지원합니다.

구성정보

테스트 환경으로 3개의 노드로 구성하였다.

vCpu: 1 CORE

vMemory: 1 GB

Install redis

$ sudo apt install redis && sudo apt install redis-sentinel

Redis Config

$ sudo vi /etc/redis/redis.conf
# master 설정
bind 0.0.0.0
protected-mode no
# slave 설정
bind 0.0.0.0
protected-mode no
replicaof 192.168.0.61 6379
# 192.168.0.61은 master node의 ip

설정하고 포트충들로 재기동안되면 강제 종료후 재기동하면된다.

root:~# ps aux | grep redis
# PID 확인후
root:~# kill -9 {PID}
root:~# systemctl restart redis

redis conf참고자료

$ sudo cat /etc/redis/redis.conf | grep -vE '^\s*#|^\s*$'
bind 0.0.0.0
protected-mode no
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised systemd
pidfile "/var/run/redis/redis-server.pid"
loglevel notice
logfile "/var/log/redis/redis-server.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dump.rdb"
rdb-del-sync-files no
dir "/var/lib/redis"
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
oom-score-adj no
oom-score-adj-values 0 200 800
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4kb
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes
user default on nopass ~* +@all
replicaof 192.168.0.61 6379

Redis Sentinel

Redis Sentinel은 센티넬 모드로 시작된 여러 Redis 인스턴스로 구성된 분산 시스템입니다. 이러한 인스턴스를  센티넬 이라고 합니다 .

센티넬 그룹은 기본 Redis 인스턴스와 그 복제본을 모니터링합니다. 센티넬이 기본 인스턴스가 실패했음을 감지하면 센티넬 프로세스는 최신 데이터가 있는 복제본을 찾고 해당 복제본을 새 기본으로 승격시킵니다. 이렇게 하면 데이터베이스와 통신하는 클라이언트가 새 기본에 다시 연결하고 평소처럼 계속 작동할 수 있으며, 사용자에게 최소한의 방해만 줍니다.

Redis Sentinel Config

$ sudo vi /etc/redis/sentinel.conf
port 26379
sentinel monitor mymaster 192.168.0.61 6379 2
sentinel deny-scripts-reconfig yes # SENTINEL  SET  명령 사용불가
sentinel down-after-milliseconds myprimary 5000
#protected-mode no
sentinel failover-timeout myprimary 60000
#sentinel failover-timeout mymaster 180000
#sentinel parallel-syncs mymaster 1
#sentinel auth-pass myprimary a_strong_password # 용도 확인 필요

확인

redis-cli info replication

테스트

import redis

# Redis 서버에 연결 (비밀번호 포함)
def connect_redis(host='localhost', port=6379, db=0, password=None):
    try:
        client = redis.Redis(host=host, port=port, db=db, password=password)
        # Ping 테스트로 연결 확인
        if client.ping():
            print("Successfully connected to Redis")
        return client
    except Exception as e:
        print(f"Could not connect to Redis: {e}")
        return None

# 데이터 저장 및 조회 테스트
def redis_test(client):
    try:
        # 키-값 설정
        client.set('mykey', 'Hello, Redis!')
        print("Set 'mykey' with value 'Hello, Redis!'")

        # 키-값 조회
        value = client.get('mykey')
        print(f"Retrieved 'mykey': {value.decode('utf-8')}")
        
        # 키 삭제
        client.delete('mykey')
        print("Deleted 'mykey'")
        
        # 키 조회 (삭제 후)
        value = client.get('mykey')
        if value is None:
            print("'mykey' not found (as expected after deletion)")
        else:
            print(f"Unexpectedly found 'mykey': {value.decode('utf-8')}")
    except Exception as e:
        print(f"Redis operation failed: {e}")

if __name__ == "__main__":
    # Redis에 연결 (비밀번호 포함)
    client = connect_redis(host='133.186.209.161', port=6379, db=0, password='injeinc123!')
    
    # 연결이 성공했다면 테스트 수행
    if client:
        redis_test(client)

참고자료

공식 학습 영상

https://university.redis.com/courses/ru101/?_gl=112p46rh_gcl_au*MjA4Mzc4MDQ0MC4xNzQzMDY2MzY4

튜토리얼

https://redis.io/learn/operate/redis-at-scale/high-availability/exercise-2

공식문서

https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel