Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

상태관리 객체를 만드는 가장 큰 단점은 구현의 난이도에 있습니다있습

니다.

성능 트레이드오프

장점

  • 로컬 상태 관리로 요청 처리 속도가 빨라짐.
  • 네트워크 비용 감소와 높은 동시성 처리.
  • 읽기와 쓰기의 독립적 최적화.
  • 데이터베이스 성능 의존을 줄일수 있음

...

draw.io Board Diagram
bordertrue
diagramNamehelloredis
simpleViewerfalse
width
linksauto
tbstyletop
lboxtrue
diagramWidth1441
revision1

  • Hello Count 를 질의하기위해 영속장치를 접근할 필요없이 , 인메모리(상태프로그래밍) 에서 정확한 값을 바로 응답할수 있습니다.
  • Redis에 마지막 값을 항상 유지함으로 ~ 업데이트 또는 장애복구시 Actor가 초기화될시 마지막값으로 상태를 복원해 시작할수 있습니다.
    • 마지막 상태값 유지를 위해, 꼭 Redis일 필요없으며, 인메모리 기능을 이미 가지고 있기때문에 RDB에 단지 마지막 값을 유지할수도 있습니다.  
    • 이 모델은 Read를 위해 매번 RDB 조회할 필요가 없으며, Read의 책임있는 DB를 인메모리가 아닌 다른곳에 위임할수도 있습니다. 
  • 이벤트의 변화를 Kafka에 기록해둠으로 누군가는 이것을 소비해 시계열 기반 분석 기능을 작성할수도 있습니다. ( 이벤트 소싱패턴 활용한 다양한 기능을 구현 )



위 방식이 전통적인 CRUD 보다 분명 복잡하고 고려해야할 사항들은 더 있을수 있으며 위 방식을 단지 CRUD방식으로 풀어서 비교해보겠습니다.

전통적인 RDB를 이용한 CRUD 방식

Code Block
themeEmacs
CREATE TABLE user_state (
    user_id VARCHAR(255) PRIMARY KEY,
    state ENUM('HAPPY', 'ANGRY') NOT NULL,
    hello_count BIGINT NOT NULL,
    hello_total_count BIGINT NOT NULL
);

DELIMITER //

CREATE PROCEDURE increment_hello_count(
    IN p_user_id VARCHAR(255),
    IN p_amount BIGINT
)
BEGIN
    UPDATE user_state
    SET hello_count = hello_count + p_amount
    WHERE user_id = p_user_id AND state = 'HAPPY';
END //

DELIMITER ;

DELIMITER //

CREATE PROCEDURE get_user_state(
    IN p_user_id VARCHAR(255)
)
BEGIN
    SELECT state, hello_count, hello_total_count
    FROM user_state
    WHERE user_id = p_user_id;
END //

DELIMITER ;


전통적인 DB에서 쓰기와 읽기를 분리한다고 했을때 이것이 CQRS라고 생각하면 큰 착각이다. 우선 DB의 Read성능을 높이기위해 확장하는것은 DB1개를 더 두는것이기때문에 아주 값비싼 확장방식이다.

더욱이 사용자의 1카운트를 증가하기위해 Update또는 Create만 발생하는것이 아니라~  기존 값을 확인(Read)한후 증가하기때문에 Read와 Write(Update)비용이 증가함과 동시에 동시성 처리를 위해

사용자단위로 LockFree하지 않은 방식이 사용되었습니다.

CRUD가 항상 단점이 있는것은 아니며 다음과 CQRS대비 장단점이 존재합니다.

장점: CRUD

  • 데이터 영속성: RDB는 내구성 있는 저장소를 제공하여 애플리케이션이 충돌하더라도 데이터가 손실되지 않습니다.
  • ACID 트랜잭션: RDB는 원자성, 일관성, 고립성, 내구성을 지원하여 신뢰할 수 있는 트랜잭션을 보장합니다.
  • 유연한 쿼리: SQL을 사용하여 복잡한 쿼리와 조인을 수행할 수 있어 데이터 검색 및 조작이 용이합니다.
  • 확장성: RDB는 대용량 데이터셋을 처리할 수 있으며 샤딩과 복제를 통해 수평 확장을 지원합니다.
  • 백업 및 복구: RDB는 데이터 백업 및 복구를 위한 내장 메커니즘을 가지고 있습니다.

단점: CQRS

  • 지연 시간: RDB 작업은 디스크 I/O 및 네트워크 지연을 수반하므로 메모리 내 작업에 비해 느릴 수 있습니다.
  • 동시성: 높은 동시성을 처리하는 것은 도전적일 수 있으며, 병목 현상을 피하기 위해 신중한 트랜잭션 관리가 필요합니다.
  • 복잡성: 스키마 관리, 인덱스 최적화 및 쿼리 최적화는 애플리케이션에 복잡성을 추가할 수 있습니다.
  • 오버헤드: RDB는 ACID 속성을 유지하고 데이터 무결성을 보장하기 위해 오버헤드를 도입합니다.
  • 확장성: RDB는 확장 가능하지만, 분산 메모리 내 액터 시스템의 선형 확장성을 따라가지 못할 수 있습니다.