Skip to content

rxcats/redisson-lock

Repository files navigation

Getting Started

프로젝트 요구사항

  • 유저의 토너먼트 참여를 위한 그룹 만들기

    • 최대 50명의 유저가 한 그룹에 참여되도록 한다.
  • 요구사항을 만족하기 위해 1 그룹당 최대 50명만 참여가 될 수 있도록 락을 도입

  • 인증은 임시로 Authorization 에 uid (userId) 를 넣어 사용

Redisson Distributed lock

  • https://github.com/redisson/redisson/wiki/8.-Distributed-locks-and-synchronizers
  • pubsub 기능을 사용하여 락이 해제될 때마다 subscribe 하는 클라이언트들에게 락 획득을 시도해도 된다고 알려줍니다.
  • timeout 이 지나면 최종적으로 false 를 반환하고 락 획득에 실패했음을 알려줍니다.
  • Lua Script를 사용하여 command 를 한번에 redis에 전송하여 atomic을 보장하면서 동시에 성능을 높이고 있습니다.

Spinlock

  • 임계 구역에 진입이 불가능할 때 진입이 가능할 때까지 루프를 돌면서 재시도하는 방식으로 구현된 락을 가리킨다

redis command 실행 결과

1642681263.180637 [0 127.0.0.1:2542] "EVAL" "if (redis.call('exists', KEYS[1]) == 0) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);" "1" "TournamentGroup" "30000" "9563f680-0c67-4857-a1c8-45917cbd5bc7:1"
1642681263.180725 [0 lua] "exists" "TournamentGroup"
1642681263.180736 [0 lua] "hincrby" "TournamentGroup" "9563f680-0c67-4857-a1c8-45917cbd5bc7:1" "1"
1642681263.180751 [0 lua] "pexpire" "TournamentGroup" "30000"
1642681263.314685 [0 127.0.0.1:2540] "EVAL" "if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;" "2" "TournamentGroup" "redisson_lock__channel:{TournamentGroup}" "0" "30000" "9563f680-0c67-4857-a1c8-45917cbd5bc7:1"
1642681263.314784 [0 lua] "hexists" "TournamentGroup" "9563f680-0c67-4857-a1c8-45917cbd5bc7:1"
1642681263.314801 [0 lua] "hincrby" "TournamentGroup" "9563f680-0c67-4857-a1c8-45917cbd5bc7:1" "-1"
1642681263.314810 [0 lua] "del" "TournamentGroup"
1642681263.314817 [0 lua] "publish" "redisson_lock__channel:{TournamentGroup}" "0"

redisson lock API

public interface Lock {
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
}

public class LockTest {
    public static void main(String[] args) {
        RLock lock = redissonClient.getLock(name);
        if (lock.tryLock(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
            try {
                // logic
            } catch (Throwable t) {
                // error
            } finally {
                lock.unlock();
            }
        } else {
            throw new IllegalStateException("redisson lock not available");
        }
    }
}

프로젝트 구성 부가설명

  • Redisson 으로 lock 을 간편하게 사용하기 위해 AOP를 도입
  • RedissonLock annotation을 메소드에 설정하게 되면 RedissonLockAdvice AOP 가 동작되도록 설정
  • MySQL 8.0.x 이상 필요

About

redisson 분산락

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published