Redis Sentinel

Redis 2015. 2. 25. 11:29

<정리>

- 2013.04.28 현재 Redis stable 버전은 2.6.12임.
- 자동 failover 기능은 충분히 사용할만 함.
- sentinel 재시작시 sentinel.conf를 사용해서 시작되는데, failover가 한번 이상 진행된 경우 진짜 master를 찾는데 문제가 있을 수 있다. Sentinel 자체로 일부 보완기능이 있으나, 하나 이상의 Sentinel을 반드시 운영해야하고, 운영자가 추가 보완책을 반드시 사용해야 함. (Resurrecting master절 참고) - 2.6.13버전 확인해 볼 것.



http://redis.io/topics/sentinel

Redis Sentinel Documentation

Redis Sentinel은 redis 관리를 돕도록 디자인된 시스템이다. 다음 3가지를 수행한다.
  • Monitoring: redis master, slave가 제대로 동작하는지 항상 검사한다.
  • Notification: sentinel은 뭔가 잘못된 Redis 인스턴스의 상태를 API를 통해 시스템 운영자나 다른 컴퓨터 프로그램에 알릴 수 있다. 
  • Automatic failover: 마스터가 예상대로 동작하지 않으면, sentinel은 slave 하나를 master로 승격시키는 failover process를 시작할 수 있다. 다른 남은 slave들은 새로운 master에 붙도록 reconfigured되고, Redis를 사용하는 어플리케이션들은 접속시(Sentinel에게 접속시?) 새로운 주소를 통지 받는다.

Redis Sentinel(이하 Sentinel)은 분산 시스템이다. 이것은 당신의 인프라에서 여러개의 sentinel 프로세스를 실행해야 하는 것을 의미하고, 이 프로세스들은 failover를 수행하기 위해 master가 다운되었다는 것을 알 수 있도록 서로 간에 agreement protocol을 사용할 것이다.
Sentinel은 redis-sentinel이라 불리는 stand-alone 실행파일로 제공된다. 그러나 실제로는 Redis 서버의 특별 실행 모드이다. redis-server에 --sentinel 옵션을 사용해서 sentinel을 띄울 수 있다.
WARNING: Sentinel은 현재 작업이 계속 진행중이다. 이 문서는 이미 구현된 것에 대한 사용 방법을 설명하며, Sentinel의 앞으로의 구현에 따라 변경될 수 있다.
Sentinel은 Redis 2.4.16 이상의 버전과 2.6.0-rc6 버전 이상과 호환된다.

Sentinel 얻기(Obtaining Sentinel)
현재 Sentinel은 github에 Redis unstable 브랜치의 일부분으로 있다. 컴파일하기 위해서는 unstable 브랜치를 clone해서 Redis를 컴파일 해야 한다. src 디렉토리에서 redis-sentinel 실행파일을 볼 수 있을 것이다.
또는 redis-server를 sentinel 모드로 실행할 수 있다. 이는 다음 절에서 설명한다.

Sentinel 실행(Running Sentinel)
redis-sentinel 실행파일을 사용한다면, 다음 커맨드 라인 명령으로 실행할 수 있다.
redis-sentinel /path/to/sentinel.conf

다른 방법으로는 redis-server를 sentinel모드로 실행할 수 있다.
redis-server /path/to/sentinel.conf --sentinel

Sentinel 설정(Configuring Sentinel)
Redis 소스 배포버전에는 sentinel.conf 파일이 포함돼 있다. 이 파일에는 sentinel을 설정할 수 있는 예제와 설명을 그 자체에 담고 있다. 전형적인 최소 설정은 다음과 같다.
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 900000
sentinel can-failover mymaster yes
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 900000
sentinel can-failover resque yes
sentinel parallel-syncs resque 5
첫째줄은 주소는 127.0.0.1이고 port는 6379인 Redis를 master로 모니터링 하라는 것이며, 2개의 sentinel로부터 master fail 감지를 받아야 한다는 것을 의미한다. (만약, 2개의 sentinel로부터 감지를 받지 못하면 자동 failover는 시작되지 않는다.)
다른 옵션들은 항상 이런 형태이다.
sentinel <option_name> <master_name> <option_value>
그리고, 이것들은 다음과 같은 목적으로 사용된다.
  • down-after-millisecons 는 sentinel이 master가 다운됐다고 판단하는 millisecond 시간값이다(다운됐다는 것은 PING 명령에 대한 응답이 없거나, 응답에 에러가 있는 경우이다). 이 시간이 지난 후 sentinel은 주관적 다운(subjectivel down(SDOWN))상태로 만들며, 이 상태는 자동 failover를 시작하기에는 불충분한 상태이다. 그러나 sentinel들이 충분히 SDOWN 상태로 인지하면(역주: 첫째줄 설정에서 2 만큼의 Sentinel들이 SDOWN을 인지하면), 해당 master는 객관적 다운(objectively down(ODOWN)) 상태가 된다. 이 sentinel수는 master에 대해 설정된 sentinel 합의 수에 의존한다.
  • can-failover 는 이 sentinel이 ODOWN이 감지되었을 때 failover를 할 수 있는지를 말한다. 필요하다면 모든 sentinel들에 대해서 failover를 수행하도록 구성할 수 있다. 또는, 몇 개의 sentinel만 합의할 수 있게 하고 failover 수행에 참여할 sentinel은 좀 더 둘 수도 있다.
  • parallel-syncs 은 failover된 후 동시에 새 master를 사용하도록 재설정될(역주: recongiured라고 돼 있으나, resync가 문맥상 맞는 듯) 수 있는 slave수를 지정한다. 이 수치가 낮으면, failover 절차를 완료하는데 더 많은 시간이 걸릴 것이다. 그러나 slave들이 old data를 제공하도록 설정돼 있다면, 모든 slave들이 새 master로부터 동시에 resync 받기를 원치 않을 수도 있다. 복제(replication/resync) 절차가 slave에게 non-blocking이라고 할지라도, master로부터 resync하는 동안 bulk data를 요청하는 것이 redis(master)를 멈추게 하는 순간이 있다. 한번에 한 slave가 not reachable이 되는지 이 옵션을 1로 설정해서 확인할 수 있다.
다른 옵션들은 이 문서의 나머지 부분에 있으며, redis 배포판의 예제 sentinel.conf 에 설명되어 있다.

SDOWN and ODOWN
이 문서에서 간단히 설명했지만, sentinel은 두가지 다른 개념의 down이 있다. 한가지는 주관적 다운(Subjectively Down(SDOWN))이다. 이 상태는 sentinel 인스턴트의 로컬 상태이다. 다른 한가지는 객관적 다운(Objectively Down(ODOWN))이다. 이 상태는 모니터링 되는 master의 quorum 파라미터로 설정된 수(정족수)만큼 SDOWN상태인 sentinel이 생긴 경우를 말하며, 다른 sentinel들은 is-master-down-byaddr 명령으로 피드백 받는다.
sentinel의 관점에서 SDOWN 상태는 is-master-down-after-milliseconds 파라미터로 설정된 시간 내에 유효한 PING 응답을 못받은 경우이다.
유효한 PING 응답은 다음과 같다.
  • +PONG 으로 응답을 받은 경우
  • -LOADING 에러로 응답을 받은 경우
  • -MASTERDOWN 에러로 응답을 받은 경우
이 이외의 다른 응답(또는 무응답)은 유효하지 않은 것으로 판단한다.

SDOWN은 설정된 전체 시간 동안 유효한 응답을 받지 못한 경우임을 기억하라. 예를 들면 interval이 30000 milliseconds(30초)이고, 매 29초에 ping 응답을 받는다면 이것은 정상으로 판단한다.
ODOWN상태는 master에게만 적용된다. 다른 redis 인스턴스(slave 또는 sentinel)인 경우 sentinel은 ODOWN을 고려하지 않는다. 그래서 ODOWN상태는 slave와 다른 sentinel 인스턴스에서는 발생하지 않는다.
Sentinel의 행동은 모든 sentinel이 따르는 규칙 셋으로 설명된다. 여러 sentinel로 구성된 분산 시스템으로써의 sentinel 전체 동작은 모든 싱글 sentinel 인스턴스가 따르는 이 규칙만으로 결정된다. 다음은 규칙의 첫번째 셋이다. 다른 규칙은 이 문서의 적절한 섹션에서 소개될 것이다.
Sentinel Rule #1: 모든 sentinel들은 모든 master, slave, sentinel에게 매 초 PING을 보낸다.
Sentinel Rule #2: 마지막 PING 응답을 down-after-milliseconds 초 이내에 못받았다면, 그 인스턴스는 SDOWN상태가 된다. 유효한 PING 응답은 +PONG, -LOADING, -MASTERDOWN 이다.
Sentinel Rule #3: 모든 sentinel은 SENTINEL is-master-down-by-addr <ip> <port> 명령의 응답을 할 수 있어야 한다. 주어진 주소가 master 인스턴스 중 하나라면 응답은 true이고, 그 master는 SDOWN 상태이다.
Sentinel Rule #4: 한 master가 SDOWN 상태인 경우(다른 sentinel들도 이 master를 모니터링하고 있음), 이 상태의 확인을 위해 매초 SENTINEL is-master-down-by-addr 명령이 사용된다. (If a master is in SDOWN condition, every other Sentinel also monitoring this master, is queried for confirmation of this state, every second, using the SENTINEL is-master-down-by-addr command.)
Sentinel Rule #5: 한 master가 SDOWN 상태이고 설정된 정족수(quorum) 이상의 sentinel이 인지하면(SENTINEL is-master-down-by-addr 명령에 5초내에 응답), 그 master는 ODOWN 상태가 된다.
Sentinel Rule #6: 모든 sentinel은 INFO 명령을 10초마다 한번에 모든 master와 slave들에게 보낸다. 만약 master가 ODOWN상태이면, 이 master의 slave들은 10초가 아니라 매초마다 INFO 요청을 받게된다.
Sentinel Rule #7: sentinel이 master로 알고 있는 redis로부터 받은 첫번째 INFO 응답이 실제로는 slave라고 돼 있으면, sentinel은 INFO 결과에 따라 실제 master를 모니터링 하도록 설정을 재구성할 것이다. 따라서 slave들에 대해서 sentinel을 재시작하는 것은 안전하다. (If the first INFO reply a Sentinel receives about a master shows that it is actually a slave, Sentinel will update the configuration to actually monitor the master reported by the INFO output instead. So it is safe to start Sentinel against slaves)

Sentinel과 Slave의 자동 발견(Sentinels and Slaves auto discovery)
Sentinel들은 다른 sentinel들과 서로 살아있는지 확인하고 서로 메시지를 주고 받기 위해 연결된 상태로 있지만, sentinel 인스턴스에 다른 sentinel의 주소를 설정할 필요는 없다. sentinel은 Redis master의 Pub/Sub 기능을 이용해 동일한 master를 모니터링하는 다른 sentinel을 발견한다.
이것은 __sentinel__:hello란 이름의 채널로 Hello Messages를 보내는 것으로 알 수 있다.
비슷하게 master에 붙은 slave들의 리스트를 설정할 필요도 없다. sentinel이 redis에 조회하여 자동으로 감지하기 때문이다.
Sentinel Rule #8: 모든 sentinel은 자신의 존재와 ip, port, runid, failover 가능 여부(sentinel.conf에 설정된 can-failover 설정에 따름)를 알리는 메시지를 모든 모니터링되는 master의 Pub/Sub 채널 __sentinel__:hello 로 매 5초마다 보낸다(publish). \
Sentinel Rule #9: 모든 sentinel은 unknown sentinel을 찾기 위해 모든 master의 Pub/Sub 채널 __sentinel__:hello 로 subscribe 한다. 새로운 sentinel이 감지되면, 해당 master의 sentinel 리스트에 추가한다.
Sentinel Rule #10: master에 새 sentinel 정보를 추가하기 전에 sentinel은 runid가 같거나, 같은 주소(ip:port쌍)의 sentinel이 이미 있는지 항상 검사한다. 만약 존재하면, 옛날것은 지워지고 새것으로 추가된다.

(역주: sentinel이 master redis의 __sentinel__:hello 채널로 붙는다(subcribe 한다).)
(sentinel port=22001)
redis 127.0.0.1:22001> info
# Server
redis_version:2.6.10
redis_git_sha1:00000000
redis_git_dirty:0
redis_mode:sentinel
os:Linux 2.6.18-308.11.1.el5xen x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.1.2
process_id:21513
run_id:8c1735bdd62a2cfdc9ffc20f742470995a913b2c
tcp_port:22001

(master port=21001)
redis 127.0.0.1:21001> subscribe __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "10.101.58.67:22001:b7c8f61ff3d1963c7bd14b018c3dd86364885406:1"
1) "message"
2) "__sentinel__:hello"
3) "10.101.56.87:22001:8c1735bdd62a2cfdc9ffc20f742470995a913b2c:1"

sentinel(22001)이 master(21001)을 감시하도록 한 후, master(21001)에 접속하여 'subscribe __sentinel__:hello' 를 치면, sentinel들이 보내오는 메시지를 볼 수 있다.



Sentinel API
디폴트로 sentinel은 TCP port 26379를 사용한다(6379는 일반 redis의 포트이다). Sentinel은 Redis 프로토콜을 사용해서 명령을 받는다. 따라서 Sentinel과 통신하기 위해 redis-cli 를 사용하거나 다른 호환되는 Redis 클라이언트를 사용할 수 있다.
Sentinel과 통신하는 두가지 방법이 있다: 첫번째는 모니터링되는 Redis 인스턴스의 상태를 체크하거나, 다른 Sentinel은 있는지 등을 sentinel에 직접 조회하는 방법이다. 다른 방법은 failover나 인스턴스의 상태 변경 같은 이벤트가 발생할 때마나 알림을 받을 수 있는 Pub/Sub를 이용하는 것이다.

Sentinel 명령들
명령에는 다음과 같은 것들이 있다:
  • PING: 단순하게 PONG을 반환한다.
  • SENTINEL masters: 모니터링하고 있는 master의 리스트와 그것들의 상태를 보여준다.
  • SENTINEL slaves <master name>: master의 slave들의 리스트와 그것들의 상태를 보여준다.
  • SENTINEL is-master-down-by-addr <ip> <port>: 두개의 multi bulk reply를 반환한다. 첫번째는 0 또는 1이다(ip:port가 master의 주소가 맞고 SDOWN상태이면 0, 그 외는 1). 두번째는 이 master의 주관적 리더(subjective leader)이다. 이것은 조회된 master에 대해 failover를 수행해야 하는 sentinel 인스턴스의 runid이다. ( The second element of the reply is the subjective leader for this master, that is, the runid of the Redis Sentinel instance that should perform the failover accordingly to the queried instance.)
  • SENTINEL get-master-addr-by-name <master name>: master name에 해당하는 ip와 port를 반환한다. 만약 failover가 진행중이거나 성공적으로 완료됐으면, promote 된 slave의 ip와 port가 반환된다.
  • SENTINEL reset <pattern>: 이 명령은 모든 매칭되는 이름의 master들을 reset한다. 패턴 인자는 glob-style 패턴이다. reset 프로세스는 master의 모든 이전 상태(failover in progress 상태를 포함하여)를 clear시키고, 해당 master와 통신하여 얻은 모든 slave와 sentinel 정보를 삭제한다.( The reset process clears any previous state in a master (including a failover in progress), and removes every slave and sentinel already discovered and associated with the master.) (역주: 어떤 상황이 되는지 테스트 해보자)

Pub/Sub Messages
클라이언트는 이벤트에 대한 알림을 받기 위해 Redis Pub/Sub 서버처럼 Sentinel에 SUBSCRIBE 또는 PSUBSCRIBE 해서 사용할 수 있다(하지만, PUBLISH는 사용할 수 없다).
채널 이름은 이벤트의 이름과 동일하다. 예를 들면 +sdown이란 이름의 채널은 인스턴스가 SDOWN 상태가 됐을 때 이와 관련된 모든 알림들을 받게된다.
모든 메시지들을 받기 위해서는 간단히 이렇게 하면 된다. PSUBSCRIBE *.
다음은 이 API를 통해서 받을 수 있는 채널들과 메시지 형식의 리스트이다. 첫번째 단어는 채널/이벤트 이름이고, 나머지는 데이터 포맷이다.
Note: instance details는 타겟 인스턴스를 식별할 수 있도록 다음 인자들을 받음을 의미한다.
<instance-type> <name> <ip> <port> @ <master-name> <master-ip> <master-port>
master를 식별하는 부분(@부터 끝까지)은 옵션이고, 해당 인스턴스가 마스터가 아닌 경우에 사용된다.
  • +reset-master <instance details> -- master가 reset 됐다.
  • +slave <instance details> -- 새로운 slave가 감지됐고, 추가(attached)됐다.
  • +failover-state-reconf-slaves <instance details> -- failover 상태가 reconf-slaves 상태로 변경됐다.
  • +failover-detected <instance details> -- 다른 Sentinel에 의해 failover 상태가 시작됐거나, 외부의 다른 entity(slave가 master로 변경됨)가 감지되었다.(역주: entity는 관리대상 또는 master/slave shard 한 셋트를 의미)
  • +slave-reconf-sent <instance details> -- 리더 Sentinel이 새 slave를 재설정(reconfigure)하기 위해 SLAVEOF 명령을 이 인스턴스에게 보냈다.
  • +slave-reconf-inprog <instance details> -- 재설정되고 있는 slave가 새 master의 slave가 되고 있음을 보여준다. 그러나 동기화 작업은 아직 완료되지 않았다.
  • +slave-reconf-done <instance details> -- slave가 새 master와 동기화 되었다.
  • -dup-sentinel <instance details> -- 파라미터로 받은 master를 감시하는 하나 또는 그 이상의 sentinel이 중복되어 제거되었다.(이 이벤트는 Sentinel 중 하나가 재시작 되었을 때 발생한다.)
  • +sentinel <instance details> -- 이 master를 위한 새로운 Sentinel이 감지되었고 추가되었다.
  • +sdown <instance details> -- 인스턴스가 SDOWN 상태가 되었다.
  • -sdown <instance details> -- 인스턴스는 이제 SDOWN 상태가 아니다.(역주: SDOWN 해제)
  • +odown <instance details> -- 인스턴스가 ODOWN 상태가 되었다.
  • -odown <instance details> -- 인스턴스는 이제 ODOWN 상태가 아니다.(역주: ODOWN 해제)
  • +failover-takedown <instance details> -- 설정된 failover-timeout 시간의 25%가 지났다. 그러나 이 Sentinel은 진행 상태는 볼 수 없고 새 리더가 된다(역주:이 이벤트가 뜨는 Sentinel이 리더란 의미인 듯).  남은 slave들이 새 master로부터 복제되도록 새 리더로써 행동을 시작한다. 
  • +failover-triggered <instance details> -- 리더 Sentinel로써 failover를 시작하고 있다. (역주: 리더 Sentinel에만 이 이벤트가 발생한다.)
  • +failover-state-wait-start <instance details> -- failover 상태가 "wait-start" 이다: failover를 시작하기 전에 { fixed seconds + random seconds } 동안 기다린다. 
  • +failover-state-select-slave <instance details> -- failover 상태가 "select-slave" 이다: promote할 적절한 slave를 찾고 있다.
  • +no-good-slave <instance details> -- promote할 적절한 slave가 없다. 이 상태에서 얼마 후 재시도 하겠지만, 아마도 failover는 정지될 것이다. 
  • +selected-slave <instance details> -- promote시킬 적절한 slave를 찾았다.
  • +failover-state-send-slaveof-noone <instance details> -- master로 promote될 slave를 재설정하고 있고, 변경되기를 기다리고 있다. (역주: master로 만들 slave에 "slaveof nonone" 명령을 보내 role이 master가 되도록 한다.)
  • +failover-end-for-timeout <instance details> -- failover가 timeout으로 종료되었다. 만약 리더 Sentinel에서 발생했으면, 아직 재설정되지 않은 나머지 slave들에게 최선의 방법으로 SLAVEOF를 보낸다(보냈다).
  • +failover-end <instance details> -- failover가 성공적으로 끝났다. 모든 slave들이 새 master에 붙었으며 복제되도록 설정되었음을 나타낸다. (역주: 복제는 master-slave간에 진행중이며, 별도 프로세스가 fork되어 진행된다.)
  • +switch-master <master name> <oldIp> <oldPort> <newIp> <newPort> -- 예전과 같은 이름으로 새 master의 모니터링을 시작한다. old master는 관리 테이블에서 완전히 삭제될 것이다.
  • +failover-abort-x-sdown <instance details> -- promote될 slave가 extended SDOWN 상태가 되어 failover는 중지(undoed/aborted)되었다.
  • -slave-reconf-undo <instance details> -- failover가 중지(aborted)되었고, 그래서 파라미터로 받은 인스턴스에게 원래 master를 바라보도록 SLAVEOF 명령을 보냈다.
  • +tilt -- tilt 모드로 들어갔다.
  • -tilt -- tilt 모드에서 나왔다.
(역주: 원문에 '+'가 빠진 이벤트는 보정해주었다. 또한, leader sentinel에서만 발생하는 이벤트는 italic체로 표기하였다(테스트 했음))


Sentinel failover
failover 과정은 다음 스탭들로 구성된다:
  • master가 ODOWN 상태가 되는 것을 인지.
  • 어떤 Sentinel이 failover를 시작시킬지 알게된다. 이 Sentinel을 리더(Leader)라고 부르며 다른 Sentinel들은 옵저버(Observer)가 된다.
  • 리더는 master로 promote시킬 slave를 선택한다.
  • promote될 slave는 SLAVEOF NO ONE 명령으로 master가 된다.
  • 옵저버들은 한 slave가 master로 바뀌는 것을 보게되고, failover가 시작되는 것을 알게 된다. Note: 이것은 옵저버들에 의해 모니터링 되는 master의 slave 중 하나가 master가 된다는 것을 failover 과정이 시작됨으로써 알게 된다. 
  • 원래 master에 붙어 있던 다른 모든 slave들은 새로운 master로부터 복제되도록 SLAVEOF 명령으로 재설정된다.
  • 모든 slave들이 재설정되면 리더는 failover 과정을 끝낸다. 관리 테이블에서 old master를 제거하고 new master를 추가한다. 이 때 원래 master의 이름을 사용한다. (역주: master name은 변경되지 않고 master 정보(주소)만 바뀜을 의미)
  • 모든 slave들이 재설정되면 옵저버들은 failover가 끝났음을 감지한다. 리더가 했던 것과 동일하게 관리 테이블에서 old master를 제거하고 new master를 감시하기 시작한다.
리더 선출은 ODOWN상태 도달과 동일한 메커니즘(SENTINEL is-master-down-by-addr 명령 사용)으로 동작한다. 질의 받은 Sentinel의 관점에서 다음 규칙에 의거하여 주관적 리더(Subjective Leader)라고 부르는 리더를 반환한다.
  • failover를 할 수 없도록 설정된 Sentinel들은 제외한다.(이 정보는 Hello 채널을 통해서 모든 Sentinel들에게 전파된다.)
  • SDOWN 상태인 Sentinel, 또는 SENTINEL_INFO_VALIDITY_TIME 밀리초(5초) 내에 ping 응답을 받지 못한 Sentinel들은 제외한다.
  • 남은 Sentinel들 중에서, 사전순서상(lexicographically) runid가 가장 낮은 것을 선택한다.(모든 Redis 인스턴스는 runid를 가지며, 모든 실행의 식별자로 사용된다.)
Sentinel이 failover를 시작할 수 있는 객관적 리더(Objective Leader)가 되기 위해서는 다음 조건들이 필요하다.
  • 자기가 주관적 리더(Subjective Leader)인지 확인한다.
  • 다른 Sentinel들로부터 리더가 맞는지에 대한 동의(acknowledges)를 받는다: 적어도 51%의 Sentinel들이 SENTINEL is-master-down-by-addr 의 응답으로 리더에 동의한다는 정보를 줄 수 있었고, failover를 하려고 하는 master에 설정된 정족수(quorum)에 만족해야 한다. (역주: sentinel.conf에 설정된 각 master(redis shard 또는 cluster)의 odown감지 정족수를 의미하며, SENTINEL is-master-down-by-addr는 sentinel간에 주고 받는 명령이다.)
한 Sentinel이 자신이 리더라고 생각할 때 failover는 시작된다. 그러나, 항상 { 5초 + random초 }의 delay를 둔다. 이것은 이 지연 시간 동안 다른 Sentinel 인스턴스가 slave를 master로 바꿔버리는지를 보고 있다가, failover가 진행되면 이를 감지해 옵저버로 동작할 수 있도록 보호 레이어를 하나 두는 것이다. 이는 redundancy 레이어이며 이론적으로는 절대 발생할 수 없다.
Sentinel Rule #11: Good Slave란 다음 조건을 만족해야 한다: 
* SDOWN도 아니고, ODOWN도 아니어야 한다.
* 정상적인 connection을 맺고 있어야 한다.(DISCONNECTED상태가 아니어야 함)
* 마지막 PING 응답이 5초 이내에 있었어야 한다.
* 마지막 INFO 응답이 5초 이내에 있었어야 한다.
* 마지막 INFO 응답에 master가 다운됐다고 보고 받아야 한다. 이 때, master 다운 시간이 Sentinel이 master가 SDOWN이 됐다고 알고 있는 시간 + down_after_milliseconds 파라미터의 10배의 시간을 넘지 않아야 한다. 예를 들면, Sentinel이 SDOWN을 감지하는 시간이 10초로 설정됐고, 50초 후에 master 다운이 감지됐다면, replication 링크가 50+(10*10)초 내에서 disconnect가 감지된 slave가 Good Slave로 인정된다.
* DEMOTE로 설정되지 않아야 한다.(see the section about resurrecting masters)
Sentinel Rule #12: master가 다운되면 Sentinel Rule #4에 설명된 대로 연결된 다른 모든 Sentinel에게 SENTINEL is-master-down-by-addr 를 보낸다. 이 명령의 질의를 받은 Sentinel은 자신의 관점에서 주관적 리더(Subjective Leader)의 runid를 응답으로 보낸다. 자신을 포함해서 N개의 Sentinel에 의해 주관적 리더라고 보고 받으면 해당 Sentinel은 자신이 객관적 리더(Objective Leader)가 된다고 믿게 된다:
* N 은 해당 master에 설정된 정족수(quorum)보다 크거나 같아야 한다.
* N은 master가 다운됐다고 인지한 Sentinel들로 구성된 투표자들의 과반(num_voters/2+1)보다 크거나 같아야 한다.
Sentinel Rule #13: 다음 조건들을 만족하면, 하나의 Sentinel이 리더로써 failover를 시작한다(이것은 실제로 Redis server로 master/slave를 재설정하는 명령을 보내는 것을 말한다):
* master가 ODOWN 상태이다.
* failover를 수행할 수 있도록 can-failover가 yes로 설정돼 있다.
* Sentinel의 관점에서 적어도 하나의 Good Slave가 있다.
* 자신이 객관적 리더(Objective Leader)라고 본다.
* 이 master에 대해 이미 진행되고 있는 failover가 없다.
Sentinel Rule #14: 다음 조건들이 동시에 만족되면, Sentinel은 옵저버로써 failover를 감지한다(이는 이 Sentinel이 failover를 따라가면서(관찰하면서) 적절한 이벤트를 로그파일과 Pub/Sub 인터페이스로 내보내지만, 인스턴스 재설정과정에는 관여하지 않는다):
* 이미 진행되고 있는 failover가 없다.
* 감시하고 있는 master의 slave 인스턴스 중 하나가 master로 변경된다. 그러나 slave 인스턴스가 master가 되고 동시에 runid가 이전과 다른 값으로 변경되었다면, failover가 시작되는 것으로 인식하지 못할 것이다. 이것은 그 인스턴스가 재시작으로 인해 master가 되었다는 것을 의미하고, slave로 선택할 수 없는 상태임을 의미하게 된다. (However the failover will NOT be sensed as started if the slave instance turns into a master and at the same time the runid has changed from the previous one. This means the instance turned into a master because of a restart, and is not a valid condition to consider it a slave election.)
(역주: Redis instance는 재시작하면 stand-alone master 롤로 뜬다. 반드시 밖에서 SLAVEOF로 재설정(reconfiguration)해줘야 한다.)
Sentinel Rule #15: 리더 Sentinel은 failover를 즉시 시작할 수는 없다. wait-start 상태라고 불리는 상태로 먼저 들어가야 한다. 5~15초 사이의 랜덤 시간동안 대기해야 한다. 이 시간 동안 Sentinel Rule #14는 계속 적용된다: 만약 slave promotion이 감지되면 리더는 옵저버로 동작한다.(if a valid slave promotion is detected the failover as leader is aborted and the failover as observer is detected.)

(역주: 원문에서 master라고 언급하는 곳은 { master redis - slave redis } 묶음(cluster)을 이야기한다. sentinel.conf에서 정의하는 "master name"의 그 master 이다. 더 정확한 의미로는 Redis Group 또는 Redis Cluster 쯤이 될 것이며, 실제 Redis master는 master instance라고 이야기하고 있다. master라고 해서 master redis instance만을 이야기하는 것이 아님을 기억하기 바란다. 글의 문맥을 보면 쉽게 구분 가능하다.)


End of failover
단일 Sentinel의 입장에서 다음을 만족하면 failover 과정이 끝났다고 판단한다:
  • promote된 slave가 SDOWN 상태가 아니다.
  • 한 slave가 새로운 master로 승격(promoted)되었다.
  • 다른 모든 slave가 새 master를 바라보도록 설정 되었다.
Note: SDOWN상태인 slave는 무시한다.

또한, 다음을 만족하면 failover 상태는 끝난 것으로 판단한다:
  • promote된 slave는 SDOWN 상태가 아니다.
  • 한 slave가 새로운 master로 승격(promoted)되었다.
  • 마지막 과정 이후로 적어도 failover-timeout 밀리초가 지났다.
failover-timeout 값은 sentinel.conf 파일에 각 cluster별로 다르게 설정할 수 있다.
다음을 기억하자. 리더가 timout 으로 failover를 완료처리할 때, 리더는 아직 설정되지 않은 slave들에게 가장 효과적인 방법으로 SLAVEOF 명령을 보낸다. slave들이 이 명령을 잘 받을 것이고 새 master에 잘 붙어서 복제될 것이라는 희망을 갖고서.

Sentinel Rule #16: 다음을 만족하면 리더 또는 옵저버는 failover가 끝났다고 판단한다:
* 하나의 slave가 master로 승격(promoted)되었고(Sentinel은 실제로 INFO 의 결과로 알 수 있다), 모든 slave들이 새 master를 복제하도록  재설정되었다(역시, Sentinel은 INFO의 결과를 통해 알게된다).
* 올바르게 승격된(promoted) slave가 있으나, 설정된 failover-timeout 시간이 지났고, 미처 재설정하지 못한 slave들이 남아 있다면, 리더는 가장 효과적인 방법으로 SLAVEOF 명령을 남은 slave들에게 보낸다. 이 상황은 승격된 slave가 SDOWN이 아닌 상태로 살아서 연결되어 있어야한다. 그렇지 않다면, failover는 완료된 것으로 판단되지 않는다.

Leader failing during failover(failover 도중 리더 장애 시)
slave를 master로 승격시키지 못한 상태에서 리더에 장애가 발생하면, 다른 Sentinel들의 관점에서 리더를 SDOWN 상태로 만드는 방법으로 failover 실패처리한다. 만약 정족수를 만족하는 다른 Sentinel이 남아 있으면, 자동으로 새 리더를 선출해서 failover를 계속 진행시킨다(이전 리더가 SDOWN상태가 될 것이기 때문에 남아 있는 Sentinel들 중 주관적 리더 하나가 진행할 것이다).

만약 failover가 이미 진행되었고 slave가 이미 승격되었다면, 몇몇 slave가 이미 재설정되었을 것이다. 이 때 새로운 리더로 선출된 옵저버는 failover-timeout 설정 시간의 25% 이후로 진행된게 전혀 없으면 failover를 계속 진행한다. (an observer that is the new objective leader will continue the failover in case no progresses are made for more than 25% of the time specified by the failover-timeout configuration option.)
여러 Sentinel들이 slave들을 재설정하기 위해 중복된 SLAVEOF 명령을 보내는 것으로부터 안전하며 이것이 어떤 경쟁상태도 만들지 않음을 기억하라. 그러나, 이와 동시에, 원래 리더가 동작하지 않는 경우에 모든 slave들이 재설정된다는 것을 보장하기를 원한다.

Sentinel Rule #17: failover 진행 중 옵저버인 Sentinel은 다음 조건을 만족하면, 남은 slave들의 재설정을 이어서 진행하기 위해 그 자신이 리더가 될 것이다:
* failover가 진행중이고, 이 Sentinel은 옵저버이다.
* 객관적 리더(Objective Leader)가 되는 것이 감지됨(이전 리더가 다른 Sentinel들에의해 더 이상 동작하지 않음(no longer reachable)이 감지됨).
* 관찰된 failover 과정에서 적어도 failover-timeout 으로 설정된 시간의 25%가 지났다.

Promoted slave failing during failover(failover 도중 승격대상 slave의 장애)
만약, 승격된 slave가 active SDOWN 상태가 되면, Sentinel은 failover가 완료됐는지 알 수 없을 것이다.
또한, extended SDOWN 상태(down-after-milliseconds시간의 10배 시간이 지난 SDOWN)이면, failover는 abort 된다(이것은 리더와 옵저버에서 일어난다). 그리고, 이전처럼 master를 다시 감시하기 시작한다. 그러면 이 상태에서 master가 여전히 장애 상태인 경우 다른 slave로 새로운 failover가 시작될 수 있다.

이 상황이 됐을 때 몇몇 slave들은 지금 장애 상태인 승격된 slave를 복제하도록 이미 설정되었을 것이 있을 수 있다. 그래서 리더 Sentinel은 이미 재설정 됐거나 진행 예정인 모든 slave들에게 원래 master를 바라보도록 재설정하는 SLAVEOF 명령을 보내서 failover를 abort 시킨다.

Sentinel Rule #18: Sentinel은 리더이거나 옵저버이거나 다음 조건을 만족하면 failover를 abort 시킬 것이다:
* failover가 진행 중이고 승격될 slave가 이미 선택되었다(또는, 옵저버인 경우 이미 master로 감지되었다).
* 승격되는 slave가 Extended SDOWN 상태(SDOWN 상태가 down-after-milliseconds 설정값의 10배 이상의 시간이 지속된 경우).
(역주: extended SDOWN = failover-abort-x-sdown 이벤트가 발생한 상태. SDOWN이 발생했다고 failover가 멈추지는 않고, extended SDOWN이 발생해야 멈춘다.)

Resurrecting master(master 부활)
failover 후에 어떤 시점에 old master가 되살아 날 것이다. Redis 2.6.13 Sentinel은 이 상황에서 old master를 new master의 slave로 자동 재설정 되도록 핸들링할 수 있다. 
이것은 다음 방식으로 진행된다:
  • 리더 Sentinel 또는 옵저버의 관점에서 failover가 시작된 이후에 old master는 new master의 slave 목록에 추가된다. 이 때 특수한 DEMOTE 플래그라는 것을 달고 추가된다(이 것은 SENTINEL SLAVES 명령의 결과로 확인할 수 있다).
  • old master가 되살아났고 다시 접속할 수 있을 때, 이 old master가 자신이 master라고 알려오면(INFO의 결과로 안다), Sentinel은 재설정 하기 위해 SLAVEOF 명령을 보낸다. 이 인스턴스가 slave라고 다시 알려오면 DEMOTE 플래그는 클리어시킨다. 
    (역주: Redis instance를 시작시키면 stand-alone master 롤로 뜨는데, 이 경우 Sentinel이 DEMOTE 플래그를 달고 관리 목록에 넣어뒀다가 다시 해당 인스턴스가 접속하면 재설정한다는 이야기인데, DEMOTE 플래그가 꺼진 상황에서 다시 재시작되면 또 다시 stand-alone master로 뜨게 된다. 이 때 Sentinel이 재시작하게 되면 대형 장애로 이어질 수 있다. sentinel.conf 에는 old master가 master로 설정돼 있기 때문이다. 이 경우 sentinel을 여러개 운영해서 sentinel이 재시작할 때 다른 sentinel의 상태를 conf파일로 덤프 받아 시작하는 방법이 안전하다, 또는 sentinel network에 처음 추가된 경우 sentinel.conf가 아니라 network에서 redis 인스턴스 정보를 받아오도록 보완되어야 할 것으로 보인다.)
old master를 slave로의 전환을 담당하는 Sentinel이 하나 이상인 것이 이 프로세스가 sentinel들의 장애에 영향 받지 않도록 하는 것이다. 동시에 DEMOTE 플래그가 있는 인스턴스는 승격대상 slave로 선택되지 않는다.
특별한 경우에 +slave 이벤트가 발생되는데 old master가 INFO를 통해 실제로 slave임을 보고할 때이다.
Sentinel Rule #19: failover가 시작됐을 때, old master는 new master의 slave로 DEMOTE 플래그를 달고 추가된다.
Sentinel Rule #20: slave가 자신이 master라고 알려오고 DEMOTE 플래그가 있으면 SLAVEOF를 통해 재설정된다. INFO의 결과를 받은 Sentinel이 잘못된 role을 감지하면 매번 이것을 수행한다.
Sentinel Rule #21: INFO의 결과로 slave라고 보고 받으면 DEMOTE 플래그는 즉시 clear된다.


Manual interactions
  • TODO: SENTINEL FAILOVER 로 failover 수동 시작.
  • TODO: SENTINEL PAUSE, RESUME으로 Sentinel 일시정지, 재시작 시키기.


The failback process
  • TODO: Sentinel은 자동 failback은 수행하지 않는다.
  • TODO: failback을 위한 단계를 문서화하기.

Client configuration update
Work in progress.


TILT mode
Redis Sentinel은 컴퓨터 시간에 매우 의존적이다: 예를 들면 한 인스턴스의 PING 응답이 재시간에 왔는지 검사하기 위해 현재시간과 검사하는 것.
그러나 컴퓨터 시간이 예기치 않게 변경되거나, 컴퓨터가 매우 바쁘거나, 어떤 이유로 프로세스가 멈추거나 하면 Sentinel은 예상치 못한 행동을 할 수도 있다.
TILE mode는 특수 "보호" 모드이다. Sentinel은 시스템의 안정성이 낮아질 수 있다는 뭔가 이상함이 감지될 때 이 모드로 들어갈 수 있다. Sentinel 타이머 인터럽트는 보통 초당 10회 호출된다. 따라서 타이머 인터럽트 사이에는 100 밀리초 +/-가 걸리는 것을 예상할 수 있다.
Sentinel이 하는 것은 타이머 인터럽트가 발생한 이전 시간을 등록하고, 이전 값과 현재 인터럽트 시간과 비교하는 것이다: 만약 이 값의 차가 음수이거나 비정상적으로 크면(2초 이상) TILT 모드로 들어간다.(이미 이 모드로 들어왔으면, TILE 모드 나가기가 연기된다.)
TILE모드 일때 Sentinel은 모든것들을 감시하게 될 것이며 다음과 같이 동작한다:
  • 모든 행동을 멈춘다.
  • SENTINEL ismaster-down-by-addr 요청에 대해 부적격(negatively) 응답을 보내 사용할 수 없는 상태임을 알린다.
만약 30초동안 모든 것들이 정상으로 판단되면, TILE mode에서 빠져나온다.


Handling of -BUSY state
(Warning: 아직 구현되지 않았음)
-BUSY 에러는 script가 설정된 시간보다 오래 동작할 경우에 반환된다. ...


Notification via user script
Work in progress.

Suggested setup
Work in progress.


Posted by 명혀니
,