Lettuce Redis Sentinel

레디스 개발자 교육 신청 레디스 정기점검/기술지원
Redis Technical Support
레디스 엔터프라이즈 서버
Redis Enterprise Server

Lettuce Redis Sentinel

이 문서는 레터스(Lettuce)를 이용해서 레디스 센티널(Redis Sentinel) 용 Java Spring 애플리케이션을 개발하는 방법을 설명합니다.
레디스 센티널에 연결(접속)하는 방법, 마스터가 다운되는 장애 발생 시 레터스 작동 방식, Pub/Sub과의 관계 등을 설명하고 관련 자바 소스 코드(source code)를 제공합니다.


기본 사용법

센티널 구성에서는 레디스 서버의 주소를 사용하지 않고 센티널 서버 주소로 연결(접속)합니다.
레터스(Lettuce)는 센티널에 접속해서 레디스 서버의 주소를 얻어와서 레디스 서버에 연결(접속)합니다. 그러므로 레디스 마스터가 다운되어 마스터 주소가 바뀌었어도 센티널이 최신 정보를 가지고 있기 때문에 새 마스터에 연결할 수 있습니다.
센티널이 3대이면 3대 주소 모두 등록합니다.

① .sentinel(node[0],Integer.parseInt(node[1]), redisProps.getSentinelMaster())
첫 번째 Sentinel 서버의 주소(ip와 port)와 MasterId 등 추가 정보로 RedisURI를 생성합니다.
② sentinelUri.getSentinels().add(RedisURI.create(node[0],Integer.parseInt(node[1])));
나머지 2대 센티널 서버의 주소를 등록합니다.
③ redisClient = RedisClient.create();
RedisClient 인스턴스를 생성합니다.
④ sentinelConnection = redisClient.connectSentinel();
센티널 서버에 연결합니다.
⑤ masterReplicaConnection = MasterReplica.connect(redisClient, StringCodec.UTF8, sentinelUri);
Redis 서버(Master/Replica)에 연결합니다.
⑥ masterReplicaConnection.setReadFrom(redisProps.getReadFrom());
조회 명령은 복제서버에서 실행하기 위해 ReadFrom을 설정합니다.
ReadFrom 각 값에 대한 자세한 설명은 여기를 보세요.
⑦ masterReplicaCommands = masterReplicaConnection.sync();
Sync 명령 실행용 API를 얻습니다.

Source code

장애복구(failover)와 Application 연결

  • 마스터가 다운되면 센티널은 복제서버 중 하나를 마스터로 승격시키는 명령을 실행하고, 기존 클라이언트(애플리케이션) 연결(normal | pubsub)을 끊습니다.
    MULTI
    SLAVEOF NO ONE
    CONFIG REWRITE
    CLIENT KILL TYPE normal
    CLIENT KILL TYPE pubsub
    EXEC
    • Sentinel 이 CLIENT KILL TYPE normal | pubsub 명령을 실행해서 client 연결을 끊는다.
      Source code: sentinel.c sentinelSendSlaveOf()
    • Redis-4.0 : CLIENT KILL TYPE normal -> pubsub은 하지 않는다.
    • Redis-5.0 : CLIENT KILL TYPE normal -> pubsub은 하지 않는다.
    • Redis-6.0 : CLIENT KILL TYPE normal | pubsub도 한다.
    • Master-Replica 연결은 끊지 않습니다.
  • 다른 복제서버에도 마스터가 변경되었음 알리고 기존 클라이언트(애플리케이션) 연결(normal | pubsub)을 끊습니다.
    MULTI
    SLAVEOF 192.168.56.102 6001
    CONFIG REWRITE
    CLIENT KILL TYPE normal
    CLIENT KILL TYPE pubsub
    EXEC
    애플리케이션은 재연결을 시도해서 다시 연결합니다.
    • 자동 재연결은 ClientOptions에서 설정하며, 기본이 true입니다.
    • 재연결은 1,2,4,8,16,30초, 이후 30초마다 반복해서 재연결 시도합니다.
    • clientOptions.autoReconnect(true);
  • 마스터가 다운되면 센티널은 복제서버 중 하나를 마스터로 승격시킵니다.
    센티널은 "Publish +switch-master mymaster ip port"로 애플리케이션에 마스터가 변경되었음을 알립니다.
    애플리케이션(lettuce)은 받은 주소로 새 마스터에 연결합니다.
    센티널로 부터 Publish를 받기 위해서 MasterReplica.connect() 시 3대 센티널에 아래 명령으로 SUBSCRIBE(등록)합니다.
    PSUBSCRIBE *
  • 레터스(lettcue)는 SentinelTopologyRefresh class (package io.lettuce.core.masterreplica)에서 아래 채널명으로 들어오는 메시지를 받아 적절한 처리를 합니다.
    "+slave", "+sdown", "-sdown", "fix-slave-config", "+convert-to-slave", "+role-change" "+elected-leader", "+reset-master" "+switch-master" "+sentinel"
  • 센티널은 다운된 레디스 서버 주소로 1초에 한번씩 PING을 보내서 다시 시작했는지 확인합니다.
    다운되었던 레디스 서버가 다시 시작하면 처음에는 마스터로 시작합니다.
    센티널은 이를 감지해서 복제서버로 만들고, 기존 클라이언트 연결을 끊습니다.
    다음 명령은 레디스 서버 시작하고 약 10초 후에 진행됩니다.
    MULTI
    SLAVEOF 192.168.56.102 6001
    CONFIG REWRITE
    CLIENT KILL TYPE normal
    CLIENT KILL TYPE pubsub
    EXEC
  • 다운되었던 마스터가 다시 시작하면 센티널은 publish -sdown 메시지를 보내서 애플리케이션에게 다시 시작했음을 알리고, 이후 publish +convert-to-slave 메시지를 보내서 복제로 변경되었음을 알립니다. 애플리케이션은 메시지를 받아 복제서버로 등록(처리)합니다.

센티널 구성과 Pub/Sub과의 관계

센티널에서 Pub/Sub을 사용하려면 "redisClient.connectPubSub();"를 사용하세요. Publish와 Subscribe 용 연결(connection)을 구분해서 사용하시기 바랍니다.
장애복구(failover) 시 레터스(lettuce)가 이전 마스터에 실행(등록)했던 subscribe 명령을 기억했다가 새 마스터에 자동으로 subscribe 명령을 실행합니다.
예) 이전 마스터에 ch01 ~ ch05까지 5번 SUBSCRIBE를 했다면 새 마스터에 이렇게 실행합니다.
    SUBSCRIBE ch05 ch03 ch04 ch01 ch02
그러므로 새 마스터에 다시 subscribe 명령을 실행할 필요 없습니다.
Pub/Sub에 대한 소개와 사용법은 여기를 보세요.

센티널 서버 password 설정

아래와 같이 사용할 수 있으나, 해당 메서드가 "@Deprecated" 되었습니다. 센티널 서버에는 가능한 password을 설정하지 말 것을 권장드립니다.

Connect String(URI)을 이용한 연결(접속) 방법

redis-sentinel URI syntax

아래와 같은 방법으로 Connect String(URI)을 만들어서 센티널에 연결한다.


Lettuce Spring Project

Spring Project 생성

Java Spring Project 생성 URL: start.spring.io

  • Project: Gradle-Groovy
  • Language: Java
  • Spring Boot: 3.1.8
  • Project Metadata
    • Group: com.redisgate
    • Artifact: SentinelLettuce -> Project 명칭, 이 이름으로 압축파일이 생긴다.
    • Name: Main -> Main Class Name
    • Description: Redis Sentinel Lettuce Application -> 설명
    • Package name: com.redisgate.redis -> Package Name
    • Packaging: Jar
    • Java: 17 -> Java 버전 선택
  • Dependencies에서 [ADD … CTRL + B] 버튼을 클릭해서 아래 3개를 추가합니다.
    • Spring Web
    • Lombok
    • Spring Data Redis(Access+Driver)
  • 마지막으로 [GENERATE CTRL + ⏎ ] 버튼 클릭해서 압축 파일(zip)을 다운받는다.
  • 스프링부트3.x 는 자바17 이상, 스프링부트 2.x는 자바11을 사용합니다.

이 프로젝트에 사용된 Lettuce, Spring, Redis 버전

  • Lettuce-6.2.7
  • Spring-Boot: 3.1.8, Spring: 6.0.16
  • Redis-7.2.3

Class/File 구성

  • Main Class: 메인 클래스
  • application.properties: 센티널/레디스 서버 연결 값들
  • RedisProps class: application.properties 파일을 읽어오는 클래스
  • RedisConn class: 센티널/레디스 서버에 연결하는 클래스
  • RedisController class: 센티널/레디스 명령 테스트 클래스
  • RedisPubSub class: Pub/Sub 테스트 클래스

Main Class

application.properties

RedisProps class

application.properties 파일을 읽어오는 클래스.

  • sentinelNodes는 센티널 노드 주소(ip:port)를 읽어옵니다. List를 사용했습니다.
  • sentinelMaster는 sentinel.conf에서 지정한 masterid를 읽어옵니다.
  • password는 char[]를 사용합니다. String을 사용하면 적용 시 getPassword().toCharArray()를 사용해야 합니다.
  • getReadFrom()은 readFrom 문자열을 ReadFrom 값으로 변경합니다.

RedisConn class

센티널/레디스 서버에 연결합니다.
ConnectTimeout은 ClientOptions을 사용해서 설정합니다.

다음은 3종류의 connect 메서드 실행 시 센티널/레디스 서버에 실행되는 명령입니다.

  • redisClient.connectSentinel() : Sentinel-1에 접속하고, 2,3에는 접속하지 않는다.
    Sentinel-1
        HELLO 3 SETNAME redisgate
  • redisClient.connect() : 센티널에 접속해서 masterid로 마스터 주소를 얻어서 마스터에 접속한다.
    Sentinel-1
        HELLO 3 SETNAME redisgate
        SENTINEL get-master-addr-by-name mymaster
        closed connection
    Master
        HELLO 3 AUTH default redisgate SETNAME redisgate
  • MasterReplica.connect() : 센티널에 접속해서 마스터와 복제 서버의 주소를 얻어오고 마스터와 복제 서버에 연결해본다. 센티널 서버에는 PSUBSCRIBE 명령을 실행한다.
    Sentinel-1
        HELLO 3 SETNAME redisgate
        SENTINEL master mymaster -> 마스터 서버의 주소를 얻는다.
        SENTINEL REPLICAS mymaster -> 복제 서버 주소를 얻는다.
        closed connection
        HELLO 3
        PSUBSCRIBE * -> 센티널로부터 publish msg를 받도록 등록한다.
    Sentinel-2
        HELLO 3
        PSUBSCRIBE * -> 센티널로부터 publish msg를 받도록 등록한다.
    Sentinel-3
        HELLO 3
        PSUBSCRIBE * -> 센티널로부터 publish msg를 받도록 등록한다.
    Master
        HELLO 3 AUTH default redisgate SETNAME redisgate
        CLIENT SETNAME lettuce#MasterReplicaTopologyRefresh
        PING NODES
        closed connection
    Replica-1
        HELLO 3 AUTH default redisgate SETNAME redisgate
        CLIENT SETNAME lettuce#MasterReplicaTopologyRefresh
        PING NODES
        closed connection
    Replica-2
        HELLO 3 AUTH default redisgate SETNAME redisgate
        CLIENT SETNAME lettuce#MasterReplicaTopologyRefresh
        PING NODES
        closed connection

RedisController class

센티널, 레디스 명령 테스트 클래스

  1. masterid로 주소(IP:Port) 조회: SENTINEL get-master-addr-by-name masterid
    http://localhost:8080/getMasterAddrByName/mymaster
  2. masterid로 마스터 정보 조회: SENTINEL MASTER masterid
    http://localhost:8080/master/mymaster
  3. masterid로 복제서버 정보 조회: SENTINEL REPLICAS masterid
    http://localhost:8080/replicas/mymaster
  4. ROLE: 마스터에서 실행
    http://localhost:8080/role
  5. SET 키-값 저장
    http://localhost:8080/set/key01
  6. GET 조회, 복제에서 읽는지 readFrom 설정 확인
    http://localhost:8080/get/key01
    GET 명령이 복제서버에 실행되는 것을 확인하기 위해서 아래와 같이 redis-cli를 실행 후 위 get 명령을 실행합니다.
    $ bin/redis-cli -p 6001 -a redisgate --stat
  7. PING: 마스터에서 실행
    http://localhost:8080/ping

RedisPubSub class

Publish/Subscribe 테스트 클래스

  1. PubSub Connection에 Listener를 등록
    http://localhost:8080/pubsubAddListener
  2. Subscribe 테스트
    http://localhost:8080/subscribe/ch01
  3. Publish 테스트
    http://localhost:8080/publish/ch01:Hello


<< Master/Replica Sentinel Cluster >>

Email 답글이 올라오면 이메일로 알려드리겠습니다.