-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature : redis 락 구현 #139
feature : redis 락 구현 #139
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
거의 질문만 남긴 것 같아요! 고생했어요 달리~~~~ 멋진 코드네요
/** | ||
* 이 어노테이션은 서비스단에서 락대상을 정하는 메서드입니다. | ||
* 해당 메서드에서 조회하는 모든 키에 대해 Lock을 거는 것이 아닌 특정 key에만 설정해줍니다. | ||
* 또한 이 Lock이 어노테이션이 없는 대상은 해당 자원에 접근할 수 있습니다. | ||
* 이 어노테이션은 이 어노테이션을 사용하는 메서드끼리만의 자원 접근을 막을 수 있습니다. | ||
* <p> | ||
* 이 어노테이션을 사용하는 메서드는 꼭 @RedisLockTarget을 사용하여 잠금 대상을 지정해주어야 합니다. | ||
* <p> | ||
* 작성자: waterricecake | ||
* <p> | ||
* 수정일시 : 20241021 | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Java Doc 야무지게 쓰시네 ;;
@Target(ElementType.PARAMETER) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface RedisLockTarget { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이것도 뭔가 JavaDoc으로 링크를 걸어준다거나, 그런 식으로 해주면 좋을 것 같아요. 제 기억으로는 @link인가 있었던 것 같은데
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public static final int WAIT_TIME = 5; | ||
public static final int LEASE_TIME = 15; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 변수들 Public으로 풀어놓은 것은 일부로 그러신건가요?
Aspect는 정말 Aspect하게만 동작해야한다고 생각해서 클래스 자체도 public으로 접근제어자를 설정하지 않고 default로 설정하는 방향도 좋은 것 같다고 생각하기 때문에 이도, public이 아니라 private으로 닫아놓는 것이 더 좋다고 생각하는데 어떻게 생각하세요? (물론 정확하지는 않지만, 클래스 접근제어자를 default로 설정하면 같은 패키지만 아니면 짜피 접근 못할 것 같긴합니다.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아... 실수.... 진짜로..... 실수..... 못봤....어요...
저도 매튜랑 마찬가지로 Aspect가 횡단 관심사 분리인 만큼 private으로 닫아놓아서 분리를 해야한다고 생각합니다.
return parsingToKeyList(redisLock.key(), args[i].toString()); | ||
} | ||
} | ||
throw new ServerException(ExceptionCode.LOCK_CODE_EXCEPTION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception 야무지네요. 어떤 Exception이 발생하는지도, Java Doc에다가 작성하면 더 좋을 것 같네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혹시 각 Exception에 어떤 상황인지 Java Doc을 작성하자는 말씀일까요? 아니면 해당 클래스인 RedisLockAspect
에 작성하자는 의미일까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RedisLock 어노테이션에요! 그냥 대충 redisLockTarget 어노테이션 안달면 해당 익셉션 터진다 이런식으로?? 지금 걸으면서 작성하고 있어서 어노테이션 명은 정확히지 않을 수 있지만 의미는 전달 되었다고 생각합니당
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boolean isLocked; | ||
|
||
try { | ||
isLocked = multiLock.tryLock(WAIT_TIME, LEASE_TIME, TimeUnit.SECONDS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
신기하네요 isLocked를 두는게 마치 뭔가 상호배제 알고리즘을 직접 구현하는 느낌이네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저도 OS 스터디 하던거 생각나더라고요 ㅋㅋ
다만 차이점이 있다면 isLocked가 true가 될때까지 while을 돌리는 것과 다르게 pub/sub 구조로 대기를 받더라고요.
isLocked = false가 되는 경우는 pub/sub을 위한 요청 제한 시간 (WAIT_TIIME)이나 전체 요청 제한 시간 (LEASE_TIME)입니다. multiLock 전체가 성공하기 위해서 이렇게 구현했습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 찾아보지는 않아서 예상만했는데 맞았군요! 굳굳
try { | ||
return proceedingJoinPoint.proceed(); | ||
} finally { | ||
multiLock.unlock(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 finally에 접근하는 시점은 언제인가요? 모든 proceed가 끝난 이후 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
옙! proceed 끝난 이후에 unlock 이 실행됩니다. finally를 한 이유는 본래 메서드에서 실패하여도 unlock을 진행하기 위해서입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
락해제 시점도 되게 중요한 것 같아서 여쭤봤더영
@RedisLock(key = "lobby") | ||
public void join(@RedisLockTarget final String code, final String name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사용하는 부분이 멋지군요 ;;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생했어 👍
* <p> | ||
* 작성자: waterricecake | ||
* <p> | ||
* 수정일시 : 20241021 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
학교 홈페이지 코드 뜯어보면 이런거 있던데
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅋㅋㅋㅋ
close #138
구현과정
Redisson으로 구현하였습니다.
또한 AOP 로 분리하여 해당 메서드에서 lock을 걸고 싶은 자원을 설정해주어야 합니다.
이렇게 할경우
lobby:code 라는 잠금을 얻게 됩니다. 따라서 lobby:code라는 잠금을 획득하기 위해서는 이 잠금이 해재될때까지 대기하게 됩니다.
단점은 이 lock을 사용하지 않는 경우에는 lock에 안걸리고 걍 접근할 수 있다입니다.
근데 이 부분은 redis의 장점을 위해서라도 모든 자원에 락을 걸지않고 꼭 필요한 동시성 이슈가 발생할 수 있는 부분에서만 거는 것이 맞지 않을까하여 이렇게 구현하였습니다.
또한 한 트랜젝션에서 여러 락을 얻고 싶을 수 도 있으니
RedisLock
의 key를 배열로 받아 처리하도록 하였습니다.구현 참고