dc ps
Name Command State Ports
--------------------------------------------------------------------------
redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
replica docker-entrypoint.sh redis ... Up 0.0.0.0:6378->6379/tcp
replica2 docker-entrypoint.sh redis ... Up 0.0.0.0:6377->6379/tcp
docker-compose exec redis redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.18.0.4,port=6379,state=online,offset=182,lag=0
slave1:ip=172.18.0.3,port=6379,state=online,offset=182,lag=1
master_failover_state:no-failover
master_replid:037e4f72795874b045dbcbb1c521888818c0e41c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:182
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:182
127.0.0.1:6379>
docker-compose up -d
Creating network "replication_replica" with driver "bridge"
Creating redis ... done
Creating replica ... done
Creating replica2 ... done
docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------
redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
replica docker-entrypoint.sh redis ... Up 0.0.0.0:6378->6379/tcp
replica2 docker-entrypoint.sh redis ... Up 0.0.0.0:6377->6379/tcp
데이터베이스 복제(Replication) 이해: Master-Slave 아키텍처
데이터베이스 복제(Replication)는 분산 시스템에서 필수적인 개념으로, 데이터를 여러 노드에 복사하여 유지함으로써 데이터 일관성, 가용성, 그리고 장애 복구 문제를 해결합니다. 특히, 복제는 데이터 손실 방지와 시스템 성능 향상을 동시에 달성하는 데 중요한 역할을 하며, CAP 이론에서 일관성(Consistency)과 가용성(Availability)의 균형을 맞추기 위한 핵심 기술입니다.
Master-Slave 아키텍처
Master-Slave 아키텍처는 하나의 마스터 노드(Master Node)가 데이터의 주요 처리와 쓰기를 담당하고, 복제본을 유지하는 슬레이브 노드(Slave Nodes)가 데이터를 받아 읽기 작업을 처리하는 구조입니다.
DB(Master) ---(Replication)---> DB(Slave)
이때 복제는 주로 비동기적(asynchronous) 방식으로 이루어집니다. 비동기 복제는 마스터 노드가 슬레이브 노드의 동기화가 완료될 때까지 기다릴 필요가 없기 때문에 쓰기 성능을 크게 향상시킬 수 있습니다. 반면, 동기 복제(synchronous replication)는 모든 데이터가 슬레이브에 완전히 복제될 때까지 대기하기 때문에 강한 일관성을 보장하지만 성능 저하를 초래할 수 있습니다. 이러한 이유로 대규모 시스템에서는 주로 비동기 복제가 선호됩니다.
장애 복구 및 데이터 가용성
~~DB(Master)~~ ---(Replication)---> DB(Slave --> Master)
Failover 메커니즘을 통해 마스터 노드가 다운될 경우 슬레이브 노드 중 하나를 새로운 마스터로 승격시켜 고가용성(High Availability)을 유지할 수 있습니다. 이를 통해 서비스는 중단 없이 운영될 수 있으며, 장애 상황에서도 빠른 복구가 가능합니다. Failover는 리더 선출 알고리즘(Leader Election Algorithm)을 통해 자동화할 수 있습니다. 예를 들어, Raft나 Paxos 알고리즘은 시스템 내에서 새로운 마스터를 신속하게 선출하는 역할을 합니다.
성능 확장과 부하 분산
Master-Slave 아키텍처는 부하 분산(Load Balancing) 측면에서도 유용합니다. 일반적으로 쓰기 작업은 마스터 노드에서 처리하고, 읽기 작업은 슬레이브 노드에서 처리함으로써 성능을 최적화할 수 있습니다. 이렇게 함으로써 읽기 성능을 극대화할 수 있으며, 특히 읽기 집약적(Read-Intensive) 애플리케이션에서 효과적입니다.
Web Application --(write)--> MasterDB ---> SlaveDB
|_______(read)_______↑
이 구조는 데이터 일관성을 크게 요구하지 않는 환경에서는 Eventually Consistent 방식을 활용해 읽기 작업을 처리할 수 있습니다. Eventually Consistent란, 시간이 지나면 모든 노드가 동일한 데이터를 가지게 된다는 일관성 모델로, 일시적으로는 데이터가 다를 수 있지만 결국에는 일관성을 확보할 수 있습니다.
컴퓨터 과학적 시사점
데이터 일관성(Consistency) vs. 가용성(Availability)
- Master-Slave 구조는 비동기 복제를 통해 가용성을 높이지만, 이로 인해 강한 일관성을 포기할 수 있습니다. 이는 특히 CAP 이론에서 언급한 일관성과 가용성 간의 트레이드오프를 반영한 설계입니다.
CAP 이론
- 분산 데이터베이스에서 일관성, 가용성, 파티션 허용성을 동시에 만족시킬 수 없다는 CAP 이론에 따르면, Master-Slave 복제는 가용성을 우선시하는 설계입니다. 이를 통해 시스템의 성능과 확장성을 확보할 수 있습니다.
확장성(Scalability)
- Master-Slave 아키텍처는 읽기 성능의 확장에 매우 적합하지만, 쓰기 성능은 여전히 마스터 노드에 의존하게 됩니다. 따라서 쓰기 성능 확장을 위해서는 샤딩(Sharding) 같은 추가적인 확장 전략이 필요합니다.
요약
데이터베이스 복제(Replication)는 분산 시스템의 안정성, 성능, 그리고 확장성을 동시에 확보하기 위한 필수 기술입니다. 특히, Master-Slave 아키텍처는 읽기 성능 최적화, 장애 복구, 확장성 확보 등 다양한 측면에서 현대 시스템의 요구사항을 충족하는 강력한 솔루션입니다.
Redis의 고가용성 및 확장성 전략
Redis는 고가용성과 확장성을 확보하기 위해 세 가지 주요 기능을 제공합니다: Redis Replication, Redis Sentinel, 그리고 Redis Cluster. 각각의 기능은 특정한 목적을 가지고 Redis 시스템의 신뢰성과 성능을 극대화하는 데 기여합니다. 이제 각 기능의 세부사항과 이를 활용한 시스템 운영에 대해 살펴보겠습니다.
Redis Replication: 마스터-레플리카 구조의 강력한 복제 시스템
Redis Replication은 기본적으로 마스터(Master)와 레플리카(Replica) 간의 데이터 복제를 담당합니다. 이를 통해 복제본이 실시간으로 원본 데이터의 변경 사항을 반영하게 되어, 읽기 작업을 분산하거나 데이터 백업을 위한 용도로 활용할 수 있습니다. Redis Replication의 핵심 기능을 살펴보면 다음과 같습니다
1. Master-Replica 구조
Redis의 Replication은 마스터 노드에서 처리된 모든 쓰기 작업을 레플리카 노드에 전달하는 방식으로 동작합니다. 이렇게 해서 복제된 데이터는 실시간으로 일관성을 유지할 수 있습니다.
2. Command Stream
마스터에서 Command Stream을 통해 레플리카로 데이터를 전달하는 방식은 단순한 데이터 복제 이상의 기능을 제공합니다. 마스터에서 수행된 쓰기 작업뿐만 아니라, TTL(Time To Live) 설정과 같은 명령도 레플리카에 동일하게 반영됩니다. 이를 통해 복제본에서도 정확한 데이터 만료 처리가 이루어집니다.
3. Resync 기능
마스터와 레플리카 간의 네트워크가 일시적으로 끊어지더라도, Redis는 자동으로 Resync 기능을 통해 복구를 시도합니다. 가능한 경우 부분 동기화(Partial Resync)를 통해 중단된 부분부터 데이터를 복제하고, 만약 이를 처리할 수 없을 때에는 완전 동기화(Full Resync)를 통해 전체 데이터를 다시 전달하여 동기화를 진행합니다. 마스터는 이때 RDB 스냅샷을 이용해 데이터를 덤프하고, 이를 레플리카로 전송하여 초기화합니다.
Redis Sentinel: 자동화된 장애 복구 시스템
Redis Replication은 기본적으로 데이터 복제와 읽기 성능 확장을 가능하게 하지만, 장애가 발생했을 때 자동 Failover가 이루어지지 않는다는 한계가 있습니다. 이를 해결하기 위해 Redis는 Redis Sentinel을 제공합니다. Sentinel은 고가용성을 위한 중요한 관리 도구로서 다음과 같은 역할을 수행합니다
1. 모니터링(Monitoring)
Sentinel은 마스터와 레플리카 노드를 지속적으로 모니터링합니다. 네트워크 연결 상태나 서버 성능을 점검하며, 마스터 노드에 이상이 발생할 경우 즉각적으로 대처할 수 있도록 준비합니다.
2. 자동 Failover
마스터 노드가 장애를 일으키면, Sentinel은 자동으로 Failover 절차를 진행합니다. 즉, 현재 사용 가능한 레플리카 중 하나를 마스터로 승격시키고, 클라이언트는 새로운 마스터에 연결되어 서비스를 중단 없이 이어갈 수 있습니다. 이 자동 Failover 메커니즘은 운영자의 개입 없이도 신속하게 이루어져, 시스템의 가용성을 극대화합니다.
Redis Sentinel은 별도의 프로세스로 동작하며, 분산된 환경에서도 안정적인 장애 복구를 보장합니다. 이러한 자동화된 장애 복구 기능은 웹 애플리케이션과 같은 실시간 서비스에서 특히 유용합니다.
Redis Cluster: 고가용성과 수평 확장의 조화
Redis Cluster는 단순히 데이터 복제뿐만 아니라, 수평적 확장성(Horizontal Scalability)을 제공하는 고급 아키텍처입니다. 다수의 마스터 노드를 운영하여 읽기 성능뿐만 아니라 쓰기 성능 또한 확장할 수 있으며, 대규모 분산 환경에서 효과적입니다.
1. 샤딩(Sharding)과 해시 슬롯
Redis Cluster는 저장된 데이터를 샤딩하여 각 마스터에 분배합니다. 이를 위해 해시 슬롯(Hash Slot) 메커니즘을 사용해 데이터를 특정 마스터 노드에 할당합니다. 데이터는 고유한 키 값에 기반한 해시 알고리즘을 통해 적절한 마스터에 분산되며, 이를 통해 클러스터는 트래픽이 증가할 때에도 원활한 확장성을 유지할 수 있습니다.
2. Replication과 고가용성
Redis Cluster에서도 Redis Replication과 유사하게 각 마스터 노드는 레플리카 노드를 갖습니다. 만약 하나의 마스터 노드에 장애가 발생하면, 해당 마스터의 레플리카가 자동으로 새로운 마스터로 승격되므로 데이터 손실 없이 가용성을 유지할 수 있습니다. Redis Cluster는 복제를 통한 고가용성과 다수의 마스터 노드를 통한 성능 확장이라는 두 가지 이점을 모두 제공하는 강력한 구조입니다.
요약: Redis 고가용성 전략의 최적화
Redis는 Replication, Sentinel, 그리고 Cluster라는 세 가지 주요 기능을 통해 고가용성과 확장성을 모두 갖춘 데이터베이스 환경을 제공합니다. 각각의 기능은 운영자가 필요로 하는 성능 목표에 맞추어 조정할 수 있으며, 특히 장애 복구와 성능 확장이 중요한 환경에서 필수적인 도구로 작동합니다. Redis Replication은 읽기 성능 최적화와 데이터 복제를 제공하며, Redis Sentinel은 자동 장애 복구를 가능하게 하고, Redis Cluster는 대규모 수평 확장성과 복제를 동시에 지원합니다.
이러한 Redis의 기능들은 실시간 애플리케이션, 고성능 요구 사항, 그리고 고가용성이 필수적인 시스템에서 중요한 역할을 수행할 것입니다. Redis의 유연한 확장 전략을 통해 복잡한 운영 환경에서도 안정적이고 확장 가능한 서비스를 제공할 수 있습니다.
실습
간단히 redis replication에 대한 실습을 진행해 보겠습니다.
우선 docker hub에서 redis 페이지로 가봅니다.
/usr/local/etc/redis 디렉토리에 설정 파일을 위치 시켜 두면, 레디스 설정에 대한 조치가 될 것입니다.
이미지에 언급된 Dockerfile대로 진행을 할 것입니다.
그렇다면 redis.conf 파일에 설정 방법에 대해 알아 봐야 합니다.
redis 공식 홈페이지에서 replication section으로 이동하여 그 방법을 알아보겠습니다.
'replicaof [IP] [PORT]' 를 입력하게 되는데 이때, 아이피와 포트는 Master Node의 정보입니다.
그럼 입력한 redis는 replica으로 설정 됩니다. 이후 replica는 read-only로 동작하게 됩니다.
당연히 쓰기작업은 되지 않으며, 실패 처리 됩니다.
아래 트리 명령어를 통해서 간단히 실습할 프로젝트 디렉토리의 구조를 확인해 봅니다.
tree .
.
├── conf
│ └── redis.conf
└── docker-compose.yml
2 directories, 2 files
docker-compose.yml 파일의 명세 내역입니다.
version: '3.8'
networks:
replica:
driver: bridge
services:
redis:
image: redis:6.2
container_name: redis
ports:
- 6379:6379
networks:
- replica
restart: always
replica:
image: redis:6.2
container_name: replica
ports:
- 6378:6379
networks:
- replica
volumes:
- ./conf:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
restart: always
replica2:
image: redis:6.2
container_name: replica2
ports:
- 6377:6379
networks:
- replica
volumes:
- ./conf:/usr/local/etc/redis/
command: redis-server /usr/local/etc/redis/redis.conf
restart: always
redis.confl 파일의 명세 내역입니다.
cat conf/redis.conf
replicaof redis 6379
그럼 컨테이너를 기동합니다. 정상적으로 기동이 되었는지. docker-compose ps 명령어로 확인해봅니다.
docker-compose up -d
Creating network "replication_replica" with driver "bridge"
Creating redis ... done
Creating replica ... done
Creating replica2 ... done
docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------
redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
replica docker-entrypoint.sh redis ... Up 0.0.0.0:6378->6379/tcp
replica2 docker-entrypoint.sh redis ... Up 0.0.0.0:6377->6379/tcp
redis-cli를 통해서 replication 접속 정보를 더 상세히 살펴 보겠습니다.
dc ps
Name Command State Ports
--------------------------------------------------------------------------
redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
replica docker-entrypoint.sh redis ... Up 0.0.0.0:6378->6379/tcp
replica2 docker-entrypoint.sh redis ... Up 0.0.0.0:6377->6379/tcp
docker-compose exec redis redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.18.0.4,port=6379,state=online,offset=182,lag=0
slave1:ip=172.18.0.3,port=6379,state=online,offset=182,lag=1
master_failover_state:no-failover
master_replid:037e4f72795874b045dbcbb1c521888818c0e41c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:182
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:182
127.0.0.1:6379>
Replication은 기존 동기화 정보가 끊어 졌을 때, 끊어진 부분부터 다시 이어서 동기화를 진행 할 수 있습니다.
그 이유는 ID, offset 기반으로 진행되기 때문입니다.
동기화 테스트
가장 위쪽이 현재 마스트 redis-cli이며 아래는 replica, replica2로 접속한 상태입니다.
Master Redis에서 쓰기, 읽기 작업시 2개의 replica에서도 싱크가 잘 맞추어져 데이터가 동기화된 모습 보입니다.
Master Redis에서 데이터를 삭제하더라도 replica 모두 데이터가 지워진 모습이 나타납니다.
offset이 변화된 모습이 잘 보입니다.
replica 2곳에서 쓰기 작업이 되지 않습니다.
이번에는 마스터를 다운 시켜보겠습니다. 단순 redis replication 구조인 master - slave 구조에서는
fail-over가 되지 않습니다.
마스터 노드를 재기동하여 원상복구 시켜보며 info replication 명령어를 통해 동기화 되었는지 확인해 보겠습니다.
'DB > Redis' 카테고리의 다른 글
Redis 모니터링 (feat. Prometheus, Grafana, Redis 및 Redis Exporter) (4) | 2024.09.15 |
---|---|
Spring Boot Cache 실습 (1) | 2024.09.14 |
Redis Cache 실습(Aka. Write Back) (1) | 2024.09.14 |
Redis Cache 실습(Aka. Jedis, Cache Aside) (0) | 2024.09.14 |
Redis Cache 활용법: 성능 최적화를 위한 캐시 전략 (0) | 2024.09.12 |