inflearn logo
강의

Khóa học

Chia sẻ kiến thức

Cách giải quyết các vấn đề đồng thời bằng hệ thống kiểm kê

단일연산

69

ililil

16 câu hỏi đã được viết

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

 

final Stock stock = stockRepository.getByProductId(productId);
stock.decrease(quantity);
stockRepository.save(stock)

public void decrease(final Long quantity) {
		if (this.quantity - quantity < 0) {
			throw new RuntimeException("재고 부족");
		}

		this.quantity -= quantity;
	}


락을 건 이유는 decrease 로직에서 quantity를 줄이고 다시 저장했기 때문이라 생각했습니다. stock 상태가 코드레벨에서 변하기 때문에 발생하기 때문입니다.

다만 코드레벨에서 변경하지 않고 디비에서 직접 변경한다면(update stock quantity=quantity-1 과 같이) update 자체가 배타락이기 때문에 굳이 락을 걸지 않아도 된다고 판단하였습니다.

그래서 단일 연산으로 해결할 수 없는 상황은 quantity 필드 뿐만 아니라 다른 필드에도 영향이 미칠 때라 생각했습니다. stock 필드에 soft delete 필드 delYn을 추가하고,
코드 상에서 만약 재고가 0이면 delYn=True 로 바꾼다 이런 경우일 것 같은데 제가 생각한게 맞을까요?

단일 연산으로도 정합성을 유지할 수 있는데 왜 stock을 다시 저장하는지 모르겠습니다

java spring 동시성

Câu trả lời 2

0

169developer9973

ililil 님 안녕하세요.
단일 데이터베이스를 사용한다면 말씀해주신대로 디비의 트랜잭션과 쿼리문을 통해 제어를 할 수 있습니다.
다만, update stock quantity = quanity - ? where quantity - ? >= 0 과 같이 where 문이 추가되어야 할 것 같네요.

 

강의에서는 동시성을 제어하는 여러가지 방법을 소개하기 위해 '재고' 라는 예제를 선택한것이고 재고만을 관리하는 로직이라면 말씀하신대로 트랜잭션과 쿼리를 활용하여 제어를 할 수 있습니다.

 

다만, 비즈니스 로직이 복잡해져서 유니크키를 사용할 수 없는상황이거나 다수의 데이터소스를 사용하는경우에 락을 사용할 수 있다고 이해해주시면 좋을것 같습니다.

감사합니다.

0

communityai8509

안녕하세요, 인프런 AI 인턴입니다.

gelab님께서 말씀하신 것처럼, 데이터베이스의 UPDATE 문을 사용하여 단일 연산을 수행하면, 데이터베이스 레벨에서 락을 걸어주기 때문에 동시성 문제를 부분적으로 해결할 수 있습니다. 이는 데이터를 직접적으로 조작하여 트랜잭션의 격리를 통해 동시성을 관리하는 방식입니다.

실제로 UPDATE stock SET quantity = quantity - :quantity WHERE product_id = :productId와 같은 쿼리는 데이터베이스에서의 단일 연산으로, 다수의 트랜잭션이 동시에 같은 데이터를 업데이트 하려고 할 때 자동으로 잠금을 이용하여 동시성 문제를 방지합니다.

하지만, 단일 쿼리가 아닌 경우, 예를 들어 여러 필드의 변경이 필요하거나, 비즈니스 로직이 복잡한 경우, 트랜잭션의 일관성을 위해 객체 상태를 영속 컨텍스트에서 관리한 후 저장해야 할 필요가 있습니다.

또한, 아래와 같은 경우에도 코드에서 객체 상태를 변경 후 저장해야 합니다:
1. 복잡한 비즈니스 로직: 데이터베이스의 단일 연산으로 처리하기 어려운 복잡한 조건 및 비즈니스 로직이 필요한 경우.
2. 다른 필드와의 연관성 및 상태 변경: 업데이트 시 다른 필드나 연관된 엔티티의 상태에도 영향을 미쳐야 하는 경우. 예를 들어, 재고가 0이 될 때 delYn 필드를 true로 설정해야 하는 경우.

관련된 질문들에서 유사한 고민을 다룬 예가 있어, 참고해볼 만한 링크를 제공드립니다:

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

레디선 테스트코드에서 채널이름은 없어도 되는건가요?

0

39

2

낙관적 락을 사용할 떄 차이점

0

118

2

동시성 검증 코드에 관한 문의

0

91

2

낙관적락vs. 레디스락

0

106

2

안녕하세요. 레디슨 질문있습니다..!!

0

65

2

@Lock(OPTIMISTIC)이 필요한 이유

0

88

2

get_lock 의 timeout이 3000초 이던데 너무 긴거 아닌가요?

0

128

2

DataSource Hikari 사용 이유

0

144

2

saveAndFlush 사용 이유 문의

0

111

3

비관적 락 VS 네임드 락

0

158

3

application.yaml 에 redis 정보

0

99

2

왜 클래스 이름에 Facade 가 붙나요?

0

181

2

@Transactional 으로 인한 동시성 문제 발생 원인이 궁금합니다.

0

217

2

@modifying 이용한 동시성 제어

0

167

2

DB락과 분산락

0

260

2

NamedLock 테스트 실패

0

186

2

테스트에서 트랜잭션 어노테이션 질문 있습니다.

0

171

2

optimistic Lock 재시도 질문입니다.

0

229

2

낙관적 락 테스트 실패

0

239

2

오류?

0

1624

4

LettureLockStockFacadeTest에서 오류가 발생합니다.

1

267

2

Pessimistic Lock 전체 테스트 오류 문의

0

357

3

비관적 락 vs 레디스(Lettuce)락 비교 관련 질문

0

458

2

낙관적락 vs 네임드락

0

386

2