같은 시간대에 여러 사용자가 동시에 예약을 시도할 때의 문제점을 해결하기 위해 Redis의 분산 락을 활용했습니다. 분산 락은 동시에 들어오는 예약 요청을 순차적으로 처리하여 데이터 정합성을 보장합니다.
레디스 락 적용코드
Redisson 클라이언트를 사용하여 분산 락을 구현한 코드입니다. 예약 시간대별로 유니크한 키를 생성하여 동시 접근을 제어합니다.
/** * Redis를 활용한 병원 예약 동시성 제어 */ @Slf4j @Component @RequiredArgsConstructor public class RedisLock { private final RedissonClient redissonClient; private final HospitalReservationServiceWithLock hospitalReservationServiceWithLock; /** * 병원 예약에 대한 분산 락 처리 * @param hospId 병원 ID * @param reservationAt 예약 날짜 * @param reservationTime 예약 시간 * @return 예약 처리 결과 */ public String lockReservation(Long hospId, LocalDate reservationAt, LocalTime reservationTime){ // 예약 날짜 형식 변환 (yyyy-MM-dd) DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); String formattedDate = reservationAt.format(formatter); // 예약 시간 형식 변환 (HH:mm) DateTimeFormatter formatterT = DateTimeFormatter.ofPattern("HH:mm"); String formattedTime = reservationTime.format(formatterT); // Redis 락 키 생성 (병원ID:예약날짜:예약시간) String key = hospId + ":" + formattedDate + ":" + formattedTime; RLock lock = redissonClient.getLock(key); try { // 락 획득 시도 (대기시간 10초, 락 유지시간 20초) boolean available = lock.tryLock(10, 20, TimeUnit.SECONDS); if(!available) { throw new RuntimeException(); } return hospitalReservationServiceWithLock.getLock(key); } catch (InterruptedException e) { throw new RuntimeException(e); }finally { // 락 해제 lock.unlock(); } } }
예약 상태 검증 및 처리
분산 락 획득 후, 실제 예약 가능 여부를 검증하고 예약 상태를 관리하는 과정입니다./** * 병원 예약 처리와 검증을 담당하는 서비스 */ @Service @RequiredArgsConstructor public class HospitalReservationServiceWithLock { private final ApplicationLockClient applicationLockClient; /** * 예약 가능 여부 검증 및 상태 저장 * * @param key 예약 키 (병원ID:예약날짜:예약시간) * @return 생성된 Redis 키 * @throws RuntimeException 중복 예약이거나 저장 실패 시 발생 */ public String getLock(String key){ // Redis에서 사용할 키 생성 String redisKey = ApplicationLockClient.createKey(key); // Redis에서 해당 예약 건의 상태 조회 String checkValue = applicationLockClient.findByKey(redisKey); if(checkValue != null){ throw new RuntimeException(); // 이미 예약이 존재하는 경우 } // 예약 진행 상태 저장 applicationLockClient.save(redisKey); // 저장된 상태값 검증 String redisValue = applicationLockClient.findByKey(redisKey); if(!redisValue.equals("pending")) throw new RuntimeException(); // 저장된 상태값이 유효하지 않은 경우 return redisKey; } }
분산 락이 적용된 예약 프로세스
Redis에 저장된 예약 상태
Redis의 분산 락을 활용하여 병원 예약 시스템의 동시성 문제를 효과적으로 해결했습니다. Redisson 클라이언트를 통해 구현된 분산 락은 동일 시간대의 중복 예약을 방지하고, 데이터 정합성을 보장합니다.
예약 시간대별로 유니크한 키를 생성하여 락을 관리하고, 예약 상태를 검증하는 이중 체크 방식으로 안전한 예약 프로세스를 구현했습니다. 실제 서비스에 적용한 결과, 동시 예약 요청에 대해 순차적인 처리가 이루어지며 데이터의 일관성이 유지되는 것을 확인할 수 있었습니다.
이러한 구현은 분산 환경에서도 안정적인 예약 서비스를 제공할 수 있게 해주며, 사용자 경험 저하 없이 시스템의 신뢰성을 향상시킬 수 있었습니다.