Java

[JAVA] Spring Boot 대규모 트래픽 처리 #Redis #Scheduler

TaeHuiLee 2025. 1. 14. 23:47
반응형

1. 🖥️ Spring Boot 대규모 트래픽 처리 방안: Redis, Scheduler

대규모 트래픽 상황에서 데이터를 효율적으로 처리하기 위한 방법중 하나로 RedisdScheduler를 활용한 개발 방법을 정리해 보려 합니다.
Redis에 데이터를 임시 저장하고, 일정 시간 간격으로 DB에 적재하는 방식을 구현합니다. Redis는 빠른 쓰기 작업에 유리하며, 데이터 배치를 통해 DB의 부담을 줄일 수 있습니다.


2. 🚀 로직과 코드 구현

🔹 전체 로직

  1. 데이터 저장
    • 데이터를 Redis의 리스트(List) 구조에 저장합니다.
    • 가장 최근 키에 데이터를 추가하되, 리스트가 3000개 이상일 경우 새로운 키를 생성합니다.
  2. 스케줄링 처리
    • Redis에서 가장 오래된 키부터 데이터를 가져옵니다.
    • 데이터를 DB에 적재하고, 처리된 키는 삭제합니다.
    • 데이터가 3000개 미만이면 추가 데이터를 가져와 배치를 완성합니다.

3️⃣ 구현 코드

1. Redis에 데이터 저장 서비스

@Service
public class RedisDataService {

    private final RedisTemplate<String, String> redisTemplate;

    public RedisDataService(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    public void saveData(String data) {
        // 1. 가장 최근 Key 찾기
        String recentKey = findMostRecentKey();

        // 2. Key의 데이터 개수 확인
        Long size = redisTemplate.opsForList().size(recentKey);

        if (size != null && size < 3000) {
            // 기존 Key에 데이터 저장
            redisTemplate.opsForList().leftPush(recentKey, data);
        } else {
            // 새로운 Key 생성
            String newKey = generateNewKey();
            redisTemplate.opsForList().leftPush(newKey, data);
        }
    }

    private String findMostRecentKey() {
        // Redis Key 조회 후 가장 최근 Key 반환
        Set<String> keys = redisTemplate.keys("data_*");
        return keys.stream().max(String::compareTo).orElse(generateNewKey());
    }

    private String generateNewKey() {
        // 새로운 Key 생성: 현재 시간 + UUID
        return "data_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + "_" + UUID.randomUUID();
    }
}

2. Redis 데이터를 DB로 옮기는 스케줄러

@Service
public class RedisToDbScheduler {

    private final RedisTemplate<String, String> redisTemplate;
    private final DataRepository dataRepository;

    public RedisToDbScheduler(RedisTemplate<String, String> redisTemplate, DataRepository dataRepository) {
        this.redisTemplate = redisTemplate;
        this.dataRepository = dataRepository;
    }

    @Scheduled(fixedRate = 5000) // 5초마다 실행
    public void processRedisKeys() {
        Set<String> keys = redisTemplate.keys("data_*");

        if (keys != null && !keys.isEmpty()) {
            // 가장 오래된 Key 정렬 후 처리
            List<String> sortedKeys = keys.stream().sorted().toList();

            int totalProcessed = 0;
            List<String> batchData = new ArrayList<>();

            for (String key : sortedKeys) {
                // 현재 Key의 데이터 가져오기
                List<String> dataList = redisTemplate.opsForList().range(key, 0, -1);

                if (dataList != null && !dataList.isEmpty()) {
                    batchData.addAll(dataList);
                    totalProcessed += dataList.size();

                    // Key 삭제
                    redisTemplate.delete(key);

                    // 3000개 이상 채워지면 DB에 INSERT 후 종료
                    if (totalProcessed >= 3000) {
                        break;
                    }
                }
            }

            // 배치 INSERT
            if (!batchData.isEmpty()) {
                List<DataEntity> entities = batchData.stream()
                        .map(data -> new DataEntity(data))
                        .collect(Collectors.toList());
                dataRepository.saveAll(entities);
            }
        }
    }
}

4. 🤔장점과 단점

장점

  1. 부하 분산:
    • Redis를 완충 버퍼로 사용해 트래픽 몰림 방지.
    • DB는 3000개 단위로 배치 처리하여 성능 최적화.
  2. 데이터 유실 방지:
    • Redis에 데이터를 저장 후 처리하므로 실시간 데이터 유실 가능성 낮음.
  3. 확장성:
    • Redis Cluster와 함께 사용하면 높은 트래픽도 안정적으로 처리 가능.

단점

  1. Key 관리 복잡성:
    • Key 개수가 많아지면 스케줄러 처리 비용 증가.
  2. 스케줄 주기 조정 필요:
    • 트래픽 상황에 따라 5초 주기가 너무 짧거나 길 수 있음.
  3. Redis 부하:
    • 과도한 트래픽으로 인한 Redis 부하가 발생할 수 있음.
  4. Redis 설정 복잡성
    • Redis의 원자성과 격리성을 보장하기 위해 추가 설정이 필요할 수 도 있음.

개선방안

  1. Kafka 사용
    • 다음 글에서는 Kafka 메시지 큐를 통해 사용해 보다 효율적으로 처리하는 방법을 정리해 보도록 하겠습니다.

5. 💡 정리

  1. Redis 데이터 저장 로직
    • 최근 키 확인 후, 조건에 따라 데이터 저장 또는 새 키 생성.
  2. 스케줄링으로 데이터 처리
    • Redis에서 오래된 데이터를 배치로 가져와 DB에 저장.
  3. Kafka 도입으로 개선
    • 메시지 큐를 통해 트래픽 분산 및 병렬 처리로 성능 최적화.
반응형