
레디스란?
레디스(Redis)는 오픈 소스인 메모리 기반의 데이터 저장소이다. 주로 데이터베이스, 캐시 및 메시지 브로커로 사용된다.
Redis는 키-값(key-value) 형식의 데이터 저장소로서, 기본적으로 메모리에 데이터를 저장하고 필요에 따라 디스크에 데이터를 지속시킨다.
레디스의 특징
레디스의 주요 특징은 다음과 같다.
- 속도: 레디스는 메모리에 데이터를 저장하고 읽기 때문에 매우 빠른 응답 속도를 제공한다. 이는 데이터가 디스크에 저장되는 전통적인 디스크 기반 데이터베이스와는 대조적인 부분이다.
- 데이터 구조: 레디스는 다양한 데이터 구조를 지원하는데 문자열, 해시, 리스트, 세트, 정렬된 세트와 같은 데이터 형식을 지원하여 여러 가지 용도로 사용할 수 있다.
- 영속성: 레디스는 필요에 따라 디스크에 데이터를 저장할 수 있어 데이터의 영속성을 보장한다. 이는 데이터 손실을 방지하고 데이터베이스의 내구성을 향상시킨다.
- Pub/Sub 메시징: 레디스는 Pub/Sub(Publish/Subscribe) 메커니즘을 지원하여 메시지 브로커로도 사용할 수 있다. 이를 통해 메시지 기반 통신을 구현할 수 있다.
- 다양한 클라이언트 라이브러리: 레디스는 다양한 프로그래밍 언어를 지원하는 클라이언트 라이브러리를 제공하여 다양한 환경에서 사용할 수 있다.
정리하자면 레디스는 캐싱, 세션 저장, 대기열 관리, 실시간 리더보드, 채팅 애플리케이션 등 다양한 분야에서 사용되며, 빠른 속도와 다양한 데이터 구조를 제공하여 많은 개발자들에게 인기 있는 NoSQL의 한 종류로 사용되고 있다.
고가용성 확보
Redis를 포함하여 전통적인 RDBMS인 MySQL, MariaDB 등 여러 가지 데이터베이스들은 기본적으로 고가용성을 위한 여러가지 기능들을 지원한다.
그럼 레디스는 어떤 방식으로 고가용성을 지원할까? 바로 모드(Mode)를 이용한 고가용성을 지원하고 있다.
레디스에는 1개의 노드로 구성되는 단일(Standalone) 모드를 제외하고 센티널(Sentinel) 모드와 클러스터(Cluster) 모드가 존재한다.
먼저 센티널 모드는 Master와 Slave 서버로 구성되어 동작하며, Master 서버에 장애가 발생했을 시 이를 감지하는 Sentinel이라는 서버를 추가로 두어 Slave 서버를 Master 서버로 승격시켜 다운타임을 최소화하는 방식이다. Slave가 평상시에 Read 요청에 대해서는 처리를 해주지만 데이터를 Write 하는 역할은 Master 1대만 가능하기에 애플리케이션단에서 요청량이 많을 경우에 사용하기에는 적합하지 않다.
클러스터 모드는 여러 개의 노드(Master+Slave)를 동작시키고 이를 1개의 클러스터로 묶어서 사용한다. 그렇기에 실제 저장되는 데이터가 1개의 노드에 종속되는 것이 아닌 클러스터로 묶은 여러 개의 노드로 분산되어 저장된다. 때문에 애플리케이션 단에서 데이터에 대한 다수의 요청을 보내도 해당 내용이 여러 노드로 분산되어 문제없이 처리가 가능하다. 또한 별도의 Slave 노드를 두어 Master에 장애가 발생했을 때 Sentinel 모드처럼 Slave 서버를 Master로 자동 승격시켜 다운타임을 최소화할 수 있다.
센티널 구성
이번 글에서는 위에서 소개한 2가지 모드 중 센티널 모드를 직접 구성해 보고 동작을 확인해 본다.
설치환경
- Redhat 8.6
- Redis 7.0.5
- Server1(192.168.0.101, Redis-Master/Sentinel)
- Server2(192.168.0.102, Redis-Slave/Sentinel)
- Server3(192.168.0.103, Redis-Slave/Sentinel)
설치내용
- 작업 디렉토리 생성
$ mkdir -p /data/redis
$ cd /data/redis
- Redis 다운로드 및 압축해제, data/log용 디렉토리 생성
$ wget https://download.redis.io/releases/redis-7.0.5.tar.gz
$ tar -xvzf redis-7.0.5.tar.gz
$ mkdir /data/redis/redis-7.0.5/data
$ mkdir /data/redis/redis-7.0.5/log
- 필수 패키지 설치
Redis는 실행 파일을 패키지로 설치하거나 소스 파일을 다운받아 Make를 이용하여 직접 빌드하여 설치할 수 있다.
해당 글에서는 Make를 이용하여 직접 빌드하는 방법을 사용했다.
$ dnf install make gcc
- 레디스 빌드 및 설치
$ cd /data/redis/redis-7.0.5
$ make
$ make install
- 기존 conf 파일 백업
$ mv redis.conf redis.conf.bck
$ mv sentinel.conf sentinel.conf.bck
- 신규 conf 파일 작성
Redis-Master(192.168.0.101)
# Redis.conf
protected-mode no
port 6379
daemonize yes
pidfile "/data/redis/redis-7.0.5/data/redis.pid"
loglevel notice
logfile "/data/redis/redis-7.0.5/log/redis.log"
dir "/data/redis/redis-7.0.5/data"
requirepass "redis"
masterauth "redis"
# Sentinel.conf
protected-mode no
port 26379
daemonize yes
pidfile "/data/redis/redis-7.0.5/data/sentinel.pid"
loglevel notice
logfile "/data/redis/redis-7.0.5/log/sentinel.log"
dir "/tmp"
sentinel monitor mymaster 192.168.0.101 6379 2
sentinel auth-pass mymaster redis
Sentinel.conf
에서 Master 서버인 192.168.0.101:6379
의 상태를 모니터링하도록 설정해 준다.
또한 쿼럼(quorum)
은 2
로 설정하여 최소 2대 이상의 Sentinel이 Master 서버의 정상동작 여부를 판단하도록 설정한다.
Redis-Slave(192.168.0.102, 192.168.0.103)
# Redis.conf
protected-mode no
port 6379
daemonize yes
pidfile "/data/redis/redis-7.0.5/data/redis.pid"
loglevel notice
logfile "/data/redis/redis-7.0.5/log/redis.log"
dir "/data/redis/redis-7.0.5/data"
requirepass "redis"
masterauth "redis"
replicaof 192.168.0.101 6379
# Sentinel.conf
protected-mode no
port 26379
daemonize yes
pidfile "/data/redis/redis-7.0.5/data/sentinel.pid"
loglevel notice
logfile "/data/redis/redis-7.0.5/log/sentinel.log"
dir "/tmp"
sentinel monitor mymaster 192.168.0.101 6379 2
sentinel auth-pass mymaster redis
전체적인 내용은 동일하지만 레디스 서버가 Slave로 동작하도록 replicaof
옵션을 추가해 주고, Master 서버의 데이터를 복제할 수 있도록 설정해 준다.
- 각 서버에서 레디스 서버와 센티널을 실행
$ redis-server redis.conf
$ redis-sentinel sentinel.conf
실행된 레디스 서버에 접속하여 정보를 확인해 본다.
$ redis-cli
127.0.0.1:6379> auth redis
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.103,port=6379,state=online,offset=1280994,lag=0
slave1:ip=192.168.0.102,port=6379,state=online,offset=1280853,lag=0
master_failover_state:no-failover
master_replid:3ec9a68f00cdf08924ea4fd45004d3c5278fe164
master_replid2:5fb475ee90251ea85299b75df367477ca39edf93
master_repl_offset:1280994
second_repl_offset:1213754
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1213754
repl_backlog_histlen:67241
출력된 정보를 확인해 보면 role이 master
로 되어있어 Server1의 레디스 서버가 Master
역할을 수행하고 있음을 알 수 있다.
또한 connected_slaves
가 2
로 설정되어 있어 해당 Master서버에 2개의 Slave 서버가 접속되어 있는 것도 확인된다.
- Master <-> Slave 데이터 복제 동작 확인
Server1(Master)에서 hello world
라는 키값을 넣고 Server2, Server3(Slave)에서 동일한 데이터가 있는지 확인해 본다.
Redis-Master(192.168.0.101)
192.168.0.101:6379> set hello world
OK
192.168.0.101:6379> keys *
1) "hello"
Redis-Slave(192.168.0.102, 192.168.0.103)
192.168.0.102:6379> auth redis
OK
192.168.0.102:6379> keys *
1) "hello"
Server1(Master)에서 입력한 키값이 정상적으로 Server2(Slave)에서 복제되는 것을 확인할 수 있다.
- Server1에서 레디스 서버를 강제로 종료
$ ps -ef | grep redis
root 2229331 1 0 11:38 ? 00:00:02 redis-server *:6379
root 2238022 1 0 11:51 ? 00:00:01 redis-sentinel *:26379 [sentinel]
root 2244175 1244312 0 12:00 pts/0 00:00:00 grep --color=auto redis
$ kill 2229331
이후 sentinel 로그를 확인한다.(cat log/sentinel.log
)
2238022:X 28 Feb 2024 12:01:00.215 # +sdown master mymaster 192.168.0.101 6379
2238022:X 28 Feb 2024 12:01:00.275 * Sentinel new configuration saved on disk
2238022:X 28 Feb 2024 12:01:00.275 # +new-epoch 1
2238022:X 28 Feb 2024 12:01:00.279 * Sentinel new configuration saved on disk
2238022:X 28 Feb 2024 12:01:00.279 # +vote-for-leader 23fede91d70017f0d8744f373638d66bedb72a90 1
2238022:X 28 Feb 2024 12:01:00.279 # +odown master mymaster 192.168.0.101 6379 #quorum 3/2
2238022:X 28 Feb 2024 12:01:00.279 # Next failover delay: I will not start a failover before Wed Feb 28 12:07:00 2024
2238022:X 28 Feb 2024 12:01:01.037 # +config-update-from sentinel 23fede91d70017f0d8744f373638d66bedb72a90 192.168.0.102 26379 @ mymaster 192.168.0.101 6379
2238022:X 28 Feb 2024 12:01:01.037 # +switch-master mymaster 192.168.0.101 6379 192.168.0.103 6379
2238022:X 28 Feb 2024 12:01:01.038 * +slave slave 192.168.0.102:6379 192.168.0.102 6379 @ mymaster 192.168.0.103 6379
2238022:X 28 Feb 2024 12:01:01.038 * +slave slave 192.168.0.101:6379 192.168.0.101 6379 @ mymaster 192.168.0.103 6379
2238022:X 28 Feb 2024 12:01:01.041 * Sentinel new configuration saved on disk
2238022:X 28 Feb 2024 12:01:31.050 # +sdown slave 192.168.0.101:6379 192.168.0.101 6379 @ mymaster 192.168.0.103 6379
간략하게 로그를 설명하자면 아래와 같다.
+sdown master mymaster 192.168.0.101 6379
: 192.168.0.101:6379에 대한 접속이 끊어짐을 확인(101 sentinel의 개인 의견)
+odown master mymaster 192.168.0.101 6379 #quorum 3/2
: 192.168.0.101:6379에 대한 접속이 끊어짐을 확인(101, 102, 103 3개의 sentinel 중 2개 이상 sentinel의 단체 의견, master 서버가 내려갔다 고 판단하고 자동 복구 절차를 진행)
+switch-master mymaster 192.168.0.101 6379 192.168.0.103 6379
: master 서버를 192.168.0.101:6379에서 192.168.0.103:6379로 전환
+slave slave 192.168.0.102:6379 192.168.0.102 6379 @ mymaster 192.168.0.103 6379
: 192.168.0.102:6379가 192.168.0.103:6379에 대한 slave로 동작하도록 설정 변경
+slave slave 192.168.0.101:6379 192.168.0.101 6379 @ mymaster 192.168.0.103 6379
: 192.168.0.101:6379가 192.168.0.103:6379에 대한 slave로 동작하도록 설정 변경
위와 같은 과정을 통해 192.168.0.101:6379
에서 192.168.0.103:6379
로 master가 전환 됐다.
확실하게 확인하려면 redis-cli를 통해 확인해 볼 수도 있다.
192.168.0.103:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.0.102,port=6379,state=online,offset=1422442,lag=0
master_failover_state:no-failover
master_replid:c2681ba8a2adfb65f5a61004c85d47cd339504c7
master_replid2:3ec9a68f00cdf08924ea4fd45004d3c5278fe164
master_repl_offset:1422442
second_repl_offset:1328448
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1213754
repl_backlog_histlen:208689
이전에 확인했을 때 slave였던 role이 현재는 master로 되어있는 걸 확인할 수 있다.
- 내려간 Server1의 레디스 서버를 다시 기동
$ redis-server redis.conf
이후 redis-cli로 접속하여 info를 확인해 본다.
192.168.0.101:6379> auth redis
OK
192.168.0.101:6379> info replication
# Replication
role:slave
master_host:192.168.0.103
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:1469867
slave_repl_offset:1469867
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:c2681ba8a2adfb65f5a61004c85d47cd339504c7
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1469867
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1463176
repl_backlog_histlen:6692
정상적으로 구동되었지만 slave로 동작하며 이전처럼 master 역할을 다시 부여받지는 못하는 걸 확인할 수 있다.