본문 바로가기

학습 기록 (Learning Logs)/CS Study

[Note]In-memory cache-basic

 

 


공통 질문

1. 인메모리 캐시란 무엇인가요?
2. 캐시가 필요한 이유는 무엇인가요?
3. 캐시와 데이터베이스의 차이는 무엇인가요?
4. 인메모리 캐시에서 사용하는 주요 도구는 무엇인가요?
5. 캐시 적중률(Cache Hit Ratio)이란 무엇인가요?
6. 캐싱 전략에는 어떤 것들이 있나요?
7. 캐시 무효화(Cache Invalidation)는 무엇이며, 왜 중요한가요?
8. TTL(Time-To-Live)이란 무엇인가요?
9. 캐시를 사용할 때 발생할 수 있는 문제점은 무엇인가요?
10. Redis와 Memcached의 차이점은 무엇인가요?
11. LRU 캐싱이란 무엇인가요?

 


1. 인메모리 캐시란 무엇인가요?

인메모리 캐시는 데이터를 디스크가 아닌 메모리(RAM)에 저장하여 데이터를 빠르게 읽고 쓸 수 있도록 하는 저장소입니다.

데이터베이스나 디스크보다 훨씬 빠른 액세스 속도를 제공하며, 애플리케이션의 성능을 크게 향상시킵니다.

  • 예: Redis, Memcached, Ehcache 등.

 

 

Redis는 캐시 메모리를 사용합니다.
즉, 메인 메모리(RAM) 위에서 동작하며 데이터를 저장하고 관리합니다.

Redis는 데이터를 디스크에 저장하는 보조 기억장치(HDD, SSD)도 지원하지만,

본질적으로 인메모리 데이터 저장소로 설계되었습니다. 

1. 레지스터

  • CPU 내부에 있는 가장 빠른 저장 공간.
  • 크기가 매우 작으며, 명령어나 데이터의 임시 저장에 사용.
  • Redis와는 관련이 없음.

2. 캐시 메모리

  • CPU와 메인 메모리(RAM) 사이에서 데이터 접근 속도를 높이기 위해 사용되는 고속 메모리.
  • 보통 CPU 내부 또는 가까운 위치에 위치하여 데이터 접근 시간을 줄임.
  • Redis와는 직접적인 관련이 없음, 하지만 캐싱의 개념은 Redis에서도 활용됩니다.

3. 메모리 (RAM)

  • Redis는 주로 메인 메모리(RAM)를 사용합니다.
    • Redis의 데이터는 메모리(RAM)에 저장되며, 이로 인해 읽기/쓰기 작업이 매우 빠릅니다.
    • RAM에 데이터를 저장하기 때문에 데이터를 관리하거나 읽어오는 속도가 디스크(HDD/SSD)에 비해 월등히 빠릅니다.
  • Redis의 핵심 동작 방식은 RAM에서 데이터를 관리하는 것이며, 이를 통해 캐시 시스템으로 널리 사용됩니다.

4. 보조 기억장치 (HDD, SSD)

  • Redis는 보조 기억장치(HDD, SSD)를 선택적으로 사용합니다.
    • Redis는 기본적으로 RAM에 데이터를 저장하지만, 데이터를 영속성 있게 유지하기 위해 RDB(Snapshot) 또는 **AOF(Append Only File)**를 사용하여 데이터를 디스크에 저장할 수 있습니다.
    • 디스크를 사용하는 기능은 데이터 영속성을 보장하기 위한 것이며, 캐싱 목적보다는 데이터 복구를 위해 사용됩니다.

Redis의 디스크 기반 저장 옵션:

  1. RDB (Redis Database Snapshot):
    • 특정 시점에 Redis 데이터를 디스크로 덤프(스냅샷).
    • 주로 백업과 복구에 사용되며, 데이터가 손실될 가능성이 있음(스냅샷 주기와 복구 시점 간 차이).
  2. AOF (Append-Only File):
    • Redis에서 수행된 모든 쓰기 작업을 디스크에 순차적으로 기록.
    • 데이터 손실을 최소화하지만 디스크 I/O 부하가 높음.

Redis의 메모리 사용 특성

  1. RAM 기반 속도:
    • RAM 위에서 동작하므로 초당 수십만~수백만 개의 요청을 처리할 수 있습니다.
  2. 메모리 한계:
    • Redis의 데이터 크기는 사용할 수 있는 RAM 용량에 의존합니다.
    • 데이터 크기가 RAM을 초과하면, 오래된 데이터를 제거하는 Eviction 정책(LRU, LFU 등)이 적용됩니다.
  3. 데이터 휘발성:
    • 기본적으로 RAM에 저장된 데이터는 Redis 서버가 종료되거나 재시작되면 손실됩니다.
    • 이 문제를 해결하기 위해 RDB/AOF로 데이터를 디스크에 저장할 수 있습니다.

 

 

2. 캐시가 필요한 이유는 무엇인가요?

캐시는 데이터 액세스 속도를 높이고, 데이터베이스나 외부 API의 부하를 줄이기 위해 사용됩니다. 주요 이유는 다음과 같습니다:

  1. 성능 향상: 빈번히 조회되는 데이터를 메모리에 저장하여 빠르게 접근.
  2. 부하 분산: 데이터베이스, API 서버의 요청 부하를 줄임.
  3. 비용 절감: 처리 시간을 줄이고, 트래픽 비용 감소.
  4. 사용자 경험 개선: 응답 시간이 짧아져 애플리케이션 성능이 향상

3. 캐시와 데이터베이스의 차이는 무엇인가요?

4. 인메모리 캐시에서 사용하는 주요 도구는 무엇인가요?

Redis:

  • 고성능, 키-값 기반 인메모리 데이터 구조 저장소.
  • 데이터 영속성 지원(옵션).
  • 다양한 데이터 구조 지원(List, Set, Sorted Set, Hash 등)

Memcached:

  • 분산 메모리 객체 캐싱 시스템.
  • 키-값 저장 방식.
  • 간단한 구조로 고속 읽기/쓰기.

Ehcache:

  • Java 애플리케이션용으로 설계된 캐싱 라이브러리.
  • JVM 내에서 동작하며 디스크 캐싱도 지원.

Caffeine:

  • Java에서 사용할 수 있는 고성능 캐싱 라이브러리.
  • LRU 및 LFU와 같은 캐싱 전략 제공.

 

5. 캐시 적중률(Cache Hit Ratio)이란 무엇인가요?

캐시 적중률(Cache Hit Ratio)은 요청된 데이터가 캐시에서 성공적으로 검색된 비율을 의미합니다.

Cache Hit Ratio = (캐시 적중 횟수 / 총 요청 횟수) × 100

 

  • 높은 적중률: 데이터 요청의 대부분이 캐시에서 해결됨.
  • 낮은 적중률: 캐시에 저장되지 않은 데이터 요청이 많음(캐시 미스)

 

6. 캐싱 전략에는 어떤 것들이 있나요?

캐싱 전략? 캐시의 데이터를 효율적으로 관리하고 유지하는 방법

 

 

Cache-Aside:

  • 애플리케이션이 먼저 캐시를 확인하고 없으면 데이터베이스에서 가져와 캐시에 저장.
  • 캐시가 데이터베이스로부터 독립적.

Read-Through:

  • 캐시에 데이터가 없을 경우 자동으로 데이터베이스에서 가져오고 캐시에 저장.

TTL (Time-To-Live):

  • 캐시된 데이터에 만료 시간을 설정하여 일정 시간이 지나면 캐시를 자동 삭제.

Write-Through:

  • 데이터가 캐시에 저장될 때, 동시에 데이터베이스에도 저장.
  • 데이터 일관성이 높지만 쓰기 성능 저하 가능.

Write-Behind:

  • 캐시에 데이터를 저장한 후 비동기적으로 데이터베이스에 저장.
  • 쓰기 성능이 개선되지만 데이터 유실 가능성 존재.

 

7. 캐시 무효화(Cache Invalidation)는 무엇이며, 왜 중요한가요?

캐시 무효화는 캐시된 데이터가 더 이상 유효하지 않을 때 캐시에서 데이터를 제거하거나 업데이트하는 과정입니다.

 

  • 중요성:
    • 캐시는 최신 상태의 데이터를 보장하지 않으므로 데이터의 정확성일관성을 유지하기 위해 필요.
    • 잘못된 캐시 데이터를 사용하는 경우 애플리케이션의 동작에 문제가 생길 수 있음.
  • 캐시 무효화 방법:
    1. 수동 무효화: 애플리케이션 코드에서 캐시 데이터를 직접 제거.
    2. TTL 기반: 데이터에 만료 시간을 설정하여 자동으로 무효화.
    3. Write-Through/Write-Behind: 데이터 업데이트 시 캐시도 동기화.

 

implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-cache'
2. Redis 설정
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class CacheConfig {
    // @EnableCaching: Spring 캐싱 기능 활성화
}
application.yml:

spring:
  cache:
    type: redis
  redis:
    host: localhost
    port: 6379
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 데이터 읽기: 캐시에 데이터가 없으면 DB에서 조회하고 캐시에 저장.
     */
    @Cacheable(value = "users", key = "#userId")
    public User getUserById(Long userId) {
        System.out.println("Fetching from DB for userId: " + userId);
        return userRepository.findById(userId).orElse(null);
    }

    /**
     * 데이터 업데이트: DB를 업데이트하고 캐시를 갱신.
     */
    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        System.out.println("Updating DB and cache for userId: " + user.getId());
        return userRepository.save(user);
    }

    /**
     * 데이터 삭제: DB에서 삭제하고 캐시를 무효화.
     */
    @CacheEvict(value = "users", key = "#userId")
    public void deleteUser(Long userId) {
        System.out.println("Deleting from DB and evicting cache for userId: " + userId);
        userRepository.deleteById(userId);
    }

    /**
     * 전체 캐시 무효화: 모든 캐시를 삭제.
     */
    @CacheEvict(value = "users", allEntries = true)
    public void evictAllUsersCache() {
        System.out.println("Evicting all cache entries for users");
    }
}

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;

@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
}
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @PutMapping
    public User updateUser(@RequestBody User user) {
        return userService.updateUser(user);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }

    @DeleteMapping("/cache")
    public void evictAllCache() {
        userService.evictAllUsersCache();
    }
}

 

 

# 캐시에서 조회:
GET /users/1
Fetching from DB for userId: 1
GET /users/1
(캐시에서 가져온 결과)

# 데이터 업데이트:
PUT /users
Updating DB and cache for userId: 1

# 데이터 삭제:
DELETE /users/1
Deleting from DB and evicting cache for userId: 1

# 전체 캐시 무효화:
DELETE /users/cache
Evicting all cache entries for users

 

8. TTL (Time-To-Live)이란 무엇인가요?

TTL(Time-To-Live)은 캐시에 저장된 데이터의 유효 기간을 설정하는 값입니다.

TTL이 지나면 해당 데이터는 자동으로 삭제되며, 이를 통해 캐시 크기를 제어하고 오래된 데이터를 제거할 수 있습니다.

 

9. 캐시를 사용할 때 발생할 수 있는 문제점은 무엇인가요?

  1. 캐시 무효화 문제:
    • 캐시에 오래된 데이터가 남아 있을 경우 데이터 불일치가 발생.
  2. 메모리 부족:
    • 캐시는 메모리 기반이므로 대규모 데이터를 캐싱할 경우 메모리가 부족할 수 있음.
  3. 캐시 중복 데이터:
    • 여러 인스턴스에서 캐시를 사용하면 중복 데이터가 증가할 가능성.
  4. 캐시 미스(Cache Miss):
    • 데이터가 캐시에 없을 경우 데이터베이스를 조회해야 하며, 이로 인해 지연이 발생.
  5. 성능 병목:
    • 캐시 서버 자체가 과부하되거나 느려질 경우, 전체 애플리케이션의 성능에 영향을 미침.

10. Redis와 Memcached의 차이점은 무엇인가요?

 

 

11. LRU 캐싱이란 무엇인가요?

LRU (Least Recently Used) 캐싱은 가장 오래된 데이터를 우선적으로 제거하는 캐싱 알고리즘

  • 동작 원리:
    1. 캐시가 가득 찼을 때, 가장 최근에 사용되지 않은 데이터를 삭제.
    2. 사용 빈도가 낮은 데이터부터 제거하므로 캐시 효율성을 높임.
  • :
    • 캐시 크기가 3이고, 요청이 A, B, C, D, A 순으로 들어올 때:
      1. A, B, C 저장 (초기).
      2. D 추가 시 A가 제거 (가장 오래된 데이터).
      3. A 요청 시 B 제거.
  • 구현:
    • 보통 LinkedHashMap이나 Deque를 사용하여 LRU 알고리즘을 구현.
    • Redis, Memcached 등에도 LRU 정책이 내장되어 있음.

 

'학습 기록 (Learning Logs) > CS Study' 카테고리의 다른 글

AOP  (0) 2024.12.23
[Note]redis  (0) 2024.12.16
Fetch Join  (0) 2024.12.12
JPA-troubleShooting  (0) 2024.12.12
JPA-advanced-question  (0) 2024.12.12