운영하다 만난 세 가지 의문RabbitMQ 컨슈머가 죽으면 메시지가 즉시 재큐잉됩니다. 브로커는 어떻게 즉시 알았을까요?좀비가 된 컨슈머는 30분(ack timeout)이나 기다립니다. 왜 얘는 즉시 알 수 없었을까요?업로드가 중간에 끊기면 폴백이 발동합니다. "끊김"은 누가, 언제 판정한 걸까요?셋 다 답이 한 가지 사실에서 나옵니다.전제: TCP에서 침묵은 정상이다TCP 연결은 케이블 어딘가에 실체로 존재하는 게 아닙니다. 양쪽 컴퓨터의 커널이 각자 메모리에 적어둔 상태(어디까지 보냈나, 어디까지 받았나, 버퍼)일 뿐입니다. 그리고 주고받을 데이터가 없으면 아무 패킷도 흐르지 않습니다. 조용한 연결은 0바이트이고, 그게 TCP의 정상 상태입니다.여기서 문제가 생깁니다. 상대가 조용할 때, 그 침묵이 ..
배경: 며칠 지나면 맥이 느려졌다로컬에서 개발하다 보면 부팅 직후에는 빨랐습니다.그런데 며칠이 지나면 점점 느려졌습니다.재부팅하면 다시 빨라졌습니다.이 패턴이 계속 반복됐습니다.처음에는 그냥 넘겼다"뭔가 쌓여서 그렇겠지" 하고 대수롭지 않게 봤습니다.재부팅하면 해결되니까요.그런데 너무 자주 반복되니 원인이 궁금해졌습니다.첫 시도: 도커 컨테이너를 줄여봤다처음에는 도커가 메모리를 많이 먹는다고 생각했습니다.그래서 Kafka 컨테이너를 3개에서 1개로 줄였습니다.큰 효과가 없었습니다.컨테이너 개수가 문제가 아니라는 뜻이었습니다.메모리를 직접 들여다봤다먼저 무엇이 병목인지 봤습니다. CPU는 한가한데 메모리만 압박이었습니다.top -l 1 | grep PhysMemPhysMem: 35G used (4937M ..
다운로드 시간의 중요성운영 중인 서비스는 Spot 인스턴스 기반이라 매일 100~200번 인스턴스가 교체됩니다. 재부팅할 때마다 S3에서 수 GB의 모델 파일을 받아야 하기 때문에 아래와 같은 관점에서 다운로드 시간을 줄이는 것이 중요합니다.비용: 기동 시간 1분 단축 = 월 수십 시간 절약 = 월 수십 달러 절감장애 대응: 트래픽 스파이크 때 새 인스턴스가 준비되는 시간 = 사용자가 기다리는 시간1단계: 네트워크 시간이 느린걸까?이 시간을 줄여보기 위해. 먼저 현재 속도가 정상적인지를 검토해보았습니다.실측 속도가 ~300 MB/s였고, 스펙상으로는 더 빨라야했습니다.여러 시도병렬 다운로드multipart chunk 크기 조정 (8MB → 64MB)S3 Transfer Acceleration 활성화CRT..
이전 글에서 synchronous_commit 설정을 통해 데이터 안전과 쓰기 성능 사이의 트레이드오프를 확인해 보았습니다. 이론적으로 커밋된 데이터는 WAL(Write-Ahead Log) 덕분에 안전하게 보장된다고 배웠습니다.하지만 문득 이런 의문이 들었습니다."이론적으로 복구된다는 건 알겠는데, 실제로 데이터가 막 쏟아지고 있는 찰나에 서버 전원이 나가버려도 정말 데이터가 하나도 안 날아가고 다 복구될까?" 이 궁금증을 해결하기 위해, 직접 PostgreSQL 컨테이너의 프로세스를 강제로 Kill하는 실험을 진행했습니다.synchronous_commit의 정확한 작동 방식트랜잭션 처리 과정1. 데이터 변경 발생 (INSERT, UPDATE 등)메모리에 데이터 기록데이터를 WAL 버퍼(메모리)에 기록2..
WAL/Redo 쓰기 지연에 대해 공부하면서 안전과 속도의 트레이드오프가 실무에서 비용과 직결된다는 글을 읽었습니다. 그런데 문득 이론적으로 느리다는 건 알겠는데, 실제로 디스크 I/O 병목이 얼마나 심하길래 데이터 유실의 위험을 감수하면서까지 속도를 올리려고 하는 걸까? 하는 생각이 들었습니다. 더 깊이 이해하고 싶어서 PostgreSQL의 synchronous_commit 설정을 이용해 직접 테스트를 진행하고 관련 내용을 찾아보았습니다synchronous_commit 설정이란?PostgreSQL에서 트랜잭션이 커밋될 때, 해당 변경 사항을 디스크의 WAL(Write-Ahead Log) 파일에 언제 물리적으로 기록할지 결정하는 설정입니다.on (기본값): 커밋 시 데이터가 디스크에 완전히 기록될 때까지..