Redis와 같은 인메모리 캐시 시스템을 사용해 성능을 개선하는 것은 좋은 접근이지만, Redis의 원자적 연산이 끝난 후 서버가 다운되면 데이터 불일치 문제가 발생할 수 있습니다. 이를 방지하고 성능을 유지하려면 다음과 같은 전략을 고려해볼 수 있습니다:
1. Redis와 데이터베이스 간 이중 확인 (Double Confirmation)
Redis에서 상품 수량을 감소한 후 결제가 성공했을 때, 데이터베이스와 Redis를 싱크하는 작업을 바로 하지 않고, 비동기 이벤트 처리 방식을 사용해 데이터 일관성을 유지합니다.
프로세스:
1. Redis에서 상품 수량 감소 (atomic decrby 사용).
2. 결제 API 호출 후 성공 시, 메시지 큐나 이벤트 스트림(Kafka 등)을 통해 재고 감소 이벤트 발행.
3. 별도의 비동기 작업(또는 다른 마이크로서비스)이 데이터베이스 재고 정보를 업데이트.
이 방식은 시스템이 중간에 실패하더라도 데이터베이스 재고 업데이트가 비동기적으로 이루어지기 때문에 Redis와 데이터베이스 간 데이터 불일치 가능성을 최소화합니다.
2. Redis LUA 스크립트 사용
Redis의 Lua 스크립트를 사용해 복잡한 트랜잭션을 Redis 내에서 원자적으로 처리할 수 있습니다. Lua 스크립트를 사용해 수량 감소와 성공 처리 플래그를 한 번에 처리할 수 있습니다. 이렇게 하면 서버가 죽기 전까지는 트랜잭션의 일관성을 유지할 수 있습니다.
프로세스:
1. Lua 스크립트를 사용해 Redis에서 상품 수량 감소와 트랜잭션 플래그를 설정.
2. 트랜잭션 플래그를 확인 후 결제 API 호출.
3. 결제 성공 시 비동기적으로 DB 싱크.
3. 최종 일관성 모델 채택
Redis와 DB 간의 데이터 불일치를 허용하는 최종 일관성 모델을 고려할 수 있습니다. 즉, 모든 트랜잭션이 반드시 즉시 완전하게 일치할 필요는 없지만, 일정 시간 내에 데이터 싱크가 이루어지는 모델입니다. 이벤트 기반으로 DB와 Redis가 시간차를 두고 동기화될 수 있습니다.
4. SAGA 패턴 적용
분산 트랜잭션을 처리하는 패턴인 SAGA 패턴을 도입할 수 있습니다. 결제와 재고 처리 등 각 단계가 별도의 트랜잭션으로 처리되며, 각 트랜잭션이 실패하면 롤백 처리가 이루어집니다.
프로세스:
1. Redis에서 재고 감소 트랜잭션 시작.
2. 결제 API 성공 시, 데이터베이스에 반영하는 트랜잭션 실행.
3. 각 트랜잭션이 독립적으로 처리되며, 실패 시 보상 트랜잭션 실행(예: Redis 재고 복구).
5. Zookeeper나 Consul을 통한 분산 락
Zookeeper나 Consul 같은 분산 락 시스템을 사용해 상품별로 락을 걸고, 락이 걸린 동안 하나의 트랜잭션만 처리되도록 할 수 있습니다. 하지만 이 방식은 성능에 큰 영향을 미칠 수 있어, 고성능이 필요하지 않거나, 제한적인 경우에만 적합합니다.
---
이 중 이벤트 기반 최종 일관성 모델이나 SAGA 패턴이 현재 상황에 적합할 가능성이 높습니다.
인간시대의 끝이 도래했다.
지피티 말이 맞는지 검증하려면 이해가 필요하고 이해를 하고 있다면 스스로 생각해낼 수 있는 노멀한 해결책임 고로 지피티를 써서 얻을게 별로 없다