-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Redisson의 분산락을 이용해서 다중 서버 환경에서 데이터 일관성 보장
- Loading branch information
1 parent
7e46c32
commit a789aae
Showing
2 changed files
with
69 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
src/main/java/com/hcommerce/heecommerce/inventory/InventoryCommandRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.hcommerce.heecommerce.inventory; | ||
|
||
import com.hcommerce.heecommerce.common.dao.RedisStringsRepository; | ||
import java.util.concurrent.TimeUnit; | ||
import org.redisson.api.RLock; | ||
import org.redisson.api.RedissonClient; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
public class InventoryCommandRepository { | ||
|
||
private final RedisStringsRepository redisStringsRepository; | ||
|
||
private RedissonClient redissonClient; | ||
|
||
@Autowired | ||
public InventoryCommandRepository(RedisStringsRepository redisStringsRepository) { | ||
this.redisStringsRepository = redisStringsRepository; | ||
} | ||
|
||
public int decreaseByAmount(String key, int amount) { | ||
/** | ||
* TODO : Lock 로직을 Service에서 처리할 지, Repository에서 처리할지 고민 | ||
* TODO : 분산락을 다른 곳에서도 사용할 경우(예 : 결제가 실패하여 재고량 다시 원상복귀할 때)라면 AOP로 만들어도 될 것 같다는 생각이 든다. | ||
*/ | ||
RLock lock = redissonClient.getLock(key); | ||
|
||
try { | ||
// TODO : 일단, 10초 동안 락을 얻으려는 시도하고, 락을 얻기 위해 최대 1초까지 대기한다. -> 이런 수치는 어떻게 정하면 좋을까? 타임 설정 다시 생각해보기 | ||
boolean available = lock.tryLock(10, 1, TimeUnit.SECONDS); | ||
|
||
if (!available) { | ||
System.out.println("lock 획득 실패"); // TODO : logger 의논 후 수정하기 | ||
return -999; | ||
} | ||
|
||
return (int) redisStringsRepository.decreaseByAmount(key, Long.valueOf(amount)); // TODO : 결제가 실패하여 재고량 다시 원상복귀해야할 때도, 분산락 걸어줘야 되나? | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException(e); // TODO : 예외 처리 어떻게 할까? 언제 예외가 터지지? | ||
} finally { | ||
if (lock != null && lock.isLocked()) { | ||
lock.unlock(); | ||
} | ||
} | ||
} | ||
|
||
public int increaseByAmount(String key, int amount) { | ||
RLock lock = redissonClient.getLock(key); | ||
|
||
try { | ||
boolean available = lock.tryLock(10, 1, TimeUnit.SECONDS); | ||
|
||
if (!available) { | ||
System.out.println("lock 획득 실패"); // TODO : logger 의논 후 수정하기 | ||
return -999; | ||
} | ||
|
||
return (int) redisStringsRepository.increaseByAmount(key, Long.valueOf(amount)); | ||
} catch (InterruptedException e) { | ||
throw new RuntimeException(e); | ||
} finally { | ||
if (lock != null && lock.isLocked()) { | ||
lock.unlock(); | ||
} | ||
} | ||
} | ||
} |