단기간 동안 살아있는 인증번호라던가 특정 시간 동안 유효해야 하는 토큰 같은 경우 일반적으로 Redis를 이용하여 보관한다. 만약 Redis에 장애가 생기기라도 한다면 운영되고 있는 서비스에 큰 영향을 주게 된다. 특히 인증, 인허와 같은 개념이 필요한 서비스는 더욱 그렇다. Redis는 Disk 기반이 아닌 인메모리 데이터 베이스이기 때문에 영속성이 보장되지 않는다. 즉, 장애가 발생하면 데이터가 모두 유실될 수도 있다는 말이다. 이를 해결하기 위해서 복제본을 만들어두고 원본이 되는 Redis에 장애가 생겼을 때 복제본의 데이터를 가져다 쓸 수 있다.
Redis에서 제공하는 High Availibility 기술로는 Master-Slave 형태의 Replication을 제공한다. 소프트웨어 아키텍쳐 패턴중 하나인 Master-Slave 패턴은 Master는 동등한 구조를 지닌 Slave들과 연결되어 있고 작업을 분산하거나 데이터를 복제해두는 것이 주요한 목적이다.
데이터 베이스뿐만 아니라 어플리케이션 단에서도 사용되는 패턴이기도 하고 이때는 분산된 일을 맡아 계산하는 작업을 하므로 Slave라고 명명해도 무관하다. 하지만 데이터 베이스에서 사용되는 경우 복제본의 역할로 사용되므로 Replica라고 부른다. 위 그림처럼 Master는 다수의 Replica를 가질 수도 있고, 하나의 Replica를 가지고 이 Replica와 연결된 Replica가 존재하는 선형 구조의 설계도 종종 사용한다.
Master 노드의 데이터는 실시간으로 Replica 노드에 복사된다.
데이터의 복사본을 저장하는 역할말고도 쓰기는 Master에 읽기는 Replica에서 진행한다. 애플리케이션은 대개 읽기 연산이 쓰기 연산보다 훨씬 비중이 많기 때문에 Replica들에서 읽어오는 연산을 한다. 동시접속자나 처리 속도를 높이기 위함이다. 주역할이 분리되어 있는 것이지 Master에서도 읽기 연산을 할 수 있다. Master는 Read-Write, Replica는 Read-Only 모드로 세팅되어 있기 때문이다.
Master와 Replica들의 노드가 연결되면 비동기 방식으로 데이터가 복제된다. 애플리케이션에서 Master에 데이터를 쓰면 Master는 ACK를 보내고, Replica 노드에 데이터를 전달하여 복사해둔다. Master에 데이터가 변경이 일어나면 변경 내용을 backlog에 기록하고 Replica는 Master에 접속하여 backlog 기록을 바탕으로 복제를 한다. 만약 Master 노드가 중간에 장애가 발생하여 죽는다면 Replica에는 데이터가 존재하지 않을 수도 있다. 하지만 매우 빠른 시간 내에 복제되므로 가능성은 낮은 편이다.
만약 Master가 죽을 경우 Replica는 계속해서 연결을 시도하며 살아날 때까지 대기를 한다. Master가 살아났다면 Replication을 수행하며 데이터의 싱크를 맞춘다. 살아나기 어려운 상태라면 개발자는 Replica중 하나를 Master로 승격하고 Master를 Replica로 변경하는 작업을 수행해야 한다. 사람이 일일이 이러한 장애를 대응하기에는 문제점이 많다. 이때 감시자의 역할을 하는 Sentinel을 이용하여 문제를 해결할 수 있다.
Sentinel의 역할은 크게 4가지이다.
- Monitoring
Master, Replica들이 정상적으로 작동되고 있는지 감시한다. - Notification
감시하고 있는 Redis에 이상이 생기면 API를 통해 시스템 관리자 또는 다른 컴퓨터 프로그램에게 알린다. - Automatic failover
Master가 정상적으로 작동하지 않으면 자동으로 failover 프로세스를 진행한다.
* failover : Replica를 Master로 승격시키고 다른 Replica들은 새 Master를 사용하도록 재구성되며, Redis 서버를 사용하는 응용프로그램은 연결할 때 사용할 새 주소에 대해 알리는 과정. - Configuration provider
클라이언트는 주어진 서비스를 담당하는 현재 Redis 마스터의 주소를 요청하기 위해 Sentinel에 연결한다. failover가 발생하면 새 주소를 보고한다.
따라서 Sentinel을 이용하여 Master의 Downtime을 최소화하여 High Availibility를 높일 수 있다. Sentinel도 Replica처럼 여러개가 존재한다. 보통 홀수개로 구성하는데 Sentinel들이 투표를 통해 새로운 Master를 정할 때 항상 과반수 이상의 득표를 만들기 위함이다. 어느 Replica가 Master가 될지는 replica-priority에 의해 결정된다. 값이 적을수록 우선 순위가 높게 부여된다. failover process가 진행되는 와중에 어떤 Replica는 Master로 승격하고 싶지 않다고 하면 replica-priority를 0으로 설정하면 된다. 단, Replica는 2개 이상이어야 한다.
quorum은 의사를 진행시키거나 의결을 하는 데 필요한 최소한도의 인원수를 뜻한다. 위 그림에서는 Sentinel이 3개이므로 quorum을 2로 설정하면 2개이상의 Sentinel이 Master에 이상이 있다고 판단해야 failover가 실행된다. 이제 애플리케이션이 직접 Master Redis와 연결되는 것이 아니라 Sentinel한테 가서 Master의 IP, PORT를 물어본다. failover가 실행된 후 Sentinel은 바뀐 Master의 IP, PORT를 알려준다.
쿠버네티스로 Sentinel-Reids 환경을 구축해보자. 쿠버네티스 패키지 매니저인 Helm을 사용하여 설정할 것이다. 여기서 패키지는 쿠버네티스 리소스를 하나로 묶은 Helm-Chart이다. 쿠버네티스에서 애플리케이션을 배포하기 위해서는 service, deployment, StatefulSet, configMap, secret 등이 필요한데 각각의 object들을 생성하기 위해선 각각 yaml파일을 생성해줘야 한다. Helm-Chart는 yaml 파일들의 묶음이라고 생각하면 된다.
KUBEAPPS에서 Catalog에 들어간 후 redis를 최신 버전으로 Deploy한다. 클러스터가 아닌 그냥 레디스이다. Master, Sentinel의 service의 type을 NodePort로 열어주고 Sentinel의 nodePorts를 30000-32767 사이 원하는 포트로 열어준다. 예를 들면 redis는 30000, sentinel은 31000로 설정해주면 설정한 개수에 따라 다르지만 실제로 30001, 30002.. 차례로 열린다. replica 항목에서 replicaCount를 보면 몇개의 Replica가 생성될지 설정할 수 있다. 당연히 sentinel의 enabled: true로 설정해줘야 한다. Sentinel을 쓸거니까.
Deploy하면 Pod이 차례로 뜨고 환경 구축이 완료된다. 보통 Sentinel과 Redis를 각각 분리된 서버에 올리지만 편하자고 Helm-Chart를 사용했으므로 써진대로 따라야 한다. yaml에 정의된 내용대로 뜨면 각 Pod에 Redis, Sentinel이 하나씩 떠 있는 형태이다. 만약 이게 싫다면 StatefulSet을 직접 작성하면 된다.
가상 네트워크 안에서는 서로의 주소를 알고 있지만 내 로컬 환경은 해당 주소가 어디인지 알 수 없다. 고로 /etc/hosts에 127.0.0.1과 redis-node들을 맵핑해줘야 한다.
127.0.0.1 redis-node-0.default
당연히 Redis가 여러개이면 전부 다 맵핑해줘야 한다. 나의 경우 3개를 만들었으므로 3개의 주소를 모두 맵핑해줬다. 이제 요청을 순서대로 따라가보면 내 로컬 컴퓨터는 30001(redis) 포트로 접근하여 연산을 수행하려고 했는데 해당 포트는 Master가 아니었다고 하자. 그럼 그 다음에 31001(sentinel) 포트로 접근하여 Master가 누구인지를 물어본다. 만약 Master가 Redis node 2에 있다면 다시 30002(redis) 포트로 접근하여 다시 연산을 수행한다.
* 아래의 자료들을 참고하였습니다.
'DataBase' 카테고리의 다른 글
Mysql JSON 형태로 조회하기 (2) | 2022.12.31 |
---|---|
데이터를 운반하는 트럭 Packet (0) | 2022.12.31 |
쿼리문을 이용한 공격 SQL Injection (0) | 2022.12.31 |
콜백 지옥에 이은 join 지옥 (0) | 2022.12.14 |
DB와 DBMS의 차이점 (0) | 2022.12.14 |
댓글