Skip to content

Commit

Permalink
InventoryCommandRepository 추가
Browse files Browse the repository at this point in the history
- Redisson의 분산락을 이용해서 다중 서버 환경에서 데이터 일관성 보장
  • Loading branch information
daadaadaah committed Jun 12, 2023
1 parent 7e46c32 commit a789aae
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'mysql:mysql-connector-java:8.0.22'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.redisson:redisson-spring-boot-starter:3.21.3'
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
Expand Down
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();
}
}
}
}

0 comments on commit a789aae

Please sign in to comment.