아키텍처
[엔터프라이즈 애플리케이션 아키텍처 패턴] 16. 오프라인 동시성 패턴 - 낙관적, 비관적 오프라인 잠금
DevHyo
2022. 1. 22. 18:57
[ 낙관적 오프라인 잠금 ]
특징
- 충돌이 감지되면, 트랜잭션을 롤백해 동시 비즈니스 트랜잭션 간의 충돌을 방지한다.
- 한 세션에서 커밋하려는 변경 내용이 다른 세션의 변경 내용과 충돌하지 않는지 확인하는 방법이다.
- 세션 간의 충돌 가능성이 낮다고 간주될 때 사용하는 방법이다.
- 가장 일반적인 구현 방법은 시스템의 각 레코드에 버전 번호를 연결하는 것이다.
- 세션 데이터에 저장된 버전을 레코드 데이터의 현재 버전과 비교하는 것을 의미한다.
- 낙관적 오프라인 잠금을 구현하는 데 있어서 버전 번호 대신 수정 타임스탬프를 사용하는 것은 좋지 않다.
- 시스템 클록은 신뢰할 수 없고, 여러 서버 간에 작업을 조율하는 경우, 더욱 신뢰하기 어렵기 때문이다.
버전 번호를 사용할 때 문제점
- 일관성 없는 읽기의 문제가 해결되지 않는다.
- 방법이 없는 것은 아니지만, 복잡하다. (이와 관련된 내용이 책에 담겨있으니 참고할 것)
낙관적 오프라인 잠금의 단점
- 동시에 여러 명이 접근하는 경우, 한 세션을 제외한 나머지 세션은 작업이 충돌하고, 실패한다.
- 문제는 충돌이 마지막에 감지되기 때문에 사용자가 모든 작업을 마쳤는데, 실패하게 되면 더 이상 시스템을 신뢰할 수 없다는 부분이 있다.
- 충돌이 발생했을 때, 추가적인 프로세스가 필요하다면, Retry 처리와 같은 방법을 사용해야 한다.
[ 비관적 오프라인 잠금 ]
특징
- 동시 세션 간의 충돌 가능성이 높은 경우, 비관적 오프라인 잠금을 사용하는 것이 좋다.
- 사용자의 작업 내용이 버려지는 일이 있어서는 안 된다.
- 충돌이 발생했을 때의 비용 너무 높은 경우에도 해당 잠금을 사용해야 한다.
- 낙관적 오프라인 잠금을 보완하는 방법이며, 반드시 필요할 때만 사용해야 한다.
- 초기에 실패하기 때문에 사용자가 큰 거부감 없이 받아들일 수 있다.
- 잠금 유형 결정, 잠금 관리자 작성, 잠금을 사용할 비즈니스 트랜잭션의 절차를 정의하는 세 단계로 구현한다.
잠금 유형
- 배타적 쓰기 잠금 (Exclusive Write Lock)
- 수정하려는 경우에만 비즈니스 트랜잭션이 잠금을 얻도록 요구한다.
- 데이터 읽기와 관련된 문제는 무시한다.
- 세션이 반드시 최신 데이터를 읽어야 하는 경우가 아니면, 이 전략을 사용해도 충분하다.
- 배타적 읽기 잠금 (Exclusive Read Lock)
- 수정 여부와 관계없이 항상 최신 데이터를 읽어야 하는 경우에 사용한다.
- 시스템 동시성을 심각하게 제한할 가능성이 있다.
- 읽기 / 쓰기 잠금 (Read / Write Lock)
- 배타적 쓰기 잠금 및 배타적 읽기 잠금 유형을 결합해 향상된 동시성을 함께 제공한다.
- 다른 세션이 읽기 잠금을 보유한 레코드에 대해서는 쓰기 잠금을 얻을 수 없다.
- 다른 세션이 쓰기 잠금을 보유한 레코드에 대해서는 읽기 잠금을 얻을 수 없다.
- 동시 읽기 잠금은 허용된다.
- 다수의 읽기 잠금이 허용되므로 시스템 동시성이 향상된다.
잠금 유형을 선택하기 위한 고려 사항
- 시스템의 동시성 극대화
- 비즈니스 요건 충족
- 코드의 복잡성 최소화
- 도메인 모델러와 분석가가 잠금 전략을 이해할 수 있어야 한다는 점
- 도메인 모델에 비관적 오프라인 잠금을 포함하는 방법
- 비효과적인 비관적 오프라인 잠금 전략
- 비즈니스 트랜잭션이 시작할 때, 충돌을 방지하지 못하거나
- 다중 사용자 시스템의 동시성을 저하시키거나
잠금 관리자
- 잠금 관리자의 역할은 잠금 획득 또는 해제하려는 비즈니스 트랜잭션의 요청을 허용 또는 거부하는 것이다.
- 잠금을 소유자로 매핑하는 테이블 이상을 포함해서는 안 된다.
- 간단한 잠금 관리자의 경우, 인 메모리 해시 테이블을 래핑 하거나, 데이터베이스 테이블일 수 있다.
- 어떠한 방식을 사용하든 잠금 테이블은 단 하나여야 한다.
- 클러스터링 된 애플리케이션 서버 환경에서는 데이터베이스 기반 잠금 관리자가 더 적합할 수 있다.
- 잠금은 잠금 관리자에서만 접근할 수 있어야 한다.
- 세션은 잠금 객체가 아닌 잠금 관리자와 상호작용해야 한다.
잠금을 사용할 비즈니스 트랜잭션
- 잠글 대상과 시기, 잠금을 해제할 시기, 잠금을 획득할 수 없을 때의 대처 방법 등을 정의한 프로토콜이 있어야 한다.
- 잠그는 대상은 사용하는 ID 또는 기본 키를 잠그는 것이다.
- 이렇게 해야 로드하기 전에 잠금을 획득할 수 있다.
- 잠금 해제의 경우에는 비즈니스 트랜잭션이 완료되면, 잠금을 해제하는 것이다.
- 잠금을 획득할 수 없을 때의 가장 쉬운 대응은 작업을 취소하는 것이다.
- 초기에 실패하므로 사용자가 큰 거부감 없이 받아들일 수 있다.
비관적 오프라인 잠금 사용 시, 주의 사항
- SELECT FOR UPDATE와 같은 시스템 트랜잭션 잠금 체계는 잠금을 획득할 수 있을 때까지 대기하므로 교착 상태가 발생할 가능성이 있다.
비관적 잠금 관리하는 방법
- 손실된 세션에 대해 시간을 제한하는 방법이 있다.
- Redisson Lock의 경우, Timeout 과 LeaseTime로 시간을 제한한다.
- 애플리케이션 서버에서 관리하는 시간제한 메커니즘을 사용하는 방법도 있다.
참고
- http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9791158390174