모든 태그

# Distributed Systems

7개의 글

분산 시스템, 먼저 제대로 배우고 Kafka를 만든다: MIT 6.5840

자작 스택(커널·DB·JVM)이 다 단일 노드라, 다음 축은 분산이다. 분산을 배우려면 그냥 분산 시스템 하나를 밑바닥부터 만들면 될 것 같지만 거기엔 치명적 구멍이 있다. 네트워크 분단·크래시 같은 실패를 스스로 테스트할 수가 없다. 그래서 MIT 6.5840로 fundamentals를 먼저 정면돌파하고, 그 토대 위에 Kafka를 짓기로 했다. 학습 플랜, Go를 고른 이유, 첫날 MapReduce 셋업까지.

왜 Kafka를 직접 만드나: 내 첫 분산 시스템

미니 RDBMS(db-hobby)를 만들며 남긴 WAL을 보다가 생각이 하나로 모였다. 이 로그를 주인공으로 승격시켜 여러 노드에 복제하면 그게 Kafka다. Java로 바닥부터 만드는 토이 Kafka 연재의 1편. 코드를 쓰기 전에 끝낸 설계 결정들(분산 로그가 뭔지, 왜 Java인지, 단일 브로커 먼저 왜 그런지)과, 이번엔 단위 테스트 대신 "상황 시뮬레이션"으로 검증하기로 한 이유를 정리한다.

DB 내부 ⑩: Raft, primary가 죽으면 누가 결정하는가, 합의에서 HA DB까지

복제의 최대 약점은 'primary가 죽으면?'이다. replica 승격을 사람이 하면 밤에 전화가 오고, 자동으로 하면 split-brain이 온다. 이건 결국 합의(consensus) 문제고, 답이 Raft다. 리더 선출(임기·과반·무작위 타임아웃), 로그 복제(prevLogIndex 정합 검사), 그리고 '과반에 있어도 현재 임기여야만 커밋'이라는 §5.4.2의 미묘함까지, 다섯 안전성 성질을 결정적 시뮬레이션 네트워크(분단·크래시·재정렬을 재현 가능하게 주입) 위에서 확인한다. 이어서 프로덕션의 조각들: 재시작 후 이중 투표를 막는 지속성(currentTerm/votedFor fsync, §5.1), 무한히 크는 로그를 자르는 스냅샷(§7, 그리고 오프셋 0이 no-op이라 기존 테스트가 버그를 못 잡는 함정), 돌아가는 중에 노드를 넣고 빼는 멤버십 변경(§6, 겹치는 과반), 상태기계 복제(SMR)로 진짜 SQL 엔진을 복제해 리더가 죽어도 살아남는 HA DB, 마지막으로 파티션된 옛 리더가 낡은 값을 주지 않게 하는 선형화 읽기(ReadIndex, §8)까지. 적대적 리뷰가 잡아낸 실제 버그들(스냅샷 미설치 발산, apply 에러 무시, read barrier의 epoch 부재)이 각 절의 정직한 경계다.

DB 내부 ⑨: 복제, 복구의 redo를 스트림으로, base backup + WAL 스트리밍까지

복제의 첫 통찰은 '복제가 거의 공짜'라는 것이다. no-force WAL이 이미 커밋의 순차 스트림이라, replica가 할 일은 크래시 복구의 redo를 '파괴적 일회성'이 아니라 '증분·연속'으로 돌리는 것뿐이다. PostgreSQL에서 walreceiver가 WAL을 받아 쓰고 startup process가 replay하는 그 구조. 이를 소켓에 올리면 walsender/walreceiver가 되는데, 스트림엔 경계가 없어 길이 프레이밍이 필요하고, 수신자는 읽기 전용 fd에 쓸 수 없어 실제로 교착을 밟았다. 마지막은 캡스톤, 곧 진짜 엔진의 커밋이 복제본에서 SELECT되기까지다. 코드보다 어려웠던 건 조용히 깨지는 landmine 셋: 재오픈이 WAL을 truncate하고 LSN을 리셋해 replica가 신규 커밋을 조용히 스킵하는 것, base 스냅샷에 steal된 미커밋 페이지가 딸려오는 것, 카탈로그의 낡은 next_txn이 복제된 행을 미커밋으로 보이게 하는 것. 셋을 정리하면 필연적으로 실제 시스템과 같은 모델, 곧 pg_basebackup + streaming replication에 도달한다. 구조가 그렇게 강제한다.

pay 총정리: 실패가 비싼 도메인을 밑바닥부터

Spring Modulith로 만든 결제 시스템 pay의 전체 기록을 한 편에 정리했다. 결제를 고른 이유(타임아웃·중복·미확정·정산 불일치가 실제로 아픈, 실패가 비싼 도메인)에서 시작해 신뢰 경계, PG 타임아웃을 UNKNOWN으로 보존하고 복구가 확정하는 실패 설계, 복식부기 원장·정산·대사, PG 콜을 트랜잭션 밖으로 뺀 체크아웃 사가, 재고 락 3종 실측, 멀티 PG·구독·선불 월렛·가상계좌·FDS·복합결제로의 결제수단 확장, 대기열·유입 제어·암호화 같은 보안 층, 회원과 분쟁·차지백, 그리고 내 코드를 스스로 감사해 잡은 자금 손실 버그까지. 시리즈를 안 읽어도 이 한 편으로 전체가 잡히게 썼고 깊이가 필요한 지점마다 해당 편을 링크했다.