Redis Streams와 MSA, Event-Driven 아키텍처

짱구·2023년 2월 3일
0

redis

목록 보기
5/8

MSA(Microservice Architecture)

  • 시스템을 독립적인 단위의 작은 서비스들로 분리(크기보다는 독립성이 중요)
    • 독립적인 단위: 다른 서비스와 다른 이유로 변경되고, 다른 속도로 변경되는 단위
  • 각 서비스들이 사용하는 DB도 분리
  • 각 서비스들은 API(인터페이스)를 통해서만 통신(다른 서비스의 DB 접근 불가)

기존의 Monolithic 아키텍처

  • 모든 기능들이 한 서버 안에 들어가 있고, 공유 데이터베이스를사용

MSA 아키텍처

  • 기능 별로(도메인 별로) 서버가 나뉘어 있고, 각자의 데이터베이스를 사용하며, API를 이용해 통신

MSA 장점

  • 모듈성(높은 응집도, 낮은 결합도)
  • 서비스 별로 독립적인 개발과 배포가 가능
  • 서비스(코드) 크기가 작아져 이해가 쉽고 유지보수가 용이함
  • 더 빠른 개발, 테스트, 배포
  • 확장성(서비스 별로 개별 확장이 가능)
  • 결함 격리(일부 서비스 실패가 전체 시스템 실패로 이어지지 않음)

MSA의 단점

  • 분산 시스템의 단점을 그대로 가짐
    • 일부 실패에 문제를 해결, 네트워크 실패에 대한 처리도 해줘야함
  • 통합 테스트의 어려움
  • 모니터링과 디버깅의 복잡도 증가
  • 트랜잭션 관리의 어려움
  • 서비스간 통신 구조에 대한 고민이 필요
    • 동기 vs 비동기, 프로토콜, 통신 브로커 사용 등

※ 통신 브로커 : 중간에서 기능을 편리하게 사용할 수 있도록 일정 역할을 해주는 모듈

  • 통신 브로커 : 서로간의 통신하는 채널을 브로커 형태로 분리하고 필요한 처리를 해줌
    ex) 메시지 브로커의 확장성, 읽음처리, 재시도 같은 필요한 처리를 해줌

Event-Driven 아키텍처

  • 분산 시스템에서의통신 방식을 정의한 아키텍처로, 이벤트의 생성/소비 구조로 통신이 이루어짐
  • 각 서비스들은 이벤트 저장소인 Even-broker와의 의존성만 가짐

Event-Driven 아키텍처의 모습

  • 각 서버들은 Event Broker에 이벤트를 생산/소비함으로써 통신

Event-Driven 아키텍처의 장점

  • 이벤트 생산자/소비자 간의 결합도가 낮아짐(공통적인 Event-broker에 대한 결합만 있음)
    • 서버와 서버끼리의 통신이 이루어지지 않고 이벤트 브로커랑만 통신
  • 생산자/소비자의 유연한 변경(서버 추가, 삭제 시에 다른 서버를 변경할 필요가 적어짐)
    • 알림 서버가 만약 사라진다해도 알림 서버를 직접 호출하는 서버가 없기 때문에 에러가 발생 X
    • 새로운 서버가 생겨도 기존에 다른 서버에 코드를 바꿔 넣을 필요가 없음
  • 장애 탄력성(이벤트를 소비할 일부 서비스에 장애 발생해도 이벤트는 저장되고 이후에 처리됨)
    • 결제 서비스가 장애가 나더라도 주문 서비스, 주문 이벤트는 계속해서 쌓이게 됨
    • 결제 서비스가 복구가 되면 이벤트 브로커에 쌓여있던 주문 이벤트를 처리

Event-Driven 아키텍처의 단점

  • 시스템의 예측 가능성이 떨어짐(느슨하게 연결된 상호작용에서 기인함)
  • 테스트의 어려움
  • 장애 추적의 어려움

Redis Streams

  • append-only log를 구현한 자료 구조
  • 하나의 key로 식별되는 하나의 stream에 엔트리가 계속 추가되는 구조
  • 하나의 엔트리는 entry ID + (key-value 리스트)로 구성
  • 추가된 데이터는 사용자가 삭제하지 않는 한 지워지지 않음

Redis Streams의 활용

  • 센서 모니터링(지속적으로 변하는 데이터인 시간 별 날씨 수집 등)
  • 유저별 알림 데이터 저장
  • 이벤트 저장소

Redis Streams의 명령어: 엔트리 추가
XADD: 특정 key의 stream에 엔트리를 추가 (해당 key에 stream이 없으면 생성)

XADD [key] [id] [field-value]
- [id] 값에 *를 넣어주면 아이디가 자동 생성된다.
- 생성된 값은 "[시간을 나타내는 단위] - [시퀀스 넘버]"

ex) user-notifications라는 stream에 1개의 엔트리를 추가하며 2개의 field-value 쌍을 넣음


Redis Streams의 명령어: 엔트리 읽기(범위 기반)
XRANGE: 특정 ID 범위의 엔트리를 반환

XRANGE [key] [start] [end]
- [start]와 [end]에 - + 를 넣어주면 모든 범위 조회
- [start]와 [end]에 entry Id를 넣어주면 사이에 있는 엔트리들이 조회가 됨

ex) user-notifications의 모든 범위를 조회


Redis Streams의 명령어: 엔트리 읽기(Offset 기반) - 1

XREAD: 한 개 이상의 key에 대해 특정 ID 이후의 엔트리를 반환한다. (동기 수행 가능)

XREAD BLOCK [milliseconds] STREAMS [key] [id]
- BLOCK 커맨드를 넣으면 동기, 넣지않으면 비동기로 동작
- [milliseconds]는 요청을 받는 요청 대기 시간 (앞으로 [milliseconds]만큼 기다리겠다)
- [key] [id]는 여러개의 값을 넣을 수 있음, 여러개의 키와 아이디에 대해 한번에 조회하겠다는 기능

ex) user-notifications의 0보다 큰 ID조회


Redis Streams의 명령어: 엔트리 읽기(Offset 기반) - 2

XREAD BLOCK [milliseconds] STREAMS [key] [id] $
- 기존에 XREAD 문법에서 마지막에 $만 표시해줌
- 앞으로 새로 들어오는 데이터만 읽겠다는 기능
- 앞으로 들어올 데이터를 동기 방식으로 조회하여 event listener와 같은 방식으로 사용 가능

ex) user-notifications에서 새로 들어오는 엔트리를 동기 방식으로 조회


Redis Streams의 명령어: Consumer Group

  • 한 stream을 여러 consumer가 분산 처리할 수 있는 방식
  • 하나의 그룹에 속한 consumer는 서로 다른 엔트리들을 조회하게 됨 (중복 처리가 이뤄지지 않게 하기 위해)


Redis Streams의 명령어: Consumer Group - 1

XGROUP CREATE: consumer group을 생성

XGROUP CREATE [key] [group name] [id]

ex) user-notifications에 group1이라는 consumer group을 생성

  • 그룹 생성 : group1은 user-notifications라는 key를 가진 엔트리 내에서 지금 이후로 들어오는 데이터에 대해 처리를 함

Redis Streams의 명령어: Consumer Group - 2
XREADGROUP: 특정 key의 stream을 조회하되, 특정 consumer group에 속한 consumer로 읽음

XREADGROUP GROUP [group name] [consumer name] COUNT [count] STREAMS [key] [id]
- [consumer name]는 자신의 인스턴스를 나타내게 된다 
  - [consumer name]는 서버의 인스턴스 번호와 같은 unique한 값이 들어간다
- [id]에 “>”를 지정하면 아직 소비되지않은 메시지를 가져오게된다
  - 다른 Consumer가 가져가지 않은 데이터를 내가 가져가겠다는 표현

ex) user-notifications에서 group1 그룹으로 2개의 컨슈머가 각각 1개씩 조회

동일한 로직을 실행

XREADGROUP GROUP group1 consumer1 COUNT 1 STREAMS user-notifications >
XREADGROUP GROUP group1 consumer2 COUNT 1 STREAMS user-notifications >  
- consumer2는 consumer1이 가져간 메시지 이후의 데이터를 가져감

Redis Streams를 이용한 이벤트 기반 통신 개발

HTTP를 이용한 동기 통신 방식

  • 각 서비스는 필요한 서비스를 직접 호출

이번에 구현할 Event-broker를 이용한 메시지 기반 통신

  • 각 서비스는 미리 정의된 이벤트를 소비/생성함으로써 통신

실습 예제 event 리스트

  • order-events: 주문이 완료되면 발행
  • payment-events: 결제가 완료되면 발행

출처 : fastcampus

profile
코드를 거의 아트의 경지로 끌어올려서 내가 코드고 코드가 나인 물아일체의 경지

0개의 댓글