병렬 작업의 고통 둘
공유된 작업물에 세션을 여럿 동시에 돌리면 문제 둘이 바로 와. 로그 경합이랑 커밋 충돌. 같은 문제처럼 느껴져. 행위자 둘, 자원 하나. 그런데 답이 완전히 달라. 이 강의는 첫 번째고, 다음 트랙이 두 번째야.
로그 경합엔 깔끔한 구조적 답이 있고, 그 답은 잠금이 아냐. 프로세스 하나만 기록자로 만들어. 모든 세션, 모든 명령줄 도구, 모든 사용자 인터페이스가 그 프로세스한테 써달라고 부탁하는 클라이언트야. 세션끼리는 이제 안 다퉈. 근데 그걸 실제로 해주는 게 뭔지 봐. 프로세스 개수가 아냐. 단일 진입점은 분산 경합을 없애고, 기록자 안에서는 동시 요청이 여전히 스레드 풀로 들어와서 잠금 하나 뒤에서 직렬화돼. 클라이언트마다 맞아야 하던 게, 직렬화가 맞아야 하는 자리 하나로 줄어든 거야. 그게 산 거고.
이게 잠금보다 나은 이유
잠금은 공학 의상을 입은 규율이야. 모든 기록자한테 제대로 획득하고, 제대로 해제하고, 쥔 채로 죽는 경우까지 처리하라고 부탁해. 그리고 하나가 잊거나, 나중에 추가된 경로 하나가 그 관례를 모르면 조용히 깨져. 실패 양상은 멀쩡해 보이는 뒤엉킨 쓰기고.
단일 기록자는 질문 자체를 없애. 새 클라이언트가 어길 관례가 없어. 클라이언트는 아예 쓸 수가 없으니까. API 가 유일한 문이고, 문은 규칙보다 훨씬 올바르게 유지하기 쉬워.
원래 같으면 고약했을 분산 문제 한 부류도 같이 사라져. 작업이 여행 중인 노트북에서도 집의 워크스테이션에서도 벌어질 때, 공유 파일은 진짜 어려운 동기화 문제고 공유 API 종단점은 아예 문제가 아냐. 여행 중인 기계의 도구는 API 클라이언트니까 나머지랑 똑같은 단일 기록자한테 기록하고, 누구 사본이 더 새 거냐는 질문이 아예 안 생겨.
클라이언트한테 걸리는 제약
따라 나오는 명제를 적어둘 값어치가 있어. 실수로 어겨지거든. 엔진이 유일한 기록자면 클라이언트는 절대 쓰면 안 돼. 저장소에도, 로그 파일에도, "이관 때문에 딱 한 번"도 안 돼. 뭘 빨리 고치려고 자기 API 를 우회하는 명령줄 도구는 이 설계 전체가 막으려던 두 번째 기록자를 도로 들여온 거고, 여섯 달 뒤 데이터가 어긋날 때 아무도 기억 못 하는 쓰기가 바로 그거야.
기분 좋은 부수 효과도 있어. 클라이언트가 작아진 채로 남아. 데이터베이스 드라이버도, 스키마 지식도, 이관 사연도 없어. 출력을 예쁘게 찍는 HTTP 클라이언트고, 그 말은 설치 없이 아무 데서나 돌고 아무것도 못 망가뜨린다는 뜻이야.