코딩과 결혼합니다

[Game-Crew] 트러블 슈팅 : 로컬에 Embedded Redis 적용(Chche, Redis) 본문

코딩과 매일매일♥/Game_Crew

[Game-Crew] 트러블 슈팅 : 로컬에 Embedded Redis 적용(Chche, Redis)

코딩러버 2024. 1. 12. 16:42
728x90

배경

특정 유저의 프로필 조회 또는 평점 등록과 같은 반복되는 요청이 자주 발생하는 경우, 캐싱 기능을 활용하여 더 빠른 응답 속도를 제공하고자 Redis를 도입하기로 결정하였다.

Embedded Redis는 로컬 개발 환경에서 Redis를 쉽게 실행할 수 있도록 해준다. 외부 Redis를 설치하고 구성할 필요 없이 애플리케이션 내에서 실행할 수 있다는 점에서 이를 사용하기로 하였다.

 

레디스 종속성 추가

//Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation group: 'it.ozimov', name: 'embedded-redis', version: '0.7.2'
testImplementation 'it.ozimov:embedded-redis:0.7.2'

 

Cache

데이터나 결과를 임시로 저장하는 메모리 또는 저장소. 일반적으로 데이터에 빠르게 접근하기 위해 사용된다.

  • Look-aside
    • 캐시와 원본 데이터 소스 사이에 위치하여 데이터 액세스를 관리하는 방식
    • 데이터를 캐시로 직접 요청하기 전에 먼저 캐시에 해당 데이터가 있는지 확인한다. 없으면 원본 데이터 소스에서 데이터를 가져와 캐시에 저장한다.
    • 데이터의 일관성을 유지하기 위해 적절한 관리 전략을 세워야 한다.
      예를 들어 사용자 정보가 업데이트되었을 때 해당 정보를 캐시에서 제거하거나 갱신하도록 한다.
  • Write-through
    • 데이터를 캐시에 저장하는 동시에 원본 데이터 소스에도 즉시 저장하는 방식
    • 데이터의 일관성을 유지하고 데이터 손실의 위험을 줄일 수 있다.
    • 원본 데이터 소스에 대한 액세스가 필요하기 때문에 쓰기 작업이 느릴 수 있다.
  • Write-back
    • 데이터를 캐시에만 저장하고, 변경된 데이터를 나중에 원본 데이터 소스에 업데이트하는 방식
    • 원본 데이터 소스에 대한 액세스 횟수를 줄여 성능 향상
    • 일관성 유지를 위한 적절한 관리 절약 필요. 주로 읽기 작업이 많은 시스템에서 사용된다.
  • Write-around
    • 쓰기 작업을 캐시를 거치지 않고 바로 원본 데이터 소스에 기록하는 방식
    • 쓰기 작업에 대한 지연 시간과 캐시 부하를 줄일 수 있다.
    • 쓰기 작업을 읽기 작업보다 자주 하는 경우 캐시의 효과를 제한할 수 있다.
  • Write-invaidate
    • 쓰기 작업이 발생하면 해당 데이터를 캐시에서 무효화하는 방식
    • 일관성을 유지하면서 쓰기 작업의 지연 시간을 줄일 수 있다.
    • 읽기 작업에서 캐시 미스가 자주 발생할 수 있어 성능 저하를 초래할 수 있다.

캐시의 대상이 되는 정보들

  • 데이터 베이스 쿼리 결과
    • 쿼리의 결과를 캐시에 저장하여 동일한 쿼리가 반복되는 경우
    • 액세스 비용을 줄이고 응답 시간 개선
  • 외부 API 응답
    • 외부 API를 호출하여 받은 응답 데이터를 캐시에 저장하여 동일한 요청이 발생할 때
    • 외부 API 호출 비용을 줄이고 응답 시간 단축
  • 계산 결과
    • 복잡한 계산의 결과를 캐시에 저장하여 동일한 계산이 반복되는 경우
    • 계산 비용을 줄이고 응답 시간 개선
  • 세션 데이터
    • 사용자의 세션 정보나 인증 토큰과 같은 중요한 데이터를 캐시에 저장하여 매번 데이터베이스나 외부 시스템에 액세스 하지 않도고 빠르게 액세스
    • 인증 및 세션관리를 효율적으로 처리
  • 정적 파일
    • (이미지, css, JS)등을 캐시에 저장하여 반복적인 요청 시에 파일을 다시 생성하지 않고 캐시에서 가져올 수 있다.
    • 웹 페이지의 로딩 속도를 향상하고 서버의 부하를 줄임

Redis

키 - 값 쌍의 해시 맵과 같은 구조를 가진 비관계형 데이터베이스 관리 시스템이다.

별도의 쿼리문을 필요로 하지 않고, 인-메모리에 저장되어 데이터를 빠른 속도로 처리할 수 있다.

 

  • 성능
    • 데이터가 메모리에 저장되어 대시 시간을 낮추고 처리량을 높임. 읽기 및 쓰기의 작업속도가 평균 1ms로 빠르다.
  • 유연한 데이터 구조
    • String, List, Set, Hash, JSON 등 다양한 데이터 타입을 지원한다.
  • 개발 용이성
    • 쿼리문이 필요하지 않으며, 단순한 명령 구조로 데이터 저장, 조회 등이 가능하다.
    • Java, Python, C, C++, C#, JavaScript, PHP, Node.js, Ruby 등 다수의 언어를 지원한다.
  • 영속성
    • 데이터를 디스크에 저장할 수 있으며 서버에 치명적인 문제가 발생하더라도 디스크에 저장된 데이터를 통해 복구가 가능하다.
  • 싱글 스레드 방식
    • 한 번에 하나의 명령어만을 처리. 연산을 원자적으로 처리하여 경쟁 상태가 거의 발생하지 않는다.

사용사례

  • 캐싱
  • 채팅, 메시징 및 대기열
  • 랭킹 보드(순위표)
  • 인증 토큰 저장
  • 다양한 미디어 스트리밍
  • 실시간 분석
  • 위치기반 데이터 타입 사용

Troubleshooting(1)

▪️ compile group: 'it.ozimov', name: 'embedded-redis', version: '0.7.3'을 추가하고 빌드하는데 실패하였다.

//Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
compile group: 'it.ozimov', name: 'embedded-redis', version: '0.7.3
A problem occurred evaluating root project 'GameCrew_project'.
> Could not find method compile() for arguments [{group=it.ozimov, name=embedded-redis, version=0.7.3}] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

 

오류 내용 : compile() 메서드를 찾을 수 없다.

이 오류는 Gradle 버전에 따라 메서드가 변경되었거나 더 이상 사용되지 않는 메소드를 사용하려 했을 때 발생할 수 있다.

나의 gradle 버전은 8.3으로 5.0 이상이다.
compile 메소드 같은 경우에는 5.0 미만인 경우에 사용할 수 있다고 한다.

 

아래처럼 변경하여 해결하였다.

//Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation group: 'it.ozimov', name: 'embedded-redis', version: '0.7.3'
testImplementation 'it.ozimov:embedded-redis:0.7.3'


첫 줄은           | 프로덕션 코드에서 사용되는 라이브러리 추가

두 번째 줄은   |  embedded -redis를 프로덕션 코드에서 사용할 수 있도록 추가

세 번째 줄은   |  테스트 코드에서 embedded -redis를 사용하려 추가한 것이다.

 

 

Troubleshooting(2)

0.7.3 버전을 쓰면 어플리케이션 실행시에 오류가 난다.

Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
SLF4J: Class path contains multiple SLF4J providers.
SLF4J: Found provider [org.slf4j.simple.SimpleServiceProvider@5a4aa2f2]
SLF4J: Found provider [ch.qos.logback.classic.spi.LogbackServiceProvider@6591f517]
SLF4J: See https://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual provider is of type [org.slf4j.simple.SimpleServiceProvider@5a4aa2f2]

 

검색해보니 0.7.3 버전의  호환성 문제로 보여졌다. 0.7.2 버전으로 바꿔주자 정상적으로 앱이 실행되었다.