레디스(Remote Distionary Server)는 키-배류 형태의 고성능, 고가용성, 확장성을 보장하는 In memory NoSQL 저장소 이다.

레디스의 커맨드는 싱글 스레드 이벤트루프 방식으로 동작한다. 따라서 레이턴시가 높은 커맨드를 사용할때는 주의를 해야한다. 

 

자료구조

밸류타입 커맨드 성능
String SET, GET, INCR, INCRBY
MSET, MGET
O(1)
O(N)
List LPUSH, RPUSH
LPOP, RPOP, LRANGE,LTRIM, LINSERT, LSET, LINDEX
O(1)
O(N)

Set SADD,SPOP
SMEMBERS,SREM,SINTER,SUNION,SDIFF

O(1)
O(N)

SortedSet ZADD,ZRANGE,ZRANK
ZREM
O(log(N)) 
O(M*log(N))
Hash HSET, HGET
HGETALL,HMGET,HMSET
O(1)
O(N)
Hyperloglog PFADD,PFCOUNT O(1)
Bitmap SETBIT,GETBIT O(1)
Geospatial GEOADD
GEOPOS
GEOSEARCH
O(log(N))
O(1)
O(N+log(M)) 
Stream    
JSON    
Bitfield    
BloomFilter    
CuckFilter    
T-digest    
Top-K    
Count-min sketch    
     
     

 

  • 다른 자료구조가 이미 생성되어 있는 키에 다른 자료구조로 추가할때 에러를 반환함
  • 모든 아이템을 삭제하면 키도 삭제됨
  • 키가 없는 상태에서 삭제 커맨드를 실행할 경우 에러를 반환하지는 않음

캐싱전략

  • 읽기 전략
    • look a side : 애플리케이션에서 캐시를 먼저 조회하고 있으면 반환 없으면 애플리케이션이 DB를 조회하여 캐시를 채우고 반환
    • read through : 애플리케이션에서 캐시를 먼저 조회하고 있으면 반환 없으면 DB를 조회하고 캐시를 채우고 반환
  • 쓰기전략
    • write through : 데이터 업데이트시 매번 캐시도 업데이트
    • write back : 캐시에 먼저 업데이트 후  비동기로 디비에 업데이트
    • cache invalidation : 데이터가 업데이트 될때 마다 캐시를 삭제

만료시간

TTL : 데이터의 저장 기간

EXPIRE : 데이터의 만료 시간

 

복제

마스터 노드의 데이터를 슬레이브 노드로 실시간 동기화 하는 작업

 

목적

  • filover
  • 트래픽 분산(read : 슬레이브, write : 마스터) 
  • 백업 시 사용

구성

  • 마스터 노드와 다수의 슬레이브
  • 레플리카 노드에서 복제
  • 복제 그룹에는 하나의 마스터 노드 ( 마스터 노드 복제 안됨)

동작방식

  • 복제 연결
    • disk (repl-diskless-sync : no, 7 버전 미만 디폴트)
      • repalica of 명령어로 복제를 시작
      • fork로 자식 프로세스를 생성하여 마스터 노드의 RDB 스냅숏 파일을 생성(BGSAVE command)
      • RDB 생성 이후의 마스터 노드에서 실행되는 모든 커맨드는 RESP 형태로 Replication Buffer 에 저장함
      • RDB 파일을 슬레이브 노드로 전송
      • 슬레이브 노드에서는 이 파일을 로드하여 데이터를 초기화 함
      • Replication Buffer 에 쌓여있는 커맨드를 슬레이브노드로 전송하여 데이터 동기화
      • RDB 파일이 생성되는 도중 다른 복제요청이 들어올 경우 큐에 저장되고 파일 생성 완료후 동시에 복제 연결 시작
    • diskless (repl-diskless-sync : yes, 7 버전 이상 디폴트)
      • repalicaof 명령어로 복제를 시작
      • 슬레이브 노드로 소켓통신을 통해 RDB 데이터를 전송
      • RDB를 전송하기 시작한 이후의 마스터 노드에서 실행되는 모든 커맨드는 RESP 형태로 Replication Buffer 에 저장함
      • 슬레이브 노드에서는 이 RDB데이터를 RDB파일로 저장
      • 복제본의 데이터를 모두 삭제한뒤 RDB 파일 로드 
      • Replication Buffer 에 쌓여있는 커맨드를 슬레이브노드로 전송하여 데이터 동기화
      • 복제 연결이 시작된 상태에서 다른 복제 요청은 큐에 대기하고 이전 요청이 끝나기 전까지 복제를 시작할 수 없음
      • repl-diskless-sync-delay 이 옵션 값만큼 복제를 대기하고 대기하는 동안 다른 복제 요청이 들어올 경우에는 대기시간이후 동시에 복제를 시작함
  • 복제연결이후
    • 마스터에서 클라이언트가 요청한 커맨드를 실행하고 클라이언트로 응답
    • 이후 비동기로 슬레이브 노드로 커맨드 전달 
    • 마스터에서 요청처리 완료후 슬레이브로 전달하기전 마스터가 비정상 종료될 경우 슬레이브에 데이터가 유실될 수 있음

복제 데이터 일관성

  • 모든 레디스 인스턴스는 replication id를 갖고있음
  • 복제그룹의 replication id는 모두 동일함
  • INFO Replication command : replication id와 오프셋을 기준으로 마스터와 복제본간의 일치 상태를 확인

 

Partial resynchronization

  • 복제 연결이 일시적으로끊길 경우 재 연결시 RDB 파일을 새로 만들어 동기화 하는것은 비효율적임
  • 백로그 버퍼를 이용하여 복제가 끊긴 시점부터 부분적으로 복제하도록 하는 기능 (PSYNC)
  • 백로그 버퍼에 재 연동하려는 오프셋이 존재하지 않거나 replication id가 마스터와 다를 경우 에는 full resync 시도
    • repl-backlog-size : 백로그 버퍼 사이즈 설정
    • repl-backlog-ttl : 이 시간이 경과하면 삭제
  • 복제본은 마스터로 승격될 가능성이 항상 존재하기 때문에 백로그 버퍼를 해제 하지 않음

 

복제 그룹에서 새로운 마스터가 선출 될 경우

  • 기존 마스터가 비정상 종료되고 복제본 중 새로운 마스터가 선출될 경우 replication id는 새로 생성됨
  • 이 경우 승격되지 않은 다른 복제본은 새로운 마스터와 복제 연결을 하게 됨
  • 두 노드는 동일한 마스터로부터 복제 중이었으므로 Partial resynchronization이 가능함
  • 이를 위해 secondary replication id가 필요 함
  • secondary replication id : master_replid2 속성에 기존의 replid가 저장되고 복제 요청 시 마스터로 전달하여 partial resync가 가능

복제본 계층 구조

  • A - B - C 
  • master 노드 A를 B 노드가 복제하고 C 노드는 B 노드로부터 복제하는 경우 
  • B 노드에만 데이터 변경이 발생하더라고 C 노드로 복제 되지는 않음
  • A 와 C 노드는 동일한 데이터로 복제됨

유효하지 않은 복제본

  • replica-serve-stale-data=yes(default) 옵션으로 처리방식 결정
  • 기본적으로 유효하지 않은 경우에도 클라이언트로 데이터를 전달
  • no 로 설정할 경우 Sync with master in progress 라는 오류 반환

고려사항

  • 슬레이브가 마스터의 상태를 모를 경우 데이터 유실이 발생할 수 있음
  • 네트워크 / 디스크 용량 등의 문제로 복제가 실패하는 경우에 대한 모니터링과 처리
  • 백업 기능을 사용하지 않는 경우 

센티널

마스터와 슬레이브 노드의 상태를 모니터링하여 문제 발생 시 자동으로 failover 를 진행 시킴

모니터링, 자동failover, 클라이언트에 인스턴스 구성정보 전달

 

동작방식

  • sentinel.conf 파일에 port, sentinel monitor 마스터노드명 쿼럼값 등을 입력 
    • 복제노드는 자동으로 찾으므로 따로 설정하지 않음
  • redis-sentinel sentinel.conf / redis-server sentinel.conf --sentinel 두가지 명령어중 하나로 인스턴스를 띄움
  • 최소 3대이상의 독립적인 인스턴스를 실행(SPOF 방지)
  • redis-cli -p 26379(일반적으로 레디스 포트에 2를 붙임) 로 접속
    • SENTINEL master 마스터명 을 이용하여 마스터 정보를 조회, 데이터는 조회할 수 없음
    • SENTINEL replicas 마스터명 을 이용하여 복제본 정보 조회
    • SENTINEL sentinels 마스터명 을 이용하여 센티널 정보 조회
    • SENTINEL ckquorum 마스터명 을 이용하여 쿼럼 정보 조회
  • 인스턴스 정보전달
    • 클라이언트가 센티널에 레디스 구성 정보 요청을 보내면 구성정보를 응답으로 주고 클라이언트는 마스터 노드에 직접 접속하여 커맨드 처리
  • failover
    • down-after-milliseconds 에 정의된 시간안에 ping에 대한 응답이 오지 않으면 마스터가 다운됐다고 판단. 상태를 sdown(subjectly down)으로 변경
    • 다른 센터널 서버들에 장애 상황 전달 (SENTINEL is-master-down-by-addr ip port epoch)
    • 다른 센티널 서버로부터 장애상황 응답을 받고 쿼럼값이상으로 장애 상황이 인지되면 odown(objectly down) 으로 상태 변경
      • 복제본이 다운된경우에는 sdown 상태만 관리
    • epoch(failover 버전) 값 증가, 새로운 failover 처리시 마다 1씩 증가
    • epoch값을 증가시킨 센티널은 센티널 리더 선출 요청. 증가시킨 epoch 값을 같이 전달
    • 복제본 선정
      • redis.conf 파일에 명시된 replica-priority 가 낮은
      • 마스터로부터 더 많은 데이터를 수신한 복제본
      • 모두 동일하다면 runId 사전순으로 작은 복제본
    • 선정된 복제본에는 slaveof no one 수행 기존 마스터로부터 복제 연결 중단
    • 복제 연결 변경 replicaof newip newport

클러스터

레디스 클러스터는 여러 대의 레디스 노드를 하나의 분산 시스템으로 관리하는 기술로, 데이터의 분산 저장(샤딩)과 고가용성 제공

 

  • 데이터 샤딩, 자동 failover 등을 통한 고가용성, 확장성 확보
  • 데이터 샤딩
    • 마스터 최대 1000개까지 확장 가능
    • 레디스 자체 관리
    • 키가 할당된 마스터 노드로 연결 리디렉션
    • 클라이언트는 클러스터 내에서 특정 키가 어떤 마스터에 저장돼 있는지 캐싱
    • 모든 데이터는 해시슬롯에 저장, 총 16384개
    • 해시슬롯 = CRC16(key) mod 16384 
    • 다중키는 여러개 노드의 해시슬롯에 저장되어 있을 수 있으므로 다중키 커맨드는 사용 불가. 
      • 해시태그를 이용하여 처리가능
  • 고가용성
    • 클러스터 구성에 속한 노드는 서로를 모니터링 함
    • 자동 failover
    • 클러스터 버스를 이용한 독립적인 통신, cluster_bus_port 값을 지정하지 않으면 10000을 더한 16397 포트를 사용

failover

마스터 노드에 장애가 발생할 경우 해당 마스터의 복제본은 다른 마스터 노드들에게 페일오버 시도에 대한 투표 요청

과반수 이상 마스터 노드들에서 투표를 받는 경우 해당 복제본은 마스터로 승격

 

마스터로 승격되어 슬레이브 노드가 없을때 다시 장애가 발생할 경우 cluster-require-full-coverage 에 따라 처리

  • yes (default) : 데이터의 정합성을 위해 클러 스터 전체 상태 fail 
  • no : 장애가 발생한 노드만 에러 처리

자동 복제본 마이그레이션

  • cluster-allow-replica-migration : yes
  • cluster-migration-barrier : 1 ( 마스터가 가져야할 최소 복제본 수)
  • 가장 많은 복제본이 연결된 마스터노드의 복제본 중 하나를 사용

실행

  • redis.conf 파일에 cluster-enabled = yes 로 설정
  • redis-cli -cluster create host:port host2:port --clusteer-replicas 1
  • cluster nodes 명령어로 상태 확인

동작방식

  • 하트비트패킷을 이용하여 노드들간의 상태 확인
    • epoch : 버전
    • 비트맵 : 해시슬롯 비트맵
    • 플래그 : 마스터/복제본
    • 클러스터 상태 : down/ok
    • 가십섹션 : 클러스터내의 다른 노드 정보
  • 해시슬롯 구성 전파
    • 하트비트패킷
    • 업데이트메시지 : epoch 값이 오래된 경우 업데이트 메시지를 보내 해시슬롯 구성 업데이트
    • 해시슬롯 구성의 변경은 failover / 리샤딩 중에만 발생
  • 노드핸드셰이크
    • 방향성이 없는 cluster meet 커맨드를 보내고 이를 받은 노드는 자신이 알고 있는 다른 노드들에 전파
    • 이를 통해 이미 알고 있는 노드들끼리만 통신
    • 클러스터 내부의 모든 노드들은 풀 메쉬 연결
  • 리디렉션
    • MOVED : 클라이언트가 요청한 커맨드를 처리할 키의 해시슬롯이 현재 노드가 아닐때 적절한 노드의 정보로 리턴, 해시슬롯 맵 갱신
    • ASK : 현재요청은 리디렉션하지만 이후 요청은 현재 노드로 요청. 해시슬롯 맵 갱신 안함
  • failover
    • NODE_TIMEOUT 시간보다  오랫동안 ping에 대한 응답을 받지 못한 경우 노드 유형에 관계없이 PFAIL(Possible failure) 상태로 플래그
    • 클러스터내의 다른 노드가 보낸 하트비트패킷에서 PFAIL/FAIl 알림을 받는 경우 FAIL로 플래깅
    • 복제본은 마스터 상태에 따라 직접 failover 시도
      • 마스터가 FAIL 상태
      • 마스터가 1개 이상의 해시슬롯을 갖는 경우
      • 마스터와 복제가 끊어진지 설정된 값보다 오래된 경우
    • 클러스터 내의 마스터 노드에 투표요청(FAILOVER_AUTH_REQUEST)
    • FAILOVER_AUTH_ACK 패킷으로 투표
      • 동시에 다른 복제본 승격을 방지하기 위해 NODE_TIMEOUT*2 시간동안 같은 마스터의 복제본에게 투표 금지
      • 작은 epoch 값의 AUTH_ACK는 무시
    • NODE_TIMEOUT*2 시간 동안 과반수 이상의 마스터로부터 ACK 오는 경우 FAILOVER 진행
      • 응답이 오지 않아 중단된 경우 NODE_TIMEOUT*4 지연후에 재 투표 시도 가능

모니터링

  • redis_exporter
  • node_exporter
  • alertmanager
  • prometheus
  • grafana

+ Recent posts