레디스 캐시 With 스프링

김파란·2024년 8월 20일

Spring-Library

목록 보기
5/7

대용량 트래픽 처리 경험

  • 대용량 트래픽을 처리하기 위해서 필수적으로 사용기능이 기능이 캐싱이다

먼저 SQL튜닝을 해야 한다

  • 데이터 조회 성능을 개선하는 방법은 다양하다
  1. SQL 튜닝
  2. 캐싱 서버 활용 (Redis 등)
  3. 레플리케이션 (Master/Slave 구조)
  4. 샤딩
  5. DB 스케일업 (CPU, Memory, SSD 등 하드웨어 업그레이드)

위 5가지 중에서 SQL을 먼저 고려해야한다

  • SQL튜닝을 제외한 나머지방법은 추가적인 시스템을 구축해야 한다. 비용이 추가적으로 발생
  • 근본적인 문제를 해결하는 방법은 SQL 튜닝일 가능성이 높다
  • 가장 가성비가 좋은 방법이 SQL 튜닝이다

1. 설정

1). 환경설정

@Configuration
@EnableCaching // Spring Boot의 캐싱 설정을 활성화
public class RedisCacheConfig {
    @Bean
    public CacheManager boardCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
                .defaultCacheConfig()
                // Redis에 Key를 저장할 때 String으로 직렬화(변환)해서 저장
                .serializeKeysWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new StringRedisSerializer()))
                // Redis에 Value를 저장할 때 Json으로 직렬화(변환)해서 저장
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new Jackson2JsonRedisSerializer<Object>(Object.class)
                        )
                )
                // 데이터의 만료기간(TTL) 설정
                .entryTtl(Duration.ofMinutes(1L));

        return RedisCacheManager
                .RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory)
                .cacheDefaults(redisCacheConfiguration)
                .build();
    }
}

2). 캐시등록

  • cacheName: 그냥 캐시 이름을 설정한것 (의미는 없음)
  • key: Redisdp 저장할 key의 이름을 설정
  • cacheManager: 사용할 캐시매니저의 Bean이름을 지정
  • boards:page:1:size:10이라는 키로 등록될 수 있도록 설정
@Service
public class BoardService {

    private BoardRepository boardRepository;
    private Pageable pageable;

    public BoardService(BoardRepository boardRepository) {
        this.boardRepository = boardRepository;
    }

    @Cacheable(cacheNames = "getBoards", key = "'boards:page:' + #page + ':size:' + #size", cacheManager = "boardCacheManager")
    public List<Board> getBoards(int page, int size) {
        Pageable pageable = PageRequest.of(page - 1, size);
        Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable);
        return pageOfBoards.getContent();
    }
}

2. 부하테스트

  • Thorughtpuh: 서비스가 1초당 처리할 수 있는 작업량
  • TPS(Transaction PerSeconds): 단위
  • 1초에 최대 100개의 API 요청을 처리할 수 있다면 Throughput은 100 TPS라고 얘기한다

1). 부하테스트 툴

  • ngrinder, jmeter, ab, locust 등 다양한 툴이 있다
  • 그 중에서 간단하고 빠르게 테스트 해볼 수 있는 툴인 k6를 사용해보겠다
  • k6를 다운받고 js작성한다음
  • k6 run --vus 30 --duration 10ps script.js
    -> 10초 동안 30명의 유저가 요청을 보내는 것처럼 해보겠다
    -> http_reqs를 보면 숫자가 나오는데 뒤에 색깔 연한 숫자를 보면
    -> 1초 그 숫자만큼 처리했다는 소리이다. // 1초 최대 처리숫자
import http from 'k6/http';
import { sleep } from 'k6';

export default function () {
  http.get('http://{EC2 IP 주소}:8080/boards'); // 이 api로 통신을 보낸다는 뜻이다
}

3. ElastiCache

  • 일일이 Redis를 설치하고 세팅하고 관리하면서 확장까지 하려면 신경쓸 게 많다
  • 하지만 ElastiCache를 사용하면 셋팅도 쉽게할 수 있고 확장도 쉽다
  • 모니터링 기능도 제공해주고 장애날 가능성도 훨씬 적기 때문에 사용

1). 클러스터

  • 여러 캐시서버를 어우르는 한 단위의 그룹
  • 하나의 캐시서버를 노드라고 부르는데 여러개의 노드를 합친 그룹을 클러스터라고 한다
  • 클러스터 안에있는 하나 하나는 캐시서버를 뜻하는 거다
  • 하지만 어지간한 트래픽이 발생하는 서비스가 아니면 클러스터 모드까지 쓸 일이 없다

2). 환경설정

spring:
  datasource:
    url: jdbc:mysql://instagram-db.coseefawhrzc.ap-northeast-2.rds.amazonaws.com:3306/mydb
    username: admin
    password: password
  data:
    redis:
      host: [ElastiCache 엔드포인트]
      port: 6379

참고) https://developer-nyong.tistory.com/21

0개의 댓글