반응형
1. 🖥️ Spring Boot 대규모 트래픽 처리 방안: Redis, Scheduler
대규모 트래픽 상황에서 데이터를 효율적으로 처리하기 위한 방법중 하나로 Redisd
와 Scheduler
를 활용한 개발 방법을 정리해 보려 합니다.Redis
에 데이터를 임시 저장하고, 일정 시간 간격으로 DB에 적재하는 방식을 구현합니다. Redis
는 빠른 쓰기 작업에 유리하며, 데이터 배치를 통해 DB의 부담을 줄일 수 있습니다.
2. 🚀 로직과 코드 구현
🔹 전체 로직
- 데이터 저장
- 데이터를 Redis의 리스트(List) 구조에 저장합니다.
- 가장 최근 키에 데이터를 추가하되, 리스트가 3000개 이상일 경우 새로운 키를 생성합니다.
- 스케줄링 처리
- 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. 🤔장점과 단점
장점
- 부하 분산:
Redis
를 완충 버퍼로 사용해 트래픽 몰림 방지.- DB는 3000개 단위로 배치 처리하여 성능 최적화.
- 데이터 유실 방지:
Redis
에 데이터를 저장 후 처리하므로 실시간 데이터 유실 가능성 낮음.
- 확장성:
Redis Cluster
와 함께 사용하면 높은 트래픽도 안정적으로 처리 가능.
단점
Key
관리 복잡성:- Key 개수가 많아지면 스케줄러 처리 비용 증가.
- 스케줄 주기 조정 필요:
- 트래픽 상황에 따라 5초 주기가 너무 짧거나 길 수 있음.
Redis
부하:- 과도한 트래픽으로 인한 Redis 부하가 발생할 수 있음.
Redis
설정 복잡성- Redis의 원자성과 격리성을 보장하기 위해 추가 설정이 필요할 수 도 있음.
개선방안
Kafka
사용- 다음 글에서는 Kafka 메시지 큐를 통해 사용해 보다 효율적으로 처리하는 방법을 정리해 보도록 하겠습니다.
5. 💡 정리
- Redis 데이터 저장 로직
- 최근 키 확인 후, 조건에 따라 데이터 저장 또는 새 키 생성.
- 스케줄링으로 데이터 처리
- Redis에서 오래된 데이터를 배치로 가져와 DB에 저장.
- Kafka 도입으로 개선
- 메시지 큐를 통해 트래픽 분산 및 병렬 처리로 성능 최적화.
반응형
'Java' 카테고리의 다른 글
[JAVA] Spring 테스트 : Mock VS MockBean (2) | 2025.01.13 |
---|---|
[JAVA] Spring을 이용한 테스트 코드 작성 방법 (단위 테스트, 통합 테스트) (0) | 2025.01.11 |
[JAVA] ArrayList vs LinkedList 완벽 정리 (0) | 2024.12.31 |
[JAVA] PriorityQueue 설명 및 사용법 (0) | 2024.12.30 |
[JAVA] Queue와 Deque 무엇이 좋을까? (2) | 2024.12.27 |