1. 동시성 제어 (Concurrency Control)
: 여러 사용자가 동시에 데이터에 접근하거나 조작할 때 발생할 수 있는 문제를 방지하기 위한 기술
- 동시성 제어를 하지 않으면
- 같은 데이터를 동시에 읽거나 수정할 때 데이터 정합성이 깨짐
- 중복 처리, 데이터 충돌, 무결성 오류함
- 예 : 여러 사용자가 동시에 같은 열차 좌석을 예매하는 경우, 중복 예약이 발생함
- 주요 방법
- 낙관적 락 (Optimistic Lock) : 충돌이 드물다고 가정하고, 마지막에 변경 여부 확인
- 비관적 락 (Pessimistic Lock) : 충돌 가능성이 크다고 보고, 먼저 락을 걸고 작업 수행
- 분산 락 : 여러 서버/인스턴스 환경에서 락을 제어
2. 낙관적 락 (Optimistic Lock)
- 데이터 충돌이 거의 없을 것이라고 낙관적으로 가정하고 락을 사용하지 않음
- 대신, 데이터를 읽은 시점과 수정 시점 사이에 다른 트랜잭션이 해당 데이터를 변경했는지 확인하여 충돌 감지
- 동작 방식
- 데이터를 읽을 때, 버전 번호(version)를 함께 읽음
- 업데이트 시점에 해당 버전 번호가 변하지 않았으면 정상 처리
- 바뀌었다면 OptimisticLockException 발생, 트랜젝션 롤백
- 성능이 좋고 데드락 없음!
- 충돌 시, 재시도 로직 필요함
- 읽기 위주의 시스템. 충돌 가능성이 낮은 경우에 적합
- JPA에서 사용 방법 : @version 필드를 이용하여 DB에서 충돌 여부 감지
// 엔티티에 버전 필드 추가
@Version
private Long version;
3. 비관적 락 (Pessimistic Lock)
- 충돌이 자주 발생한다고 비관적으로 가정하고, 조회 시점부터 락을 걸어 다른 트랜젝션의 접근을 차단
- 동작 방식
- 데이터를 조회할 떄, DB 레벨 락(SELECT --- FOR UPDATE)을 걸어 다른 트랜젝션의 읽기/쓰기 차단
- 락을 획득한 트랜잭션만 데이터 수정 가능
- 장점 : 데이터 정합성 보장됨!!!
- 단점 : 데드락 위험, 트랜잭션 병목 발생 가능
- 충돌 가능성이 높은 경우, 반드시 정합성이 보장되어야 하는 경우에 적합
- JPA에서 사용 방법 : SELECT --- FOR UPDATE와 같은 SQL로 DB의 row-level에 직접 락을 설정
// Repository에 명시
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT p FROM Product p WHERE p.id = :id")
Product findByIdForUpdate(@Param("id") Long id);
- JPA의 비관적 락 모드 종류
- PESSIMISTIC_READ
- 읽기 락. 다른 트랜잭션의 쓰기만 막음. (읽기는 허용)
- 사용 목적 : 읽기 작업 중 데이터 수정 방지
- 쿼리 예시 : SELECT ... FOR SHARE
- PESSIMISTIC_WRITE
- 쓰기 락. 다른 트랜잭션의 읽기/쓰기 모두 차단
- 사용 목적 : 정합성이 꼭 필요한 경우
- 쿼리 예시 : SELECT ... FOR UPDATE
- PESSIMISTIC_FORCE_INCREMENT
- PESSIMISTIC_WRITE와 같지만, 버전 필드 자동 증가
- 사용 목적 : 낙관적 락과 비관적 락을 혼합해 쓰고 싶을 때
- 쿼리 예시 : SELECT ... FOR UPDATE + version++
- PESSIMISTIC_READ
4. 분산 락 (Distributed Lock) - Redis 기반
- 여러 서버 인스턴스 환경에서 공유 자원을 제어할 때, 중앙 락 저장소(예:redis)를 통해 락을 설정하고 해제하는 방식
- 동작 방식
- Redis에 SETNX + EXPIRE 방식으로 락 key 생성
- 락이 존재하면 다른 트랜젝션은 대기 또는 실패
- 처리 완료 후 key 삭제로 락 해제
- 장점 : 분산 시스템에서 자원 충돌 방지
- 서버가 여러 대일 때, 중앙에서 락 제어 가능
- TTL 설정 및 락 해제시 본인이 설정한 락인지 확인하는 로직 필요
- Redis 외에도 Zookeeper, DB를 이용한 분산락 가능
- Redisson 등의 라이브러리를 사용하면 재시도, Watchdog 기능 등 내장 지원
LIST
'👩🏻💻TIL (Today I Learn) > Redis' 카테고리의 다른 글
| 🔔 Redis는 싱글스레드인데 왜 이렇게 빠를까? (3) | 2025.08.07 |
|---|---|
| 블로킹/비블로킹, 동기/비동기 관점에서 본 Redis 메시지 큐 (3) | 2025.08.06 |
| [JWT] 🔐Redis를 활용한 로그아웃 및 블랙리스트 처리 (5) | 2025.07.30 |