Redis 분산 락(Lettuce, Redisson)

.·2024년 10월 21일
0

DB

목록 보기
2/2

1. 분산 락이란?

  • 분산 시스템 환경에서 여러 프로세스나 서버가 같은 리소스에 동시에 접근하지 않도록 제어하는 메커니즘
  • 분산 락을 사용하면 각 노드가 동일한 리소스를 사용할 수 있도록 순서를 관리하고, 자원에 대한 경헙을 제어하여 데이터 무결성을 유지한다.

2. 분산 락 구현 방법

분산 락을 구현하는 대표적인 3가지 방법은 아래와 같다.

💡
  • Zookeeper: Zookeeper는 Apache에서 제공하는 분산 서버 관리시스템으로, 분산 락을 구현하는 데 사용됩니다. Zookeeper는 클러스터 내에서 트리 구조를 사용해 자원을 관리하고, 노드 간의 동기화를 보장하는 기능을 제공합니다. 하지만 설정이 복잡하고 성능이 다소 느릴 수 있습니다.
  • MySQL: MySQL의 GET_LOCK() 같은 함수로 분산 락을 구현할 수 있습니다. 트랜잭션이 자원을 사용할 때 락을 걸고, 락 해제 시 자원이 해제되는 방식입니다. 하지만 MySQL은 데이터베이스 락이므로 인메모리 방식의 Redis에 비해 성능이 느리고 대규모 트래픽 처리에 적합하지 않을 수 있습니다.
  • Redis: Redis는 인메모리 데이터 저장소로, 매우 빠른 속도와 간단한 락 메커니즘 구현을 제공합니다. 싱글스레드 방식으로 동시성 문제를 해결하고 분산 환경에서 성능과 확장성 측면에서 유리합니다.

3가지 방법 중 Redis를 소개할건데 그 이유는 무엇보다도 빠른 성능과 확장성 때문이다. Redis는 인메모리 데이터 저장소로 더 빠른 속도를 제공하며 비교적 간단하게 락을 구현할 수 있기 때문에 대규모 트래픽을 처리하는 시스템에서 더 효율적인 선택입니다.

3. Redis 분산 락의 기본 개념

Redis에서 분산 락을 구현하는 방법은 주로 SETNX (SET if Not eXists) 명령어와 EXPIRE 명령어를 조합하는 방식이다.

1. 락 설정: SETNX 명령어를 사용하여 특정 키에 값을 설정합니다. 이 명령어는 해당 키가 존재하지 않을 때만 값을 설정하므로, 여러 프로세스 중 하나만 성공적으로 락을 획득할 수 있습니다.

2. 락 시간 설정: 락이 영원히 유지되지 않도록 EXPIRE 명령어를 사용해 TTL(Time To Live, 유효 시간)을 설정합니다. 이는 락이 과도하게 길게 유지되어 자원이 블로킹되지 않도록 방지합니다.

3. 락 해제: 락을 점유한 프로세스가 작업을 완료한 후 DEL 명령어로 해당 키를 삭제해 락을 해제합니다.

4. Java 환경에서 사용할 수 있는 레디스 클라이언트

Java 환경에서 Redis와 통신할 수 있는 대표적인 클라이언트는 LettuceRedisson입니다. 두 클라이언트를 통해 분산 락을 구현할 수 있습니다.

1. Lettuce

Lettuce는 비동기 Redis 클라이언트로, 빠른 성능을 자랑하며 스핀락(spin-lock) 방식으로 락을 구현할 수 있습니다. 스핀락은 락을 얻기 위해 계속해서 반복적으로 시도하는 방식으로, 락을 얻기 전까지 CPU를 지속적으로 사용하게 됩니다.

    public boolean acquireLock(String lockKey, long expireTime) {
        while (true) { // 스핀락: 락이 설정될 때까지 계속 시도
            if (commands.setnx(lockKey, "1")) {
                // TTL 설정: 락이 만료되면 자동으로 해제됨
                commands.expire(lockKey, expireTime);
                return true; // 락 획득 성공
            }

            try {
                // 락을 획득하지 못한 경우 잠시 대기 후 재시도
                Thread.sleep(100); // 100ms 대기 후 재시도
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void releaseLock(String lockKey) {
        commands.del(lockKey); // 락 해제
    }

    public static void main(String[] args) {
        LettuceSpinLock spinLock = new LettuceSpinLock();

        // 락 획득 시도
        if (spinLock.acquireLock("lock_key", 10)) {
            try {
                // 락을 획득한 후 안전하게 작업 수행
                System.out.println("작업 수행 중...");
                // 작업이 완료되면 락 해제
            } finally {
                spinLock.releaseLock("lock_key");
                System.out.println("락 해제 완료");
            }
        }
    }

Lettuce 스핀락의 특징:

  • 장점: 단순하고 빠른 구현이 가능하며 락을 지속적으로 재시도하여 즉시 반응이 가능합니다.
  • 단점: 락을 얻기 전까지 지속적으로 반복하므로 CPU 사용량이 높고 네트워크 트래픽이 증가할 수 있습니다.

2. Redisson

Redisson은 Redis를 활용한 고급 자바 클라이언트로 Redlock 알고리즘을 공식적으로 지원합니다. Redisson은 Redis의 Pub/Sub 메커니즘을 사용해 락을 관리하며 더 효율적이고 자원 소모가 적은 방식으로 락을 제어할 수 있습니다. 또한 분산 환경에서의 락 관리에 최적화되어 있으며 Java에서 쉽게 사용할 수 있는 다양한 분산 데이터 구조를 제공합니다.

Pub/Sub 메커니즘발행(Publish)구독(Subscribe) 방식으로 메시지를 주고받는 통신 방법입니다.

  • Publisher는 메시지를 발행하고,
  • Subscriber는 특정 주제를 구독하여 발행된 메시지를 받습니다.

이 메커니즘은 비동기적으로 동작하며, 발행자는 구독자 수나 상태를 신경 쓰지 않고 메시지를 보내고, 구독자는 자신이 구독한 주제에 대해 새 메시지가 오면 그때 받습니다.

Redis에서는 이 방식으로 클라이언트 간의 이벤트(예: 락 해제)를 전달할 때 사용됩니다.

    public static void main(String[] args) throws InterruptedException {
        // Redisson 클라이언트 설정
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);

        // RLock 객체를 통해 락 제어
        RLock lock = redisson.getLock("lock_key");

        try {
            // 락을 최대 10초 동안 대기하고, 30초 동안 점유
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                System.out.println("락 획득 성공. 작업 수행 중...");
                // 안전하게 작업 수행
            }
        } finally {
            lock.unlock(); // 락 해제
            System.out.println("락 해제 완료");
        }

        // Redisson 클라이언트 종료
        redisson.shutdown();
    }

Redisson의 특징:

  • 장점: Pub/Sub 메커니즘을 통해 락 해제 이벤트를 구독하여 CPU와 네트워크 자원을 절약할 수 있습니다. 여러 Redis 인스턴스에서 분산 락을 관리할 수 있으며, Redlock 알고리즘을 손쉽게 구현할 수 있습니다.
  • 단점: Lettuce에 비해 상대적으로 무거운 클라이언트이지만, 다양한 Redis 기능을 제공해 효율적인 락 관리가 가능합니다.

Lettuce와 Redisson의 차이점 요약

특징LettuceRedisson
락 방식스핀락 방식 (반복적으로 락을 시도)Pub/Sub 방식 (락 해제 이벤트 구독)
성능빠르지만 CPU 사용량이 높음자원 효율적 관리, 안정적
구현 난이도간단하지만 락 해제 관리가 직접 필요Redlock을 자동으로 관리, 더 쉬운 구현
사용 목적단순한 Redis 락 구현에 적합복잡한 분산 락 관리와 분산 시스템에서 적합

Java 환경에서 Redis 클라이언트를 선택할 때, Lettuce는 간단한 락 구현에 적합하지만 CPU 사용량이 높을 수 있습니다. 반면 Redisson은 더 효율적인 락 관리 및 복잡한 분산 시스템에서 유리합니다.

profile
Tech

1개의 댓글

comment-user-thumbnail
2025년 4월 26일

오 레디스 분산락! 유익하네요

답글 달기