Redis 활용 동시성 제어

Ahn yi·2022년 12월 24일
0

java

목록 보기
21/22

Redis 활용 동시성 제어 상황

  • 대용량 데이터 처리하는 동안 JMeter를 활용하여 한 번에 많은 데이터 요청이 들어왔을 경우의 상황 테스트를 진행하였다.
  • 요청이 들어오고 나서 Service단 이후, 데이터에 대한 처리를 하려고 하였지만 error 및 무결성이 훼손되는 상황이 발생하였다.
  • spring.datasource.hikari.maximum-pool-size=5 의 세팅
    • 5개의 connection 허용
    • 한 번의 JMeter 테스트 진행 시에 5개의 요청이 들어오게 된다.

데이터 처리 상황

  • Books 테이블에 count 컬럼(총 수량) 존재
  • 대여 했을 경우에 BookRental 테이블에 book_id / member_id 매핑하여 ROW 생성
  • 반납 시에 해당 ROW 삭제
  • 현재 수량은 Books 테이블의 count에서 BookRental의 book_id 활용하여 파악하여 진행
    • 총 수량 - 해당 도서 대여 수 = 현재 수량

에러 상황

  • 비관적 잠금 활용
    • error : 트랜잭션 DeadLock error가 발생하였다.
      • DeadLock이란 서로 다른 트랜잭션이 서로를 기다리다가 아무 동작도 하지 않는 상태
  • 무결성 훼손 : 수량이 0미만으로 집계되는 경우가 발생하였다.
    • 요청 5개가 동시에 들어오므로 Service단에서 0이상의 수량만 대여 가능하도록 하였지만 DB에 적용되기 전이라 처리가 되지 않았다.

동시성 제어

  • DB 트랜잭션 이전에 요청에 대한 처리를 해야한다고 생각한 후에, Service쪽 코드 수정
  • InMemory인 Redis 활용 및 임계영역 활용으로 결정
    • 추후에 Queue를 활용한 방법 공부 해봐야 할듯....

활용 방법

  • Redis 활용하여 book_id에 해당하는 키 값과 count를 저장
  • 하나의 요청이 들어올 때마다 Redis에서 count 값 조절하여 현재 수량이 0이상이 아닐 경우 예외처리 적용
    • 기존에 요청이 5개씩 들어와서 DB에 접근하는 것과 달리 하나의 요청에서 현재 수량이 0이 되면 다음 요청은 DB에 접근하지 못하게 처리
    • 해당 Redis 활용 method에 synchronized 예약어를 활용하여 5건씩 접근하는 것을 2/3 건씩 나누어 처리
    • 기존 5건씩 Redis 접근 및 기능 수행을 하다가 2건 수행 후, 3건은 요청 초반 현재 수량 0으로 예외처리

	// synchronized 활용 부분
	public synchronized long minusBookCount(long bookId, long bookCount) {

		// 생략
        
        // Redis 활용
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();

        while (stringStringValueOperations.get(bookId + String.valueOf(bookCount)) != null) {
            bookCount--;
            if(bookCount < 1)
                break;
        }

        long LIMIT_TIME = 1000;
        stringStringValueOperations.set(bookId + String.valueOf(bookCount), String.valueOf(bookCount), LIMIT_TIME, TimeUnit.MILLISECONDS);

        return bookCount;
    }

후기

Redis에 대한 활용을 이런 식으로 하게 될 줄 몰랐다. 처음 Redis에 대해 듣기로는 임시 저장정도로만 생각 하였는데 DB접근 전에 활용할 수 있다는 부분 자체를 알게 된 것 자체가 나한테는 가장 큰 도움이 될 거 같다. 물론, 대용량 처리에 있어서 저런 식의 예외처리가 많아지면 속도에서 문제가 발생할 수 있지만 정확도가 우선이라고 생각하였으며, 그게 당연한 거라고 생각한다. 그런 와중에 synchronized를 활용하여 최대한 나름대로 최대한의 성능 개선을 했다는 점에서도 만족스러운 경험이었다.

profile
소통을 잘하고싶은 백엔드 개발자

0개의 댓글