PHP 리드·아키텍트 트러블슈팅 면접
새 면접Q. 대규모 쇼핑몰 사이트에서 프로모션 기간 동안 특정 상품의 재고가 실제보다 초과 판매되는 문제가 발생했습니다. 재고 차감 로직은 파일 기반 잠금(flock)을 사용하고 있으며, 웹 서버는 NFS로 공유 스토리지를 마운트하여 사용 중입니다. 동시 주문이 많을 때 재고 정합성이 깨지며, 일부 주문은 재고가 마이너스가 되기도 합니다. 이 장애의 원인을 진단하고 즉각 및 중장기 해결 방안을 제시하세요.
NFS 환경에서 파일 잠금의 동작 방식과 분산 환경에서의 동시성 제어 메커니즘을 고려해보세요.
NFS는 파일 잠금을 완벽하게 보장하지 못하며, 특히 여러 서버에서 동시에 flock을 사용할 때 락이 제대로 동작하지 않을 수 있습니다. 즉각 조치로는 재고 차감 로직을 단일 DB 서버의 트랜잭션과 FOR UPDATE 락으로 전환하여 정합성을 보장합니다. 중장기적으로는 Redis의 INCR/DECR 같은 원자적 연산을 활용하거나, 메시지 큐를 통해 재고 차감을 단일 워커가 순차 처리하도록 아키텍처를 변경합니다. 또한 재고 검증 로직을 트랜잭션 내에서 SELECT FOR UPDATE로 조회 후 차감하도록 개선하고, 보상 트랜잭션을 통해 이중 차감을 방지합니다. 모니터링 측면에서는 재고 수량 로그를 별도로 기록하여 정합성 검증 배치를 운영하고, 알림 시스템을 구축합니다.
- • NFS 환경에서 flock의 불완전성 인지
- • DB 트랜잭션 FOR UPDATE 락 활용
- • Redis 원자적 연산 또는 메시지 큐 기반 순차 처리로 전환
- • 재고 정합성 검증 및 모니터링 체계 구축
멀티 서버 환경에서 재고, 쿠폰, 포인트 등 정합성이 중요한 자원을 관리할 때 반드시 고려해야 하는 동시성 제어 이슈입니다.
Redis를 분산 락으로 사용할 경우 Redlock 알고리즘의 필요성과 단일 Redis 인스턴스 장애 시 대응 방안은 무엇인가요?
Q. PHP 애플리케이션에서 Memcached를 세션 스토리지로 사용 중입니다. 특정 시간대에 사용자들이 갑자기 로그아웃되거나 관리자 권한이 일반 사용자로 바뀌는 등 세션 데이터가 뒤바뀌는 심각한 장애가 발생했습니다. Memcached 클러스터는 3대로 구성되어 있으며, PHP의 session.save_handler는 memcached로 설정되어 있습니다. 최근 트래픽 증가로 Memcached 서버 1대를 추가했고, 그 이후부터 문제가 발생하기 시작했습니다. 원인을 분석하고 해결 방안을 제시하세요.
Memcached 클러스터에서 서버 추가/제거 시 키 분산 방식과 세션 ID의 해싱 메커니즘을 살펴보세요.
Memcached는 consistent hashing을 사용하지 않는 기본 해싱 방식에서는 서버 목록이 변경되면 키 분산이 완전히 재배치됩니다. 서버를 추가한 후 동일한 세션 ID가 다른 서버로 라우팅되어 기존 세션을 찾지 못하거나, 더 심각하게는 해시 충돌로 다른 사용자의 세션을 가져오는 문제가 발생할 수 있습니다. 즉각 조치로는 Memcached 서버 목록을 원래대로 복구하거나, libmemcached의 consistent hashing 옵션을 활성화하여 서버 변경 시 영향을 최소화합니다. 중장기적으로는 Redis Cluster나 Redis Sentinel로 전환하여 안정적인 세션 관리 인프라를 구축하고, 세션 저장소 변경 시 Blue-Green 방식으로 전환하며 세션 이중 쓰기 기간을 두는 마이그레이션 전략을 수립합니다. 또한 세션 데이터에 사용자 식별자 검증 로직을 추가하여 세션 하이재킹을 감지하고 차단하는 보안 계층을 구현합니다.
- • Memcached 서버 변경 시 키 재분산 문제 인지
- • Consistent hashing 미적용으로 인한 세션 라우팅 오류
- • Redis로 전환 또는 libmemcached consistent hashing 활성화
- • 세션 검증 로직 추가 및 안전한 마이그레이션 전략 수립
캐시 서버 스케일 아웃 시 키 분산 방식을 고려하지 않으면 세션, 캐시 데이터의 정합성 문제가 발생할 수 있습니다.
Redis를 세션 스토리지로 사용할 때 AOF와 RDB 중 어떤 영속성 전략을 선택하시겠으며, 그 이유는 무엇인가요?
Q. 레거시 PHP 애플리케이션에서 야간 정산 배치 작업 실행 중 'Deadlock found when trying to get lock' 에러가 빈번하게 발생하며 정산이 완료되지 않습니다. 정산 로직은 여러 테이블을 조인하여 집계 후 UPDATE하는 방식이며, 동시에 10개의 PHP CLI 프로세스가 날짜별로 파티셔닝된 데이터를 병렬 처리합니다. InnoDB 엔진을 사용 중이고, 각 프로세스는 트랜잭션 내에서 주문 테이블과 정산 테이블을 번갈아 가며 접근합니다. 데드락의 원인을 분석하고 해결 방안을 제시하세요.
여러 테이블에 대한 잠금 순서와 트랜잭션 격리 수준, 인덱스 사용 여부를 점검해보세요.
데드락은 여러 프로세스가 서로 다른 순서로 테이블 또는 행에 락을 획득하려 할 때 발생합니다. SHOW ENGINE INNODB STATUS로 데드락 로그를 확인하여 어떤 쿼리와 테이블에서 락 충돌이 발생하는지 파악합니다. 즉각 조치로는 모든 프로세스가 동일한 순서로 테이블을 접근하도록 쿼리 순서를 표준화하고, WHERE 절에 적절한 인덱스가 있는지 확인하여 불필요한 갭 락을 방지합니다. 트랜잭션 격리 수준을 READ COMMITTED로 낮춰 갭 락을 줄이거나, 트랜잭션 범위를 최소화하여 락 보유 시간을 단축합니다. 중장기적으로는 정산 로직을 단일 프로세스로 순차 처리하거나, 파티션별로 완전히 독립적인 데이터 범위를 보장하여 락 경합을 원천 차단합니다. 데드락 발생 시 자동 재시도 로직을 구현하고, 슬로우 쿼리 로그와 데드락 모니터링을 통해 지속적으로 개선합니다.
- • SHOW ENGINE INNODB STATUS로 데드락 원인 파악
- • 테이블 접근 순서 표준화 및 인덱스 최적화
- • 트랜잭션 격리 수준 조정 및 범위 최소화
- • 파티션별 독립 처리 또는 순차 처리로 아키텍처 개선
배치 작업이나 대량 데이터 처리 시 병렬 처리로 인한 데드락은 흔한 문제이며, 락 순서와 트랜잭션 설계가 핵심입니다.
READ COMMITTED 격리 수준으로 변경할 경우 발생할 수 있는 부작용은 무엇이며, 정산 로직에서 어떻게 대응해야 하나요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!