RDB를 분산락으로 사용하기

다음과 같은 애플리케이션을 만족해야하는 기능 구현을 해야되는 상황

  • 애플리케이션이 1분 간격으로 작업을 실행
  • 애플리케이션 프로세스는 여러 노드에서 실행됨
  • 동시에 여러 스레드가 작업을 실행하면 데이터에 문제가 발생함 즉, 동시에 두개 이상 프로세스가 실행 되더라두 그중 하나의 프로세스, 하나의 스레드만 작업을 실행해야만하는것.

이러한 요구 충족하려면 분산 잠금이 필요.

레디스나 주키퍼같은 기술을 사용할 수도 있지만 구조를 단순히 유지하고 싶었음. 그래서 분산 잠금 수단으로 DB를 사용.

이 부록에서는 일정 시간 잠금을 소유하는 방식의 분산 잠금을 DB로 구현해본다.

분산 잠금 동작

분산 잠금이 필요한 스레드는 다음 절차에 따라 잠금을 획득한다.

  1. 트랜잭션 획득
  2. 선점 잠금 쿼리(for update)를 이용해 해당 행 점유한다.
  3. 행이 없으면 잠금 테이블에 새로운 데이터 추가한다.
  4. owner가 다른데 아직 expiry가 지나지 않았다면 잠금 획득에 실패
  5. owner가 다른데 expiry가 지났다면, owner와 expiry 값을 변경한 후 잠금을 획득
  6. owner가 같다면 expiry만 갱신한 후 잠금을 획득한다.
  7. 트랜잭션을 커밋하고 소유 결과를 리턴
  8. 트랜잭션 커밋에 실패하면 잠금 획득 실패한다.

이 절차에 따라 잠금 소유에 성공했다면 원하는 기능 실행하고, 실패했다면 기능을 실행하지 않도록 구현한다.

잠금 정보 저장 테이블

분산 잠금 구현 위한 테이블 스키마

CREATE TABLE dist_lock
	name varchar(100),
	owner varchar(100),
	expiry timestamp
  • name: 개별 잠금 구분위한 주키
  • owner: 잠금 소유가 구분 위한 키. 여러 스레드가 같은 이름의 잠금을 시도할 때 충돌을 처리한다.
  • expiry: 잠금 소유 만료 시간으로, 한 소유자가 오랜 시간 잠금을 소유하지 못하도록 한다.