# 084 — 소유자를 키로 나누면: 이 장치는 동기화를 한 줄로 세운다 2026-09-27. [로드맵](../roadmap.md) 중기 2 "키 해시 기반 단일 소유자 파티셔닝(쓰기 병목 선형 확장)"을 할지 정한 것. 착수 기준: - 바꿀 결정: 상태를 가진 앱의 소유자를 키 해시로 여럿 두고(소유자마다 저장소 하나) 내구성 있는 쓰기를 코어 수만큼 늘릴지, 지금처럼 소유자 하나가 한 번의 동기화에 모든 이벤트를 모으게 둘지. - 남은 질문: 이 장치가 파일 여러 개의 `fdatasync`를 동시에 처리하는가? 소유자를 나누면 앱의 초당 쓰기가 느는가? - 최소 확인: 저장소 커밋과 같은 모양(0을 써 둔 곳을 덮어쓰고 `fdatasync`)을 파일마다 스레드 하나로 1·2·4개 동시에 돌려 합계를 재고, 점수판 앱을 저장소 하나의 소유자 하나와 저장소를 따로 가진 소유자 둘로 번갈아 잰다. - 중단 기준: 동기화 합계가 스레드 수를 따라 늘면(장치가 병렬로 처리하면) 샤딩을 설계한다. ## 장치가 말한 것 Raspberry Pi 5, SD 카드의 ext4, 4 KiB 커밋, 3초씩, 순서를 돌려 가며 네 라운드 ([probe.c](../../research/experiments/013-parallel-syncs/probe.c), [run.py](../../research/experiments/013-parallel-syncs/run.py), [원시 결과](../../research/experiments/013-parallel-syncs/2026-09-27-ext4-linux-aarch64.json)): | 동시에 동기화하는 파일 | 합계 커밋/s | p50 | |---|---:|---:| | 1 | 512–669 | 1.21–1.23 ms | | 2 | 556–664 | 2.42–2.45 ms | | 4 | 626–684 | 4.93–5.09 ms | 합계는 그대로이고 지연만 파일 수에 비례한다. 장치가 동기화를 하나씩 처리한다(SD는 명령을 한 줄로 받는다). 점수판 앱의 내구성 POST(연결 64개를 나눠 받음, 서버는 CPU 0·1, 부하는 CPU 3·2): | | posts/s | p99 | |---|---:|---:| | 소유자 하나, 저장소 하나 | 18,542–23,384 (중앙값 20,974) | 13.8–25.6 ms | | 소유자 둘, 저장소 둘 | 13,991–17,716 (중앙값 16,230) | 36.9–57.3 ms | 나누면 23% 느리고 꼬리 지연이 2–3배다. 동기화는 줄을 서는데, 한 번의 동기화가 싣는 이벤트는 소유자마다 반으로 준다. 소유자 하나의 그룹 커밋은 기다리는 이벤트를 모두 한 번의 동기화에 싣는다. 이 장치에서는 그것이 쓰기의 최선이다. ## 결정 - 키 해시 샤딩은 하지 않는다. 쓰기의 병목은 CPU가 아니라(소유자의 라운드에서 적용은 4%, [081](081-tail-records.md)) 장치의 동기화 한 줄이다. 코어를 늘려 줄 것이 없다. - 병렬로 동기화하는 장치(여러 큐의 NVMe)에서도 저장소를 소유자마다 두기보다 한 저장소의 그룹 커밋을 여러 소유자가 함께 쓰는 쪽이 먼저다. 문서 서버는 이미 그렇게 스레드들의 커밋을 묶는다(`d4b01a7`). 앱의 적용이 CPU 하나를 넘을 때 소유자를 나누되 동기화는 장치마다 한 줄로 모은다. - 멀티코어는 읽기에 쓴다. 연결 스레드가 스냅숏으로 보기를 답한다(`--threads auto`, [080](080-snapshot-reads.md)). - 이 장치에서 쓰기를 더 늘리는 길은 동기화의 비용 자체다. 커밋 경로에서 꼬리 늘리기와 압축을 빼면 처리량은 5–8% 늘고 p99는 반이 된다([081](081-tail-records.md) 다음 결정).