Data Engineering

  • 여러 Pod가 PostgreSQL 월별 파티션을 동시에 만들지 않게 한 방법

    감사 로그는 계속 쌓이지만 오래된 기록을 조회하는 빈도는 낮습니다. 그래서 audit_log와 audit_log_target을 occurred_at 기준의 월별 RANGE 파티션으로 나눴습니다. 데이터가 어느 파티션으로 들어갈지는 명확했지만, 다음 달 파티션을 누가 언제 만들지는 별도의 문제였습니다. PostgreSQL은 입력값을 받아 줄 파티션이 없으면 부모 테이블에 대신 보관하지 않습니다. DEFAULT 파티션을 두지 않은…

    읽기 →

  • 대규모 시계열 데이터를 PostgreSQL 파티션으로 나누기

    시간 순서로 계속 쌓이는 이벤트 데이터는 처음에는 단일 PostgreSQL 테이블로도 충분했습니다. 최근 며칠을 조회하는 API, 장비별 필터, 결함 통계 모두 적절한 복합 인덱스로 빠르게 처리됐습니다. 문제는 데이터와 인덱스가 함께 커진 뒤 나타났습니다. 조회 조건은 최근 범위였지만 조회에 사용되는 인덱스는 전체 이력을 포함했습니다. 대량 삭제로 발생한 WAL과…

    읽기 →

  • 실시간·Hot·Cold 3계층 데이터 아키텍처를 설계한 이유

    시간 순서로 쌓이는 이벤트 데이터도 시간이 지나면 접근 빈도와 갱신 방식이 달라집니다. 수집 직후에는 새 데이터가 계속 들어오고 상태가 갱신되지만, 최근 며칠 또는 몇 주의 데이터는 화면 조회와 통계에서 반복해서 읽힙니다. 수개월이 지난 데이터는 거의 조회되지 않지만 감사, 장기 통계, 파일 내보내기를 위해 보관해야 합니다. 초기에는…

    읽기 →

  • Redis Streams의 Pending 메시지를 안전하게 회수하는 방법

    처음에는 XREADGROUP으로 메시지를 읽었습니다. 처리가 끝나면 XACK하면 된다고 생각했습니다. 정상 흐름만 보면 맞는 설명입니다. 운영에서는 다른 질문이 더 중요했습니다. Worker가 ACK 전에 종료되면 누가 메시지를 다시 처리해야 할까요? 전달된 메시지는 ACK 전까지 목록에 남습니다. 이 글은 MongoDB·Redis Streams·PostgreSQL 파이프라인 가운데 Pending 복구 경로를 좁혀 설명합니다. 이…

    읽기 →

  • MongoDB → Redis Streams → PostgreSQL: 유실 없는 데이터 파이프라인 만들기

    MongoDB에 원본을 저장하고 PostgreSQL에 조회용 데이터를 만드는 파이프라인을 운영했습니다. 수집 API는 빠르게 응답해야 했고, 조회 API는 복잡한 필터와 통계를 제공해야 했습니다. 두 요구를 한 데이터베이스에 맡기기보다 MongoDB를 원본 저장소로, PostgreSQL을 조회 저장소로 분리했습니다. 처음 구조만 보면 간단합니다. 수집 요청을 받은 서버가 MongoDB에 문서를 저장하고 Redis Streams에…

    읽기 →