Redis 설치 및 Sentinel을 이용한 failover환경 구성하기

Posted by Geuni's Blog on December 25, 2023

설치환경 및 Redis소스버전

OS: Ubuntu 22.04.3 LTS

Redis: 7.2.3

아래와 같이 3개의 VM을 준비한다.

No. host name IP node roles
#1 redis-server1 172.25.254.131 redis (master), sentinel
#2 redis-server2 172.25.254.132 redis (slave), sentinel
#3 redis-server3 172.25.254.133 redis (slave), sentinel

빌드 패키지 설치

1
2
3
4
5
sudo apt update
sudo apt install build-essential
# systemd로 서비스관리를 원할 경우libsystemd-dev(Debian/Ubuntu) 혹은 systemd-devel(CentOS) 패키지 설치 필요
sudo apt install libsystemd-dev
# sudo yum -y install systemd-devel

redis 소스폴더 README참고:

To build with systemd support, you’ll need systemd development libraries (such as libsystemd-dev on Debian/Ubuntu or systemd-devel on CentOS) and run:

1
% make USE_SYSTEMD=yes

Redis 소스다운로드 및 컴파일 설치

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 소스 다운로드
curl -O https://download.redis.io/redis-stable.tar.gz
# or
wget https://download.redis.io/redis-stable.tar.gz

# 압축 해제
tar -xzvf redis-stable.tar.gz

cd redis-stable
# 소스 컴파일 및 설치, systemd 지원옵션은 필요여부에 따라 넣으면 됨
make USE_SYSTEMD=yes
sudo make PREFIX=/usr/local/redis-server install

# redis 및 sentinel의 config template 복사
sudo cp redis.conf sentinel.conf /usr/local/redis-server/

# log 디렉토리 생성
sudo mkdir /usr/local/redis-server/logs

Redis 사용자 계정 생성

사용자 계정 생성 및 권한설정

1
2
sudo adduser --system --group --no-create-home redis
sudo chown -R redis:redis /usr/local/redis-server

Replication구성 (Master / Slave)

서버별로 아래와 같이 redis.conf파일 편집

master서버 #1 (172.25.254.131)

1
sudo vim /usr/local/redis-server/redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# listening IP, 개발환경 같은 경우 편이성을 위하여 코멘트 처리 하거나 0.0.0.0으로 bind해도 되나
# 인터넷에 노출된 서버이거나 운영환경일 경우 보안을 고려하여 IP를 세팅해주자.
bind 172.25.254.131

# 워킹 디렉토리(working directory), rdb, aof파일이 저장되는 위치, Redis는 해당 경로에 대한 R/W권한이 필히 필요함.
dir /usr/local/redis-server/

# replication을 위하여 slave가 master에 접속시 사용되는 비번
# failover를 고려하여 master, slave 무관하게 masterauth, requirepass 같게 설정할것을 권장
masterauth mypass

# 비번설정, 다른 명령 실행시 "AUTH <PASSWORD>" 명령으로 인증후 실행가능.
requirepass mypass

# log파일 위치
logfile "/usr/local/redis-server/logs/redis.log"

# redis주기적으로 RDB(dump)파일을 떨구지만, 장애 발생시 미치 떨구지 못한 데이터는 유실되게 된다.
# 데이터 유실 최소화를 원한다면 AOF 기능을 사용할것을 권장한다.
appendonly yes

# appendonly가 yes로 설정했을때 적용되며, aof파일에 append(file sync)하는 주기를 뜻한다.
# no, always, everysec 3개의 옵션이 있으며, 
# no: 디스크에 쓰는 시점을 운영체제에 맡긴다
# always: 비권장 옵션이다. write명령이 실행될 때 마다 aof파일을 쓰므로 성능에 매우 영향을 준다.
# everysec: 데이터를 모아서 1초 마다 디스크에 쓴다. 성능과 데이터 보존측면에서 적절한 옵션이다. 판단이 어려울때 everysec권장
# If unsure, use "everysec".
appendfsync everysec

slave 서버 #2 (172.25.254.132)

1
sudo vim /usr/local/redis-server/redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# listening IP, 개발환경 같은 경우 편이성을 위하여 코멘트 처리 하거나 0.0.0.0으로 bind해도 되나
# 인터넷에 노출된 서버이거나 운영환경일 경우 보안을 고려하여 IP를 세팅해주자.
bind 172.25.254.132

# 워킹 디렉토리(working directory), rdb, aof파일이 저장되는 위치, Redis는 해당 경로에 대한 R/W권한히 필히 필요함.
dir /usr/local/redis-server/

# replication을 위하여 slave가 master에 접속시 사용되는 비번
# failover를 고려하여 master, slave 무관하게 masterauth, requirepass 같게 설정할것을 권장
masterauth mypass

# 비번설정, 다른 명령 실행시 "AUTH <PASSWORD>" 명령으로 인증후 실행가능.
requirepass mypass

# master의 ip/port ( master만 해당옵션을 코멘트 처리해주자 )
replicaof 172.25.254.131 6379

# log파일 위치
logfile "/usr/local/redis-server/logs/redis.log"

# redis주기적으로 RDB(dump)파일을 떨구지만, 장애 발생시 미치 떨구지 못한 데이터는 유실되게 된다.
# 데이터 유실 최소화를 원한다면 AOF 기능을 사용할것을 권장한다.
appendonly yes

# appendonly가 yes로 설정했을때 적용되며, aof파일에 append(file sync)하는 주기를 뜻한다.
# no, always, everysec 3개의 옵션이 있으며, 
# no: 디스크에 쓰는 시점을 운영체제에 맡긴다
# always: 비권장 옵션이다. write명령이 실행될 때 마다 aof파일을 쓰므로 성능에 매우 영향을 준다.
# everysec: 데이터를 모아서 1초 마다 디스크에 쓴다. 성능과 데이터 보존측면에서 적절한 옵션이다. 판단이 어려울때 everysec권장
# If unsure, use "everysec".
appendfsync everysec

slave 서버 #3 (172.25.254.133)

1
sudo vim /usr/local/redis-server/redis.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# listening IP, 개발환경 같은 경우 편이성을 위하여 코멘트 처리 하거나 0.0.0.0으로 bind해도 되나
# 인터넷에 노출된 서버이거나 운영환경일 경우 보안을 고려하여 IP를 세팅해주자.
bind 172.25.254.133

# 워킹 디렉토리(working directory), rdb, aof파일이 저장되는 위치, Redis는 해당 경로에 대한 R/W권한히 필히 필요함.
dir /usr/local/redis-server/

# master의 ip/port ( master만 해당옵션을 코멘트 처리해주자 )
replicaof 172.25.254.131 6379

# replication을 위하여 slave가 master에 접속시 사용되는 비번
# failover를 고려하여 master, slave 무관하게 masterauth, requirepass 같게 설정할것을 권장
masterauth mypass

# 비번설정, 다른 명령 실행시 "AUTH <PASSWORD>" 명령으로 인증후 실행가능.
requirepass mypass

# log파일 위치
logfile "/usr/local/redis-server/logs/redis.log"

# redis주기적으로 RDB(dump)파일을 떨구지만, 장애 발생시 미치 떨구지 못한 데이터는 유실되게 된다.
# 데이터 유실 최소화를 원한다면 AOF 기능을 사용할것을 권장한다.
appendonly yes

# appendonly가 yes로 설정했을때 적용되며, aof파일에 append(file sync)하는 주기를 뜻한다.
# no, always, everysec 3개의 옵션이 있으며, 
# no: 디스크에 쓰는 시점을 운영체제에 맡긴다
# always: 비권장 옵션이다. write명령이 실행될 때 마다 aof파일을 쓰므로 성능에 매우 영향을 준다.
# everysec: 데이터를 모아서 1초 마다 디스크에 쓴다. 성능과 데이터 보존측면에서 적절한 옵션이다. 판단이 어려울때 everysec권장
# If unsure, use "everysec".
appendfsync everysec

systemd Unit파일 생성

1
sudo vim /etc/systemd/system/redis-server.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=Redis data structure server
Documentation=https://redis.io/documentation
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/redis-server/bin/redis-server /usr/local/redis-server/redis.conf --supervised systemd --daemonize no
LimitNOFILE=10032
NoNewPrivileges=yes
Type=notify
TimeoutStartSec=infinity
TimeoutStopSec=infinity
UMask=0077
User=redis
Group=redis

[Install]
WantedBy=multi-user.target

서버별로 redis instance 각각 구동

1
systemctl start redis-server

구동후 서비스 상태 확인:

1
systemctl status redis-server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
● redis-server.service - Redis data structure server
     Loaded: loaded (/etc/systemd/system/redis-server.service; disabled; vendor preset: enabled)
     Active: active (running) since Fri 2023-12-22 05:19:08 UTC; 6s ago
       Docs: https://redis.io/documentation
   Main PID: 48121 (redis-server)
     Status: "Ready to accept connections"
      Tasks: 6 (limit: 2178)
     Memory: 2.3M
        CPU: 19ms
     CGroup: /system.slice/redis-server.service
             └─48121 "/usr/local/redis-server/bin/redis-server *:6379" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" >

Dec 22 05:19:08 kafka-server1 systemd[1]: Starting Redis data structure server...
Dec 22 05:19:08 kafka-server1 systemd[1]: Started Redis data structure server.

Replication확인

master replication상태 확인

1
2
cd /usr/local/redis-server/bin
./redis-cli -h 172.25.254.131
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
172.25.254.131:6379> auth mypass
OK
172.25.254.131:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.25.254.133,port=6379,state=online,offset=95561,lag=0
slave1:ip=172.25.254.132,port=6379,state=online,offset=95561,lag=0
master_failover_state:no-failover
master_replid:e396c5f17b331fc17d89f9c03e27e8a4548214f9
master_replid2:b950d0774916c8901184640d4652864788e2a51e
master_repl_offset:95561
second_repl_offset:94277	
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:94277
repl_backlog_histlen:1285

slave replication상태 확인

1
2
# 두대의 slave상태 각각 확인
./redis-cli -h 172.25.254.132
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
172.25.254.132:6379> auth mypass
OK
172.25.254.132:6379> info replication
# Replication
role:slave
master_host:172.25.254.131
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_read_repl_offset:95603
slave_repl_offset:95603
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e396c5f17b331fc17d89f9c03e27e8a4548214f9
master_replid2:b950d0774916c8901184640d4652864788e2a51e
master_repl_offset:95603
second_repl_offset:94277
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:93577
repl_backlog_histlen:2027

서비스 활성화:

1
systemctl enable redis-server

Sentinel 구성

서버별로 sentinel.conf편집

1
sudo vim /usr/local/redis-server/sentinel.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# pid파일 위치
pidfile "/usr/local/redis-server/logs/redis-sentinel.pid"

# log파일 위치
logfile "/usr/local/redis-server/logs/sentinel.log"

# monitoring대상 master정보 및 O_DOWN판정(failover)에 필요한 최저 투표수
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 172.25.254.131 6379 2

# master비번
sentinel auth-pass mymaster mypass

# master S_DOWN판정 시간
sentinel down-after-milliseconds mymaster 6000

sentinel failover-timeout mymaster 180000

systemd Unit파일 생성

1
sudo vim /etc/systemd/system/redis-sentinel.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=Redis sentinel
Documentation=https://redis.io/docs/management/sentinel/
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/local/redis-server/bin/redis-sentinel /usr/local/redis-server/sentinel.conf --supervised systemd --daemonize no
LimitNOFILE=10032
NoNewPrivileges=yes
Type=notify
TimeoutStartSec=infinity
TimeoutStopSec=infinity
UMask=0077
User=redis
Group=redis

[Install]
WantedBy=multi-user.target

서버별로 sentinel instance 각각 구동

1
systemctl start redis-sentinel

구동후 서비스 상태 확인:

1
systemctl status redis-sentinel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
● redis-sentinel.service - Redis sentinel
     Loaded: loaded (/etc/systemd/system/redis-sentinel.service; disabled; vendor preset: enabled)
     Active: active (running) since Fri 2023-12-22 07:47:47 UTC; 16min ago
       Docs: https://redis.io/docs/management/sentinel/
   Main PID: 85260 (redis-sentinel)
     Status: "Ready to accept connections"
      Tasks: 5 (limit: 2178)
     Memory: 2.1M
        CPU: 3.497s
     CGroup: /system.slice/redis-sentinel.service
             └─85260 "/usr/local/redis-server/bin/redis-sentinel *:26379 [sentinel]" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ">

Dec 22 07:47:47 kafka-server3 systemd[1]: Starting Redis sentinel...
Dec 22 07:47:47 kafka-server3 systemd[1]: Started Redis sentinel.

Sentinel 상태정보 확인

1
2
cd /usr/local/redis-server/bin
./redis-cli -p 26379 info sentinel
1
2
3
4
5
6
7
8
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_tilt_since_seconds:-1
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=172.25.254.131:6379,slaves=2,sentinels=3

서비스 활성화:

1
systemctl enable redis-sentinel

Failover 테스트

이 단계에서 failover 테스트를 해보자. master process를 kill 혹은 sleep 처리하여 구성정보가 정상적으로 변경되였는지 확인하면 된다.

1
2
3
4
5
6
7
./bin/redis-cli
127.0.0.1:6379> auth mypass
OK
# debug명령은 redis.conf의 enable-debug-command옵션을 "local" 혹은 "yes"로 변경후 사용가능하다
127.0.0.1:6379> debug sleep 10
OK
(10.01s)

log확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
122668:X 25 Dec 2023 01:30:57.033 # +sdown master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:57.088 # +odown master mymaster 172.25.254.131 6379 #quorum 2/2
122668:X 25 Dec 2023 01:30:57.088 # +new-epoch 11
122668:X 25 Dec 2023 01:30:57.088 # +try-failover master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:57.093 * Sentinel new configuration saved on disk
122668:X 25 Dec 2023 01:30:57.093 # +vote-for-leader 8a8d49f48649f665877ae3821c411d2511f1e084 11
122668:X 25 Dec 2023 01:30:57.100 * 79aafc906bc392865fbb1c6f1c9d4f38d8996332 voted for 8a8d49f48649f665877ae3821c411d2511f1e084 11
122668:X 25 Dec 2023 01:30:57.100 * d5e27cf5588cc89870ba1454872b6eedf8f4cae7 voted for 8a8d49f48649f665877ae3821c411d2511f1e084 11
122668:X 25 Dec 2023 01:30:57.155 # +elected-leader master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:57.155 # +failover-state-select-slave master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:57.215 # +selected-slave slave 172.25.254.133:6379 172.25.254.133 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:57.215 * +failover-state-send-slaveof-noone slave 172.25.254.133:6379 172.25.254.133 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:57.272 * +failover-state-wait-promotion slave 172.25.254.133:6379 172.25.254.133 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:58.159 * Sentinel new configuration saved on disk
122668:X 25 Dec 2023 01:30:58.159 # +promoted-slave slave 172.25.254.133:6379 172.25.254.133 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:58.159 # +failover-state-reconf-slaves master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:58.258 * +slave-reconf-sent slave 172.25.254.132:6379 172.25.254.132 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:59.177 * +slave-reconf-inprog slave 172.25.254.132:6379 172.25.254.132 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:59.177 * +slave-reconf-done slave 172.25.254.132:6379 172.25.254.132 6379 @ mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:59.231 # -odown master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:59.231 # +failover-end master mymaster 172.25.254.131 6379
122668:X 25 Dec 2023 01:30:59.231 # +switch-master mymaster 172.25.254.131 6379 172.25.254.133 6379
122668:X 25 Dec 2023 01:30:59.231 * +slave slave 172.25.254.132:6379 172.25.254.132 6379 @ mymaster 172.25.254.133 6379
122668:X 25 Dec 2023 01:30:59.231 * +slave slave 172.25.254.131:6379 172.25.254.131 6379 @ mymaster 172.25.254.133 6379
122668:X 25 Dec 2023 01:30:59.233 * Sentinel new configuration saved on disk
122668:X 25 Dec 2023 01:31:10.692 * +convert-to-slave slave 172.25.254.131:6379 172.25.254.131 6379 @ mymaster 172.25.254.133 6379

대체적으로 아래와 같은 과정을 거쳐 failover가 완료된다.

  1. master의 다운상태 감지후 +sdown(주관적 다운)이벤트가 발생
  2. +sdown(주관적 다운) 상태에 대한 기타 sentine의 동의를 거친후 +odown(객관적 다운)상태로 승격
  3. sentinel leader 선출
  4. failover 수행

신규 master정보 조회

1
2
3
./redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
1) "172.25.254.133"
2) "6379"

master ip가 172.25.254.131에서 172.25.254.133으로 변한것을 확인할수 있다.