Redis Sentinel
- Master는 여러 개의 복제 노드를 가질 수 있다. (1차 복제 서버)
- 복제 노드가 또 복제 노드를 가질 수 있음.(하지만 얘는 master 후보 아님)
- 1차 복제 서버 중 conf파일에 있는
replica-priority
값이 가장 작은 값을 가진 서버가 마스터에 선정됨 - 0으로 설정할 경우 master로 승격되지 않음
- 같은 값을 가지는 경우에 대해서는 다수결
master와 1차 복제서버가 거의 동시에 다운되었을때
master 다운시 2차복제서버는 Failover 대상이 아님
만약 master와 1차복제서버가 동시에 다운되는 경우 sentinel에서는 2차복제서버를 알지 못해 master로 승급 할 수 없다.
만약 master와 1차복제서버간에 다운타임의 충분한 차이가 있으면 sentinel에서는 1차복제서버를 마스터로 승격하면서 2차복제서버의 정보를 얻어올 수 있고, 1차복제서버가 다운되면 2차복제서버를 마스터로 승급시킬 수 있다. (https://mozi.tistory.com/378)
Redis Mater-Slave 이중화 구성 관리툴로 Redis instance와 별도 설치 및 구성 필요 Master 장애시 장애 확정 및 새로운 Master 선출 투표를 위해 과반수가 가능해야함 (최소 3개 이상 필요) 전체 최소 이중화 구성 instance 개수는 5개 (Sentinel : 5개, Redis Master : 1개, Redis Slave : 1 개)
별도의 툴 설치 없이 Redis Server Cluser Mode 설정을 켜서 바로 사용 가능 멀티 마스터 구성으로 데이터를 분산 저장하며 고가용성 보장을 위해 각 Master instance는 최소 1개 이상의 Slave instance가 존재해야 함 이론상 최소 1개 instance로 Cluster 구성이 가능하나 실사용을 위한 최소 구성은 Master : 3, Slave : 3이 적정함
- Sentinel로 구성하는 Redis HA는 1 Master, N Replicas, M Sentinel
- M은 3개이상의 홀수개가 이상적이며, 최소 1 Master, 1 Replica, 3 Sentinel이 권장된다.
하는일
- Montoring: redis master, replica 모니터링
- Automatic Failover
-
Master Redis의 상태를 감시. Master가 down되면 slave 중 어떤 redis서버를 master로 승격시킬지 투표 -> sentinel의 투표를 가장 많이 받은 redis server가 master로 승격됨 -> 이후 장애를 해결한 원래 master는 재시작시 slave로 시작됨
-
redis sentinel의 노드 개수는 항상 홀수로 설정(다수결원칙)
- Notification: redis instance들이 failover되었을 때 pub/sub으로 application(client)에게 알리거나 shell script로 관리자에게 email, sms로 알림가능
sentinel은
redis.conf
파일을 조작하여 slave를 master로 변경- 자기자신의
sentinel.conf
정보를 조작하여 감시하는 redis 서버 정보를 update - (down되었던 master정보는 메모리에 저장)
sentinel은 해당 master의 redis.conf
를 조작하여 현재 master의 slave로 설정
- 일시적으로 master가 2대가 됨. 만약 down되었다가 restart된 redis에 data가 저장되는 경우, slave로 전환되면서 master rdb파일을 바탕으로 data sync를 하기때문에 데이터 유실 가능성있음. (따라서 restart 된 master에는 접근 못하도록 막아야함)
version: '3.7'
services:
redis-master:
# image: bitnami/redis:5.0
image: bitnami/redis:6.2.4
container_name: redis-master
hostname: redis-master
environment:
- REDIS_REPLICATION_MODE=master
- REDIS_PASSWORD=brightics
volumes:
- redis-data1:/bitnami/redis/data
ports:
- 6379:6379
redis-replica:
image: bitnami/redis:6.2.4
container_name: redis-replica
hostname: redis-replica
environment:
- REDIS_REPLICATION_MODE=replica
- REDIS_PASSWORD=brightics
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PASSWORD=brightics
volumes:
- redis-data2:/bitnami/redis/data
redis-sentinel:
image: bitnami/redis-sentinel:5.0
hostname: sentinel
environment:
- REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=3000
- REDIS_PASSWORD=brightics
- REDIS_MASTER_HOST=redis-master
- REDIS_MASTER_PASSWORD=brightics
- REDIS_MASTER_PORT_NUMBER=6379
- REDIS_MASTER_SET=redis-master
- REDIS_SENTINEL_QUORUM=2
depends_on:
- redis-master
- redis-replica
volumes:
redis-data1:
driver: local
redis-data2:
driver: local
- bitnami-docker-redis-sentinel 환경변수 (https://github.com/bitnami/bitnami-docker-redis-sentinel#environment-variables)
- 한글가이드(http://redisgate.kr/redis/sentinel/sentinel_set.php)
- master가 죽었다고 판단하는 최소 sentinel process의 개수.
- failover 시 Master가 죽었다는 걸 판단하기 위해서는 다수결의 원칙이 적용 (홀수로 설정해야함)
-> sentinel process가 총 3개일 경우
2
로 설정 -> sentinel process가 총 5개일 경우3
으로 설정
failover시 아래와 같은 로그를 확인할 수 있다.
redis-sentinel_3 | 1:X 09 Nov 2021 11:59:57.146 # Next failover delay: I will not start a failover before Tue Nov 9 12:05:57 2021
- 장애조치가 일정 시간이 지나도 완료되지 않았을 때 취소(abort)하는 시간
- 주의할 것은 장애조치 시작부터 완료될때까지의 시간이 아니고, 각 단계마다의 시간을 체크한다. 1~6 각 단계 완료 직후에 failover_state_change_time을 세팅하고, 이 시각과 현재 시각을 비교해서 failover-timeout 보다 크면 장애조치를 취소한다.
- 장애조치를 취소(abort)한다는 것은 각 단계마다 설정한 플레그를 초기화하고 선정된 복제 정보를 삭제한다. 객관적 다운(odown) 플레그는 그대로 둔다. 정확한 의미에서 모두 롤백(rollback)하는 것은 아니지만 장애조치를 다시 시작할 수 있도록 초기화하는 것이다. 따라서 취소된 후 센티널 서버는 odown 단계에서 부터 다시 시작할 수 있다.
- 이 시간 동안 해당 서버(마스터, 복제, 센티널)와 통신이 안되면 주관적 다운(sdown) 상태로 변경한다.
$ docker-compose up --scale redis-sentinel=3 -d
Creating redis-replica ... done
Creating redis-master ... done
Creating redis-sentinel_redis-sentinel_1 ... done
Creating redis-sentinel_redis-sentinel_2 ... done
Creating redis-sentinel_redis-sentinel_3 ... done
$ docker-compose logs -f
- default connection TCP port는 26379
$ docker exec -it redis-sentinel_redis-sentinel_3 bash # sentinel container로 붙기
@sentinel:/$ redis-cli -p 26379 -a brightics
- sentinel info 확인
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=redis-master,status=ok,address=172.18.0.3:6379,slaves=1,sentinels=3
- Master 정보 확인
127.0.0.1:26379> sentinel master redis-master
1) "name"
2) "redis-master"
3) "ip"
4) "172.18.0.3"
5) "port"
6) "6379"
7) "runid"
8) "180a0685825d51f6f0258e99f0855654ee9563f5"
(...)
$ docker exec -it redis-master bash # redis container로 붙기
@redis-replica:/$ redis-cli
127.0.0.1:6379> auth brightics
OK
127.0.0.1:6379> set samplekey samplevalue
OK
127.0.0.1:6379> get samplekey
$ docker stop redis-master
redis-master exited with code 0
redis-replica | 1:S 09 Nov 2021 09:54:45.304 * Connecting to MASTER redis-master:6379
redis-sentinel_1 | 1:X 09 Nov 2021 09:54:47.946 # +sdown master redis-master 172.18.0.3 6379
redis-sentinel_3 | 1:X 09 Nov 2021 09:54:47.963 # +sdown master redis-master 172.18.0.3 6379
redis-sentinel_2 | 1:X 09 Nov 2021 09:54:47.965 # +sdown master redis-master 172.18.0.3 6379
redis-sentinel_3 | 1:X 09 Nov 2021 09:54:48.040 # +odown master redis-master 172.18.0.3 6379 #quorum 2/2
redis-sentinel_3 | 1:X 09 Nov 2021 09:54:48.040 # +new-epoch 1
redis-sentinel_3 | 1:X 09 Nov 2021 09:54:48.040 # +try-failover master redis-master 172.18.0.3 6379
redis-sentinel_2 | 1:X 09 Nov 2021 09:54:48.041 # +odown master redis-master 172.18.0.3 6379 #quorum 3/2
Master가 죽게되면 sentinel은 자신이 감시하고 있는 master가 죽었다고 sdown
시그널을 보낸다.
sdown
(Subjective Down): 단지 Master와 sentinel 자신이 연결되지 않음을 의미함
다수결의 원칙에 따라 quorum 값 만큼 sdown이 발생하면 sentinel은 odown
시그널을 보낸다.
odown
(Objective Down): 다수결에 의해 명시적으로 Master가 down되었음을 선포함 -> failover가 trigger됨 -> sentinel들은 다음 master를 선출하기 위해 남아있는 slave redis들에게 투표 진행 -> 더 많은 투표수를 받은 slave가 Master로 선출
# 2개의 sentinel에서 2개의 sdown이 감지되었으므로 odown 으로 판정한다는 뜻
+odown master redis-master 172.18.0.3 6379 #quorum 2/2
Failover 과정 (http://redisgate.kr/redis/sentinel/sentinel_masters.php)
- master:
172.18.0.3
- replica:
172.18.0.2
- pub/sub message 참고(https://redis.io/topics/sentinel#pubsub-messages)
- instance details
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
- wait_start: epoch를 증가시키고 장애 조치를 주관할 sentinel을 찾는다
+try-failover <instance details>
elected-leader
: 센티널 리더 선출
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:26.055 # +new-epoch 1
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:26.055 # +try-failover master redis-master 172.18.0.3 6379
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.059 # +vote-for-leader 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 1
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.059 # b3a6aa46758ee62eea71f3c738c9461dd8415241 voted for b3a6aa46758ee62eea71f3c738c9461dd8415241 1
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:26.059 # +vote-for-leader b3a6aa46758ee62eea71f3c738c9461dd8415241 1
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:26.059 # 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae voted for 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 1
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:26.066 # +new-epoch 1
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:26.070 # +vote-for-leader 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 1
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.070 # 3b007ba5996a3cd11c757cc48abacd5c6fc3616a voted for 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 1
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:26.070 # 3b007ba5996a3cd11c757cc48abacd5c6fc3616a voted for 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 1
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:26.099 # +odown master redis-master 172.18.0.3 6379 #quorum 3/2
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:26.099 # Next failover delay: I will not start a failover before Tue Nov 9 10:57:26 2021
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.111 # +elected-leader master redis-master 172.18.0.3 6379
- select_slave: 새로운 마스터가 될 복제를 선정한다.
failover-state-select-slave
selected-slave
: 슬레이브 선정
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.111 # +failover-state-select-slave master redis-master 172.18.0.3 6379
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.173 # +selected-slave slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
- send_slaveof_noone: 선정된 복제에게 SLAVEOF NO ONE 명령을 실행
failover-state-send-slaveof-noone
: 승격된 replica가 master로 reconfigure되기를 시도
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.173 * +failover-state-send-slaveof-noone slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
- wait_promotion : SLAVEOF NO ONE 명령이 완료되기를 기다리는 상태
- redis-replica | MASTER MODE enabled!!!!
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:26.307 * +failover-state-wait-promotion slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:27.664 # +sdown slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:27.673 # +sdown slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:27.674 # +sdown slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
redis-replica | 1:S 09 Nov 2021 10:51:33.718 # Unable to connect to MASTER: Resource temporarily unavailable
redis-replica | 1:M 09 Nov 2021 10:51:33.720 * Discarding previously cached master state.
redis-replica | 1:M 09 Nov 2021 10:51:33.720 # Setting secondary replication ID to cd6da3c89085d43ca9043a0a8716dd8c260ac681, valid up to offset: 30704. New replication ID is 06b4d7adc106735504b2949e5037edef3e0e602c
redis-replica | 1:M 09 Nov 2021 10:51:33.720 * MASTER MODE enabled (user request from 'id=13 addr=172.18.0.5:52707 laddr=172.18.0.2:6379 fd=10 name=sentinel-2d2a77f6-cmd age=0 idle=0 flags=x db=0 sub=0 psub=0 multi=3 qbuf=6889 qbuf-free=34065 argv-mem=4 obl=4701 oll=0 omem=0 tot-mem=61468 events=r cmd=exec user=default redir=-1')
redis-replica | 1:M 09 Nov 2021 10:51:33.724 # CONFIG REWRITE executed with success.
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:33.729 # +promoted-slave slave 172.18.0.2:6379 172.18.0.2 6379 @ redis-master 172.18.0.3 6379
- reconf_slaves : 복제들에게 새 마스터를 바라보도록 SLAVEOF New-IP New-Port 명령을 실행한 상태.
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:33.729 # +failover-state-reconf-slaves master redis-master 172.18.0.3 6379
- 원래는 replica개수만큼 아래와 같은 로그를 남긴다. 현재는 1 master - 1 replica라서 남지않음.
18:00:24.982 * +slave-reconf-sent slave 127.0.0.1:7123 127.0.0.1 7123 @ mymaster01 127.0.0.1 7122 18:00:25.969 * +slave-reconf-inprog slave 127.0.0.1:7123 127.0.0.1 7123 @ mymaster01 127.0.0.1 7122 18:00:25.969 * +slave-reconf-done slave 127.0.0.1:7123 127.0.0.1 7123 @ mymaster01 127.0.0.1 7122
- update_config : 센티널이 가지고 있는 정보를 새 마스터와 복제로 갱신하고 새 마스터를 모니터링하기 시작
failover-end
: failover가 성공적으로 끝남. 다른 replica들은 새로운 master로 바라보게 reconfigure됨.switch-master <master name> <oldip> <oldport> <newip> <newport>
master 승격완료~
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:33.732 # +config-update-from sentinel 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 172.18.0.5 26379 @ redis-master 172.18.0.3 6379
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:33.733 # +switch-master redis-master 172.18.0.3 6379 172.18.0.2 6379
redis-sentinel_2 | 1:X 09 Nov 2021 10:51:33.733 * +slave slave 172.18.0.3:6379 172.18.0.3 6379 @ redis-master 172.18.0.2 6379
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:33.733 # +config-update-from sentinel 2d2a77f6607c02f4c7f1c3a70db5c36b6d034aae 172.18.0.5 26379 @ redis-master 172.18.0.3 6379
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:33.733 # +switch-master redis-master 172.18.0.3 6379 172.18.0.2 6379
redis-sentinel_3 | 1:X 09 Nov 2021 10:51:33.733 * +slave slave 172.18.0.3:6379 172.18.0.3 6379 @ redis-master 172.18.0.2 6379
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:33.808 # +failover-end master redis-master 172.18.0.3 6379
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:33.808 # +switch-master redis-master 172.18.0.3 6379 172.18.0.2 6379
redis-sentinel_1 | 1:X 09 Nov 2021 10:51:33.808 * +slave slave 172.18.0.3:6379 172.18.0.3 6379 @ redis-master 172.18.0.2 6379
http://redisgate.kr/redis/sentinel/sentinel.php
- get-master-addr-by-name : 마스터,복제 모두 다운되었을 때, 센티널에 접속해서 마스터 서버 정보를 요청하면 이미 다운된 서버 정보를 리턴한다. 이 정보를 받은 클라이언트/어플리케이션은 이미 다운된 서버에 접속하려고 시도할 것이다. INFO sentinel 명령으로 마스터의 status를 확인해야 한다.
127.0.0.1:5000> sentinel get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6382"
127.0.0.1:5000> info sentinel
master0:name=mymaster,status=odown,address=127.0.0.1:6383,slaves=1,sentinels=1
- 복제 -> 마스터 승격 안되는 경우 복제가 먼저 다운되고, 마스터가 다운된 다음, 복제(6383)가 시작되면 이 서버는 마스터로 전환되지 않는다. 즉, 복제의 redis.conf 에 자신이 복제로 되어 있고, 센티널도 이 서버(6383)를 복제라고 인식하고 있을 경우 마스터로 전환하지 않는다. 해결책은 복제(6383)을 시작하기 전에 redis.conf 에서 slaveof 를 삭제하는 것이다
https://redis.io/topics/sentinel http://redisgate.kr/redis/sentinel/sentinel_info.php
http://redisgate.kr/redis/sentinel/sentinel_masters.php
https://jaehun2841.github.io/2018/12/02/2018-12-02-docker-7 https://devops.sdsdev.co.kr/confluence/pages/viewpage.action?pageId=94386973
더 찾아봐야하럿
-
영속성유지의 방법은 AOF, RDB방식이 존재하는데, 잦은 재기동이 필요한 환경(kubernetes나 docker)에는 AOF 방식이 유리하다.
-
Redis5 -> Redis6의 주요 기능은 보안관련인데, TLS통신관련과 ACL기능이 들어와있다.
-
https://redis.io/topics/sentinel#example-sentinel-deployments
redis.conf는 어디있지?? sentinel.conf는 sentinel container의 /bitnami/redis-sentinel/conf에 있음.