티스토리 뷰

[어떤 Lock을 적용할지 고려하는 순서]

1. DB Transaction과 Lock 범위에 따른 처리를 고려해야 한다.

트랜잭션 시작, 종료 전후로 락을 획득해야 하는지

트랜잭션을 먼저 시작하고 락을 획득해도 되는지 등등

 

2. 낙관적 Lock으로 해소가 가능한가?

먼저 낙관적락으로 해소가 가능한지 확인한다.

낙관적 락이 적합한 경우는

첫 번째 조건 : 수정에 실패했을 때, 해당 비즈니스로직의 실패로 이어져도 되는 경우

두 번째 조건 : 동시에 많은 충돌을 발생시키지 않는 경우(Retry로 해소)

 

3. 비관적 Lock으로 해소가 가능한지?

비관적 락이 적합한 경우는

첫 번쨰 조건 : 작은 트랜잭션 범위 내에서는 빠르게 처리 가능

두 번째 조건 : 반드시 순서대로 처리해야 하는 작업에 효과적

 

주의 : Lock의 잠금 범위에 따라서 성능 차이가 발생할 수 있음. 테이블 전체를 락을 걸어버리면 성능에 큰 이슈가 발생.

 

4. 분산 Lock으로 해소 가능한지?

Redis 등을 활용해서 할 수 있는지?

Redis + DB 여서 관리에 대한 포인트가 더 생긴다. 하지만 DB에 가해지는 직접적인 부하가 낮아지므로

성능 속도면에서 효과적이다.

 

 

[분산락을 사용할 때 발생할 수 있는 문제점]

@Transactional
public void charge(Long userId, BigDecimal point) {
	Boolean accrued = redissonClient.getLock("userChargeLock").tryLock();
	try {
		if(accrued == true) {
			User user = userRepository.findById(userId)
			user.charge(point)
		}
	}
	
}

@Transactional
public void pay(Long userId, BigDecimal point) {
	RLock lock = redissonClient.getLock("userPayLock");
	User user = userRepository.findById(userId)
	user.pay(point)
}

1. userCharge 락, userUse락으로 락을 별개로 한다면 충전과 사용이 동시에 발생할 수 있다.

=> 락은 1개로 걸어야 한다.

2. userPointLock 처럼 테이블 전체에 락이 걸리면 성능이 매우 떨어진다. 우리가 원하는 건 테이블 내의 특정 ID의 포인트에 락을 거는 것.

=> 락의 범위를 잘 설정해야 한다.

 

[배운점]

동시성 제어의 방법은 sychronized, ConcurrentHashMap, 낙관적 락, 비관적 락, Redis 분산 락 등이 있다.

현재 나의 시스템의 특성을 기준으로 동시성 제어방식을 선택해야 한다.

서버가 1개이고 구현을 쉽게하고자 한다면 synchronized를 사용해도 된다. 하지만 서버가 여러대인 경우에는 synchronized로 부족하다.

ConcurrentHashMap을 사용하면 데이터 각각에 락을 걸 수 있기 때문에 더 성능이 좋다. 하지만 이 또한 분산시스템에는 적합하지 않다.

그래서 비관적 락과 낙관적 락이 필요하게 되는데. 이 경우 데이터 수정시 충돌 빈도와 순차처리를 기준으로 선택을 해야 한다.

데이터 수정시 충돌이 많고 모든게 순차적으로 처리되어야 한다면 비관적 락을 사용하는게 맞다. 반면에 데이터 수정시 충돌이 적고, 여러 요청 중에 1건만 성공시켜야 하는 경우 낙관적 락으로 하면 된다. 추가적으로 낙관적 락으로 하는 경우 재시도에 대한 프로그래밍도 고려해야 한다.

그리고 DB에 부하를 줄이기 위해서 Redis 를 활용한 분산락을 사용할 수도 있다. 현재 현업에서 많이 사용되는 방법이다.

 

 

[DB 인덱스]

- 생각보다 인덱스를 모르는 사람이 많다.

- 대체되지 않는 개발자가 되기 위해서는 어떤 인덱스가 필요한지 알아야 하고, 선제안할 수 있어야 한다.인덱

 

 

[인덱스 설정시 고려할 것]

- 카디널리티가 높은 컬럼 => 중복 데이터가 적은 컬럼

- 인덱스 재정렬 최소화 => 데이터 삽익과 수정이 적은 컬럼

- 인덱스 목적은 검색 => 조회에 자주 사용되는 컬럼

- 너무 많지 않은 인덱스(3~4개) - 인덱스도 공간을 차지하기 때문.

 

[이번주 공부해볼 것]

- Like, 

 

[sync Schedule Strategy]

 

[석범 코치님이 추천해준 책]

- 리얼 Mysql 8.0 책 보기 => 석범 코치님 추천

 

[Caching]

 

 

[ Cache Termination Type]

- 인스타그램의 피드의 좋아요 => Expiration 방식이 바람직함

- 이커머스의 인기상품 조회 - 실시간으로 데이터

=> 인기상품 리스트를 만들 때는 일정 주기별로 쿼리를 조회해서 캐시에 넣어놓는다.

 

[석범코치님의 대기열 구현 관련 예상 면접 내용]

1. API는 어떻게 뽑아볼래?

API는 총 4개 정도 생성하면 될 것 같다.

 

2. 대기열 토큰 폴링

Korail 예약할 때 명절에 하면 F12로 보면 폴링방식으로 조회 요청이 계속 날라가는 것을 알 수 있다.

 

[대기열 구현]

- 놀이동산 방식으로 대기열 구현할 떄

왜 몇 초마다 몇 명을 Active 시켜줘야 하는지 근거를 가지고 개발하면 더 좋다.

10초마다 3000명을 대기 인원으로 추가할 수 있는 이유 같은게 있어야 한다.

 

- 대기열을 왜 어떤 선택, 고민으로 구현을 했는지 생각하고 작성해보기

- 설계문서를 작성하는게 중요.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글