
은행이나 금융 시스템에서는 사용자의 모든 거래 내역을 즉시 데이터베이스(DB)에 반영할 수 없다.
거래가 발생할 때마다 DB를 업데이트하면 부하가 커지고 성능이 저하될 위험이 있기 때문이다.
그래서 실제 금융 시스템에서는 Redis 같은 캐싱 시스템을 활용하여 임시 저장한 후, 자정에 배치(batch) 처리를 통해 DB에 반영하는 방식이 일반적이다.
해외주식 거래는 국내 주식과 달리 D+2 결제 원칙을 따른다.
즉, 매수 또는 매도 주문이 체결되더라도 2일 후(D+2)에 예수금이 최종 반영된다.
배치 처리 시스템은 매일 밤 12시(00:00) 에 실행되어 D+2일이 된 데이터만 반영한다.
<배치 처리 흐름>
00:00 자정 배치 실행 (applyPendingUpdates())
@Scheduled(cron = "0 0 0 * * ?") // 매일 00:00 실행
public void applyPendingUpdates() {
String today = LocalDate.now().format(DATE_FORMATTER);
Set<String> keys = redisTemplate.keys("user:*:batch_balance:" + today);
if (keys == null || keys.isEmpty()) {
log.info("[배치 처리] 오늘({}) 적용할 예수금 데이터 없음.", today);
return;
}
for (String key : keys) {
String userId = key.split(":")[1]; // Redis 키에서 userId 추출
String balanceStr = redisTemplate.opsForValue().get(key);
String newBalance = balanceStr;
accountRepository.updateAccountWithholding(Long.parseLong(userId), Long.parseLong(newBalance));
log.info("사용자 {} 예수금 DB 업데이트 (D+2 반영): {}", userId, newBalance);
// Redis 사용자 잔고 업데이트
String userBalanceKey = "user:" + userId + ":balance";
redisTemplate.opsForValue().set(userBalanceKey, newBalance, EXPIRATION_DAYS, TimeUnit.DAYS);
log.info("Redis 사용자 {} 실제 예수금 업데이트: {}", userId, newBalance);
log.info("[배치 적용 완료] 사용자ID: {}, 적용 예수금: {}", userId, newBalance);
}
}
체결 후 배치 예수금을 저장할 때, Redis에 D+2 날짜를 포함한 키로 저장!
user:123:batch_balance:2025-03-19 -> "5000000"
user:456:batch_balance:2025-03-19 -> "2500000"
user:123:batch_balance:2025-03-19 → D+2일(2025-03-19)에 500만 원 반영 예정
✔ user:456:batch_balance:2025-03-19 → D+2일(2025-03-19)에 250만 원 반영 예정
D+2 날짜가 포함된 키로 저장하여 배치 실행 시 필요한 데이터만 조회 가능
캐싱을 활용하여 빠른 조회 가능
실제 DB 업데이트가 필요한 시점(D+2)에만 반영하여 부하 감소
문제 1: 배치 실행 후에도 Redis 값이 즉시 반영되지 않음
이슈:
-> 배치가 실행된 후 DB에는 정상 반영되었지만, Redis의 사용자 잔고(user:{userId}:balance)가 갱신되지 않아 사용자가 조회할 때 오래된 값이 보임
해결 방법:
배치 실행 후 DB 업데이트와 동시에 Redis에도 최신 데이터를 반영
String userBalanceKey = "user:" + userId + ":balance";
redisTemplate.opsForValue().set(userBalanceKey, newBalance, EXPIRATION_DAYS, TimeUnit.DAYS);
-> 배치 실행 후 DB & Redis 동시 업데이트하여 사용자 조회 시 최신 예수금 표시
금융 시스템에서 예수금을 실시간으로 DB에 반영하는 것은 비효율적이며, 부하를 줄이기 위해 배치 프로세스가 필수적이다 !