S3 삭제 감사 로그 유실 — append 동시성과 FIFO SQS
어느 날 보니 파일이 32개 삭제됐는데 기록은 25줄만 남아 있었습니다.
S3 버킷에 쌓인 파일은 며칠 지나면 라이프사이클 규칙 이 알아서 지우고, 무엇이 언제 지워졌는지는 남아 있어야 하니 파일이 하나 삭제될 때마다 구글 스프레드시트에 한 줄씩 적는 감사(audit) 파이프라인을 붙여 뒀습니다. 삭제 이벤트를 EventBridge(AWS 이벤트 버스)가 잡아 SQS(메시지 큐)로 넣고, Lambda 가 메시지를 하나씩 받아 시트에 한 줄을 덧붙이는 경로입니다.
AWS 서비스 몇 개를 이어 붙였을 뿐이라 직접 짠 코드는 Lambda 안의 append 호출 정도입니다.
모든 단계 지표는 32로 정상
각 단계를 다 확인했지만 어디에도 이상이 없었습니다.
| 단계 | 수 |
|---|---|
| EventBridge 매칭 | 32 |
| SQS sent / received / deleted | 32 |
| Lambda invocation | 32 |
| Lambda error | 0 |
| 시트 최종 | 25 |
메시지도 안 잃고 Lambda 도 다 돌았고 에러도 0 인데 시트만 모자란 상태였습니다.
원인 — 동시 실행과 append의 동시성 한계
CloudWatch 로그 스트림을 실행 단위로 하나씩 열어 보니, 한 실행 안에서 Appended row 가 두
번 찍힌 게 있었습니다. 배치로 메시지 두 건을 받아 순차로 처리한 것이고, 그런 실행이 동시에
여러 개 떠 있었습니다.
Google Sheets 의 append 에는 문서에 명시된 한계가 있습니다. 동시에 들어온 append 들이 같은
셀 범위를 잡아 서로 덮어씁니다. “다음 빈 줄” 을 각자 계산하니, 동시에 계산하면 같은 줄을
가리켜 하나가 다른 하나를 밀어내는 것이라, 호출은 다 성공하고 결과 줄만 모자랍니다. 에러가
없으니 지표로는 안 잡히는 실패입니다.
해결 — FIFO SQS로 직렬화
동시에 들어가는 게 문제라 처리를 한 줄로 세우기로 하고, Standard SQS 를 FIFO 로 바꾸고 모든
메시지에 같은 MessageGroupId 를 줬습니다. FIFO 큐는 같은 그룹에 속한 메시지를 한 번에
하나씩만 처리하니 그룹을 하나로 고정하면 전체가 한 줄로 세워집니다. 여기에 Lambda 배치 크기를 1
로 두면 한 실행에서 한 건만 다룹니다.
EventBridge 도 SqsParameters 로 FIFO 타겟의 MessageGroupId 를 지정할 수 있어서 파이프라인
구조는 그대로 두고 직렬화만 얹으면 됐고, 그 뒤로는 32개가 빠짐없이 기록됩니다.
지표는 정상인데 결과가 모자랄 때 — 동시 덮어쓰기
모든 단계 지표가 정상인데 최종 결과만 모자라면 동시에 들어와서 서로 덮어쓴 걸 의심합니다. 로그를 실행 단위로 하나씩 열어 한 실행이 몇 건을 처리했는지, 그런 실행이 같은 시각에 몇 개나 떠 있었는지를 보면 대개 거기서 드러납니다.
순서가 있는 append 성 작업이라면 처음부터 FIFO 큐에 단일 MessageGroupId 로 직렬화해 두는 편이 낫습니다. 감사 로그처럼 건수가 적고 빠질 일이 없어야 하는 쪽은 병렬로 빨리 처리하는 것보다 겹치지 않게 하는 게 목적입니다.
댓글 0