λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
  • μž₯원읡 κΈ°μˆ λΈ”λ‘œκ·Έ
πŸ”¬web application/- System architecture

cache 101 - μΊμ‹œμ— λŒ€ν•œ 거의 λͺ¨λ“  것

by Wonit 2024. 2. 1.

μ΄λ²ˆμ—λŠ” cache 에 λŒ€ν•΄μ„œ μ•Œμ•„λ³Ό 것이닀.

 

cache 라고 ν•œλ‹€λ©΄ computer science μ—μ„œ 정말 λ‹€μ–‘ν•œ λΆ„μ•Όμ—μ„œ μ‚¬μš©λ˜κ³ , λ™μΌν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•˜μ§€λ§Œ λ¬Έλ§₯에 λ”°λΌμ„œ λ‹€λ₯Έ 이해도가 ν•„μš”ν•˜λ‹€.

 

λ‚˜λŠ” cache 에 λŒ€ν•΄μ„œ web application layer 의 λ¬Έλ§₯μ—μ„œ μ„€λͺ…을 ν•  것이고, software cache 에 λŒ€ν•œ μ„€λͺ…을 주둜 ν•  것이닀.

 

hardware cache 와 더 low level 의 cache λ₯Ό μ›ν•œλ‹€λ©΄ 이 글은 μ ν•©ν•˜μ§€ μ•Šμ„ 수 μžˆλ‹€.

 

TL;DR

 

이번 κΈ€μ˜ 핡심을 μš”μ•½ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€

  • 1. μΊμ‹œλž€ 무엇인가
    • cache: 데이터λ₯Ό μ €μž₯ν•˜μ—¬ λ―Έλž˜μ— ν•΄λ‹Ή 데이터에 λŒ€ν•œ μš”μ²­μ„ 더 λΉ λ₯΄κ²Œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ ν•˜λŠ” hardware ν˜Ήμ€ software
    • cache 의 μ’…λ₯˜
      • h/w cache
      • s/w cache
  • μ™œ cache κ°€ 효과적일까?
    • software μ—μ„œ ν”„λ‘œμ„Έμ„œμ˜ νŠΉμ„±μΈ μ°Έμ‘° 지역성을 κ΅¬ν˜„ν•œ 것이 λ°”λ‘œ μΊμ‹œμž„
      • μ°Έμ‘° 지역성: ν”„λ‘œμ„Έμ„œκ°€ 짧은 μ‹œκ°„ λ™μ•ˆ λ™μΌν•œ λ©”λͺ¨λ¦¬ μœ„μΉ˜μ— νŠΉμ • νŒ¨ν„΄μ„ 가지고 반볡적으둜 μ•‘μ„ΈμŠ€ ν•˜λŠ” κ²½ν–₯
  • cache hit 와 miss 그리고 ratio
    • cache hit: cache 에 μ‘°νšŒν•˜λ €λŠ” 값이 쑴재
    • cache miss: cache 에 μ‘°νšŒν•˜λ €λŠ” 값이 λΆ€μž¬
    • cache hit ratio: hit λΉ„μœ¨
  • cache eviction κ³Ό replacement
    • cache eviction
      • μ˜λ„ν•˜μ§€ μ•Šμ€ 방좜
      • lack of memory 에 μ˜ν•΄ λ°œμƒ
      • μ˜λ„ν•œ 방좜인 expiration κ³ΌλŠ” ꡬ뢄됨
    • cache replacement
      • cache miss -> cache eviction -> load data to cache ν”„λ‘œμ„ΈμŠ€
  • cache ꡐ체 μ „λž΅
    • cache ꡐ체 μ •μ±…
      • LRU : κ°€μž₯ μ‚¬μš©ν•˜μ§€ μ•Šμ€, 였래된 데이터λ₯Ό κ΅μ²΄ν•˜λŠ” μ „λž΅
      • MRU : κ°€μž₯ μ΅œκ·Όμ— μ‚¬μš©λœ νŽ˜μ΄μ§€λ₯Ό κ΅μ²΄ν•˜λŠ” μ „λž΅
      • κ·Έ μ™Έμ˜ μ•Œκ³ λ¦¬μ¦˜
        • LFU
        • RR
  • 그럼 cache λŠ” μ–Έμ œ μ“°λŠ”κ°€?
    • cache λŠ” λΉ„μ‹Ό λ¦¬μ†ŒμŠ€λ―€λ‘œ λΉ„μš© νš¨μœ¨μ„±μ„ 높이렀면 backing store 에 λΉ„ν•΄ μž‘κ²Œ μœ μ§€λ˜μ–΄μ•Ό 함
    • 자주 λ°”λ€Œμ§€ μ•ŠλŠ”λ° 자주 μ‚¬μš©λ˜λŠ” 데이터일 경우 맀우 μœ μš©ν•¨

 

1. cache λž€ 무엇인가?

 

cache λŠ” 데이터λ₯Ό μ €μž₯ν•˜μ—¬ ν–₯ν›„ 데이터에 λŒ€ν•œ μš”μ²­μ„ 더 λΉ λ₯΄κ²Œ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ ν•˜λŠ” h/w ν˜Ήμ€ s/w 이닀.

 

cache 의 컨셉은 μ•„μ£Ό κ°„λ‹¨ν•˜λ‹€. 그림으둜 μ΄ν•΄ν•΄λ³΄μž.

 

μ–΄λ–€ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 있고 λ‹€μŒκ³Ό 같이 μš”μ²­μ„ μ²˜λ¦¬ν•˜μ—¬ μ‚¬μš©μžκ°€ 응닡을 λ°›κΈ°κΉŒμ§€ 2,000ms κ°€ μ†Œμš”λœλ‹€κ³  κ°€μ •ν–ˆμ„ λ•Œ

 

 

좔후에도 μ΄λŸ¬ν•œ μš”μ²­μ΄ 올 것을 μ˜ˆμΈ‘ν•΄, μ—°μ‚°μ˜ κ²°κ³Όλ‚˜ 응닡을 미리 μ–΄λ–€ 곡간에 μ €μž₯ν•΄λ†“λŠ” 것이닀.

 

 

μ–΄λ–€ 곡간에 μ €μž₯된 데이터λ₯Ό entry 라고 λΆ€λ₯΄κ³  이후 μš”μ²­λ“€μ— λŒ€ν•΄μ„œλŠ” entries λ₯Ό μ‘°νšŒν•˜μ˜€μ„ λ•Œ μ‘΄μž¬ν•˜λ©΄ 미리 μ €μž₯된 κ²°κ³Όλ₯Ό λ°”λ‘œ λ°˜ν™˜ν•œλ‹€.

 

 

λ§Œμ•½ 데이터가 entries 에 μ‘΄μž¬ν•œλ‹€λ©΄ κ²°κ³Όλ₯Ό λ°”λ‘œ λ°˜ν™˜ν•  κ²ƒμ΄μ§€λ§Œ, 그렇지 μ•Šλ‹€λ©΄ κΈ°μ‘΄ μš”μ²­κ³Ό 같이 전체 ν”Œλ‘œμš°λ₯Ό λ™μΌν•˜κ²Œ μ§„ν–‰ν•˜λŠ” 것이닀

 

μΊμ‹œλŠ” κ±°μ°½ν•˜μ§€ μ•Šλ‹€.

 

μΊμ‹œλŠ” κΌ­ μ–΄λ– ν•œ 기술(memcache)μ΄λ‚˜ 툴 ν˜Ήμ€ μ†”λ£¨μ…˜(redis)을 μ΄μš©ν•΄μ•Όν•˜ μΊμ‹œλ₯Ό μ“΄λ‹€κ³  ν•  수 μžˆμ„κΉŒ? 그렇지 μ•Šλ‹€.

 

λ‹¨μˆœνžˆ μ½”λ“œλ ˆλ²¨μ—μ„œ db 결과값을 λ³€μˆ˜(λ©”λͺ¨λ¦¬)에 μ €μž₯해놨닀가 μš”μ²­μ΄ 였면 db 에 μΏΌλ¦¬ν•˜μ§€ μ•Šκ³  μ €μž₯된 값을 μ‚¬μš©ν•˜λŠ” 것도 cache 라고 λ³Ό 수 μžˆλ‹€

public class FooService {

  // DB connection & interactions
  private final FooRepository repository;
  // In memory operations
  private final Map<UserId, User> myCache;

  public User getUser(UserId id) {
    if (myCache.contains(id)) {
      return myCache.get(id);
    }

    return repository.findBy(id);
  }
}

 

이제 λ‹€μ‹œ 본둠으둜 λŒμ•„μ™€μ„œ, μΊμ‹œμ— λŒ€ν•œ μ •μ˜λ₯Ό λ§ˆλ¬΄λ¦¬ν•΄λ³΄μž

 

1-1. μΊμ‹œλŠ” κ²°κ΅­ 무엇인가?

μΊμ‹œλŠ” 이전 κ³„μ‚°μ˜ κ²°κ³Όλ‚˜ λ‹€λ₯Έ 곳에 μ €μž₯된 λ°μ΄ν„°μ˜ 볡사본을 νŠΉμ • 곡간에 μ €μž₯ν•˜μ—¬ μž¬μ‚¬μš©ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

 

κ²°κ΅­ λͺ©μ μ€ 연산에 λŒ€ν•œ overhead λ₯Ό μ€„μ΄λŠ” 것이닀

  • 이전 κ³„μ‚°μ˜ κ²°κ³Ό: λ™μΌν•œ λ§€κ°œλ³€μˆ˜λΌλ©΄ 결과도 동일할 κ²ƒμ΄λ―€λ‘œ 이쀑 연산에 λŒ€ν•œ overhead λ₯Ό 쀄여쀀닀
  • λ°μ΄ν„°μ˜ 볡사본: 물리적으둜 떨어진 데이터λ₯Ό μ‘°νšŒν•  λ•Œ λ°œμƒν•˜λŠ” overhead λ₯Ό 쀄여쀀닀

 

1-2. λŒ€ν‘œμ μΈ μΊμ‹œμ˜ μ’…λ₯˜

 

μΊμ‹œλŠ” 2가지 μ’…λ₯˜λ‘œ 크게 λ‚˜λˆŒ 수 μžˆλ‹€.

 

  1. hardware cache
  2. software cache

 

μΊμ‹œμ˜ μ’…λ₯˜ - hardware cache

 

hardware cache λŠ” operating system κ³Ό computer architecture μ—μ„œ 자주 μ–ΈκΈ‰λ˜λŠ” CPU cache κ°€ λŒ€ν‘œμ μ΄λ‹€.

 

 

H/W λ‚˜ S/W λͺ¨λ‘ 컨셉은 λ™μΌν•˜λ‹€.

 

H/W cache 쀑에 CPU cache λŠ” μ£ΌκΈ°μ–΅μž₯치인 RAM κ³Ό 보쑰기얡μž₯치 μ‚¬μ΄μ˜ 속도λ₯Ό ν–₯μƒμ‹œν‚€κΈ° μœ„ν•œ λͺ©μ μœΌλ‘œ μ‚¬μš©λœλ‹€

 

μΊμ‹œμ˜ μ’…λ₯˜ - software cache

 

software cache λŠ” application layer μ—μ„œ λ™μž‘ν•˜λŠ” cache λ₯Ό μƒκ°ν•˜λ©΄ λœλ‹€

 

유λͺ…ν•œ μ†”λ£¨μ…˜μΈ Redis λ₯Ό μ‚¬μš©ν•˜μ—¬ DB λ°μ΄ν„°λ‚˜ μ—°μ‚° κ²°κ³Όλ₯Ό μ €μž₯ν•˜λŠ” global cache 도 software cache 이며

 

MySQL μ—μ„œ μ‚¬μš©λ˜λŠ” InnoDB buffer λ‚˜ λ³΅μž‘ν•œ 데이터 쑰합을 미리 λ§Œλ“€μ–΄ μ €μž₯ν•˜λŠ” materialized view 도 cache 에 μ†ν•œλ‹€.

 

1-3. μ™œ cache κ°€ 효과적일까?

 

μ™œ cache κ°€ 효과적일까? 이쯀 되면 μ•žμ„  μ„€λͺ…μœΌλ‘œ cache κ°€ 더 λΉ λ₯Έ μ†λ„λ‘œ μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ” 것은 λ‹Ήμ—°ν•΄ 보일 것이닀.

 

cache κ°€ 효과적인 μ΄μœ λŠ” computer science μ—μ„œ ν•„μ—°μ μœΌλ‘œ λ°œμƒν•˜λŠ” μ°Έμ‘° 지역성, Locality of Reference λ•Œλ¬Έμ΄λ‹€.

 

μ΄μœ λŠ” Locality of Reference, μ°Έμ‘° 지역성 λ•Œλ¬Έμ΄λ‹€!

 

μ°Έμ‘° 지역성, Locality of Reference 은 ν”„λ‘œμ„Έμ„œκ°€ 짧은 μ‹œκ°„ λ™μ•ˆ λ™μΌν•œ λ©”λͺ¨λ¦¬ μœ„μΉ˜μ— νŠΉμ • νŒ¨ν„΄μ„ 가지고 반볡적으둜 μ•‘μ„ΈμŠ€ ν•˜λŠ” κ²½ν–₯을 μ˜λ―Έν•œλ‹€.

 

κ²°κ΅­ 반볡적으둜 μ•‘μ„ΈμŠ€ν•˜λŠ” κ²½ν–₯만 잘 μ΄μš©ν•œλ‹€λ©΄ μ΅œμ ν™”λ₯Ό 이뀄낼 수 있고 그것이 λ°”λ‘œ cache 인 것이닀

 


2. cache hit 와 miss 그리고 ratio

 

cache λ₯Ό μ‚¬μš©ν•˜λŠ” client λŠ” 상황에 따라 λ‹€μ–‘ν•˜λ‹€.

 

λ„€νŠΈμ›Œν¬ μΊμ‹œλ₯Ό μ‚¬μš©ν•˜λŠ” λΈŒλΌμš°μ €κ°€ 될 μˆ˜λ„, cache memory λ₯Ό μ‚¬μš©ν•˜λŠ” CPU κ°€ 될 μˆ˜λ„, redis 와 같은 global cache storage λ₯Ό μ‚¬μš©ν•˜λŠ” web application 이 될 μˆ˜λ„ μžˆλ‹€.

 

μ΄λŸ¬ν•œ cache client λŠ” backing store 에 μ‘΄μž¬ν•œλ‹€κ³  μƒκ°λ˜λŠ” 데이터에 μ ‘κ·Όν•  λ•Œ cache λ₯Ό μ‘°νšŒν•˜μ—¬ 2가지 결둠을 λ‚Έλ‹€.

 

  1. cache hit, cache 에 client κ°€ μ›ν•˜λŠ” 데이터가 μ‘΄μž¬ν•΄
  2. cache miss, cache 에 client κ°€ μ›ν•˜λŠ” 데이터가 μ‘΄μž¬ν•˜μ§€ μ•Šμ•„

 

λͺ¨λ“  cache client λŠ” cache 에 λŒ€ν•΄ hit ν•˜κ±°λ‚˜, miss ν•˜κ²Œ λœλ‹€

 

2-1. cache hit

 

client κ°€ μ›ν•˜λŠ” 데이터가 cache memory 에 μ‘΄μž¬ν•  경우 cache hit 라고 ν•œλ‹€

 

 

'cache client λŠ” cache hit μ‹œ ν•΄λ‹Ή 데이터λ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ— λ³„λ„μ˜ μΆ”κ°€ μž‘μ—…μ΄ ν•„μš”ν•˜μ§€ μ•Šλ‹€

 

κ·Έλž˜μ„œ cache hit κ°€ λ§Žμ„ 수둝 μ „λ°˜μ μœΌλ‘œ μ‹œμŠ€ν…œμ˜ μ„±λŠ₯이 ν–₯μƒλœλ‹€

 

2-2. cache miss

 

ν•˜μ§€λ§Œ client κ°€ μ›ν•˜λŠ” 데이터가 cache 에 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경우라면 μ΄μ•ΌκΈ°λŠ” 달라진닀.

 

이λ₯Ό cache miss 라고 ν•œλ‹€

 

 

λ§Œμ•½ cache miss κ°€ λ°œμƒν–ˆλ‹€λ©΄ cache client λŠ” backing store 에 λ‹€μ‹œ μš”μ²­μ„ 톡해 데이터λ₯Ό μ‘°νšŒν•˜λŠ” 과정에 overhead κ°€ μΆ”κ°€μ μœΌλ‘œ λ°œμƒν•˜κ³  μ„±λŠ₯ ν•˜λ½μœΌλ‘œ μ΄μ–΄μ§€κ²Œ λœλ‹€.

 

2-3. cache ratio

 

cache ratio λŠ” 2가지가 μ‘΄μž¬ν•œλ‹€.

 

  1. cache hit ratio
  2. cache miss ratio

cache hit ratio 와 cache miss ratio λŠ” 각각 hit 냐 miss 냐 에 λŒ€ν•œ λΉ„μœ¨μ΄λ‹€

 

 

전체 μš”μ²­(access)에 λŒ€λΉ„ν•΄μ„œ μ–Όλ§ˆλ‚˜ hit or miss 인지 λ‚˜νƒ€λ‚΄λŠ” λΉ„μœ¨μΈλ°, λ‹Ήμ—°νžˆ hit ratio κ°€ λ†’μ•„μ Έμ•Ό cache 에 λŒ€ν•œ μ„±λŠ₯ μ΅œμ ν™”μ™€ 섀계가 잘 λ˜μ—ˆλ‹€κ³  ν•œλ‹€

 

그럼 cache miss κ°€ λ°œμƒν•œλ‹€λ©΄ μ–΄λ–€ 상황이 λ²Œμ–΄μ§€κ²Œ 될까?

 

cache miss κ°€ λ°œμƒν•˜λ©΄ cache client λŠ” 2가지λ₯Ό κ³ λ―Όν•΄μ•Όν•œλ‹€

 

  1. μΆ”ν›„λ₯Ό λŒ€λΉ„ν•΄ 이 데이터λ₯Ό cache 에 μ μž¬ν•΄ λ†“μ„κΉŒ?
  2. λ§Œμ•½ 적재λ₯Ό ν•˜λ €λŠ”λ° cache κ°€ 꽉 μ°Όλ‹€λ©΄ μ–΄λ–€ 데이터λ₯Ό μ‚­μ œν•΄μ•Όν•˜μ§€?

 

이 고민을 더 μžμ„Ένžˆ μ•Œμ•„λ³΄μž

 


3. μΊμ‹œ 방좜과 ꡐ체

 

μ•žμ„  고민은 cache λ₯Ό μ‚¬μš©ν•  λ•Œ ν•œ 번쯀 해봐야 ν•˜λŠ” 고민이닀.

 

이 κ³ λ―Ό μ•ˆμ—λŠ” 사싀 2κ°€μ§€μ˜ 큰 κ°œλ…μ΄ μˆ¨μ–΄μžˆλŠ”λ°, 그것이 λ°”λ‘œ eviction κ³Ό replacement 이닀

 

3-1. μΊμ‹œ 방좜, cache eviction

 

cache λŠ” νŠΉμ •ν•œ ν˜•νƒœμ˜ μ €μž₯μ†Œμ΄λ‹€. 즉, μ œν•œλœ 크기λ₯Ό 가지고 있기 λ•Œλ¬Έμ— μ–Έμ  κ°€λŠ” 데이터가 꽉 차게 λœλ‹€.

 

λ§Œμ•½ μƒˆλ‘œμš΄ 데이터λ₯Ό cache 에 μ μž¬ν•˜λ € ν•˜λŠ”λ° cache κ°€ 꽉 μ°¨μžˆλ‹€κ³  κ°€μ • ν•΄λ³΄μž

 

그럼 λ‹Ήμ—°νžˆ cache 에 μƒˆλ‘œμš΄ 데이터λ₯Ό μˆ˜μš©ν•  수 μžˆλŠ” 곡간을 λ§Œλ“€μ–΄μ•Ό ν•  것이닀.

 

이 λ•Œ cache 에 μƒˆλ‘œμš΄ 데이터λ₯Ό μΆ”κ°€ν•˜κΈ° μœ„ν•΄μ„œλŠ” cache 에 μ‘΄μž¬ν•˜λŠ” νŠΉμ • 데이터λ₯Ό μ‚­μ œλΌλŠ” 과정을 거쳐야 ν•˜κ³  이 것이 λ°”λ‘œ cache eviction, μΊμ‹œ 방좜이라고 ν•œλ‹€

 

cache λ₯Ό μ‚¬μš©ν•˜λ‹€ 보면 eviction κ³Ό expiration μ΄λΌλŠ” μš©μ–΄λ₯Ό λ§Œλ‚  수 μžˆλ‹€. 이 λ‘˜μ€ λͺ…ν™•νžˆ κ΅¬λΆ„λ˜μ–΄μ•Ό ν•˜λŠ”λ°, eviction 은 λͺ…μ‹œμ μœΌλ‘œ μ˜λ„ν•˜μ§€ μ•Šμ€ 방좜의 ν–‰μœ„λΌλ©΄ expiration 은 λͺ…μ‹œμ μœΌλ‘œ μ˜λ„ν•œ 방좜의 ν–‰μš°μ΄λ‹€.

 

Eviction 은 lack of memory 에 μ˜ν•΄μ„œ λ°œμƒν•˜λŠ” passive ν•œ 연산이닀

 

κ·Έλž˜μ„œ 항상 cache 의 put μ—°μ‚° 이전에 μ™„λ£Œλ˜μ–΄μ•Ό ν•œλ‹€

 

3-2. μΊμ‹œ ꡐ체, cache replacement

 

μΊμ‹œ κ΅μ²΄λŠ” μ•žμ„  cache miss -> cache eviction -> load data to cache 의 전체 ν”„λ‘œμ„ΈμŠ€λ₯Ό μ˜λ―Έν•œλ‹€

κ²°κ΅­ cache miss κ°€ λ°œμƒν•˜μ—¬ cache eviction 을 톡해 곡간을 λ§Œλ“€κ³  μƒˆλ‘œμš΄ 데이터λ₯Ό cache 에 μ μž¬ν•˜λŠ” ν–‰μœ„λ“€μ„ ν†΅ν‹€μ–΄μ„œ ꡐ체 라고 ν•˜λŠ” 것이닀

 

이 μΊμ‹œ κ΅μ²΄λŠ” cache 의 μ„±λŠ₯κ³Ό νš¨μœ¨μ„±μ— μžˆμ–΄μ„œ μ•„μ£Ό μ€‘μš”ν•œ 뢀뢄을 μ°¨μ§€ν•œλ‹€.

 

cache replacement λŠ” μΊμ‹œμ˜ μ„±λŠ₯κ³Ό μ§κ²°λœλ‹€

 

λ§Œμ•½ μΊμ‹œκ°€ 꽉 μ°¨μžˆμ–΄μ„œ μž„μ˜λ‘œ μ–΄λ–€ 데이터λ₯Ό evict ν•˜μ˜€λ‹€.

 

ν•˜μ§€λ§Œ ν•΄λ‹Ή λ°μ΄ν„°λŠ” eviction λœμ§€ μ–Όλ§ˆ μ•ˆ μžˆμ–΄ λ‹€μ‹œ κ΅μ²΄λ˜μ–΄ cache 에 μ €μž₯λ˜μ—ˆλ‹€.

 

ν•˜μ§€λ§Œ 또 μΊμ‹œκ°€ 꽉 μ°¨μ„œ ν•΄λ‹Ή 데이터λ₯Ό evict ν•œλ‹€λ©΄ κ³„μ†ν•΄μ„œ cache miss κ°€ λ°œμƒν•˜κ²Œ 될 것인데 그럼 cache miss ratio κ°€ μ˜¬λΌκ°€ κ²°κ΅­ cache 의 μ„±λŠ₯이 맀우 λ–¨μ–΄μ§€κ²Œ 될 것이닀

 

κ·Έλž˜μ„œ cache miss μ‹œ cache 에 데이터λ₯Ό λ°©μΆœν•˜λŠ” 방법에 λŒ€ν•΄ λ§Žμ€ 고민이 ν•„μš”ν•˜λ‹€

 


4. cache ꡐ체 μ „λž΅

 

cache λ₯Ό ꡐ체할 λ•Œμ—λŠ” μ „λž΅μ΄ ν•„μš”ν•˜λ‹€

 

μ•žμ„  μ˜ˆμ‹œμ²˜λŸΌ cache λ₯Ό ꡐ체해야 ν•˜λŠ”λ° μž„μ˜μ΄ 데이터λ₯Ό μ„ νƒν•΄μ„œ κ΅μ²΄ν–ˆλ‹€κ³  κ°€μ •ν•΄λ³΄μž.

 

κ·Έλ ‡λ‹€λ©΄ μ΅œμ•…μ˜ μƒν™©μ—μ„œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” cache λ₯Ό λ°©μΆœν•˜κ²Œ λ˜μ–΄ cache miss ratio κ°€ λ†’μ•„μ Έ cache λ₯Ό μ‚¬μš©ν•˜λŠ”λ° 큰 효과λ₯Ό 얻지 λͺ»ν•˜κ²Œ 될 수 μžˆλ‹€.

 

κ·Έλž˜μ„œ cache ꡐ체 μ „λž΅μ„ 잘 μ„Έμš΄λ‹€λ©΄ cache hit ratio λ₯Ό λ†’κ²Œ μœ μ§€ν•  수 μžˆλŠ”λ°, cache ꡐ체 μ „λž΅μ€ Operation System μ—μ„œ μ΄μ•ΌκΈ°ν•˜λŠ” Page Fault 에 λŒ€ν•œ handling κ³Ό μœ μ‚¬ν•˜κ²Œ μ²˜λ¦¬λœλ‹€.

 

λ‹€μ–‘ν•œ replacement algorith 이 μ‘΄μž¬ν•˜λŠ”λ°, κ°€μž₯ λŒ€ν‘œμ μΈ LRU μ•Œκ³ λ¦¬μ¦˜μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μž

 

μš”μ¦˜ μ‚¬μš©ν•˜λŠ” cache λŠ” LRU cache κ°€ κ°€μž₯ λŒ€ν‘œμ μ΄λ‹€

 

4-1. cache ꡐ체 μ „λž΅, LRU (Least Recently Used)

 

LRU μ•Œκ³ λ¦¬μ¦˜μ€ κ°€μž₯ μ‚¬μš©ν•˜μ§€ μ•Šμ€, 였래된 데이터λ₯Ό κ΅μ²΄ν•˜λŠ” μ „λž΅μ΄λ‹€

 

이 λ…Όλ¦¬λŠ” μ•žμ„œ μ΄μ•ΌκΈ°ν•œ μ°Έμ‘° μ§€μ—­μ„±μ˜ νŠΉμ„± 즉, μ΅œκ·Όμ— μ‚¬μš©ν•˜μ§€ μ•Šμ€ λ°μ΄ν„°λŠ” λ―Έλž˜μ—λ„ μ‚¬μš©ν•˜μ§€ μ•Šμ„ κ²ƒμ΄λΌλŠ” idea μ—μ„œ μ‹œμž‘λ˜μ—ˆλ‹€.

LRU μ•Œκ³ λ¦¬μ¦˜μ˜ 핡심은 λ°”λ‘œ accessOrder 이닀.

 

즉, νŠΉμ • 데이터에 μ–Όλ§ˆλ‚˜ μ•‘μ„ΈμŠ€ ν–ˆλƒλ₯Ό ν†΅ν•΄μ„œ 데이터가 eviction 될지 말지가 κ²°μ •λ˜κΈ° λ•Œλ¬Έμ— LRU μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•  λ•Œμ—λŠ” access 에 λŒ€ν•œ tracking 이 ν•„μš”ν•˜λ‹€

 

Java μ—μ„œλŠ” HashMap κ³Ό LinkedHashSet 을 ν†΅ν•΄μ„œ μ‰½κ²Œ κ΅¬ν˜„μ΄ κ°€λŠ₯ν•˜λ‹€

 

public class MyCache {
  public static final int STORAGE_CAPACITY = 10;
  // 초기 μš©λŸ‰μ΄ 10 인 map 생성
  HashMap<String, String> storage = new HashMap<>(STORAGE_CAPACITY);
  LinkedHashSet<String> accessOrder = new LinkedHashSet<>();

  /**
   * μΊμ‹œ 쑰회
   */
  public String get(String key) {
    if (!storage.containsKey(key)) {
      return "CACHE MISS";
    }
    markUsed(key); // access tracking
    return storage.get(key);
  }

  /**
   * μ‚¬μš© ν–ˆλ‹€λŠ” λ§ˆν‚Ή
   */
  private void markUsed(String key) {
    accessOrder.remove(key);
    accessOrder.add(key);
  }

  /**
   * μΊμ‹œ ꡐ체 ν˜Ήμ€ 적재
   */
  public void put(String key, String value) {
    if (storage.containsKey(key)) {
      throw new IllegalArgumentException("이미 cache 에 μ‘΄μž¬ν•˜λŠ” key μž…λ‹ˆλ‹€");
    }

    evictLRU(); // 방좜
    storage.put(key, value);
  }

  /**
   * κ°€μž₯ 였래 μ‚¬μš©λ˜μ§€ μ•Šμ€ 데이터λ₯Ό μ‚­μ œ
   */
  private void evictLRU() {
    if (storage.size() != STORAGE_CAPACITY) { // λ§Œμ•½ μΊμ‹œκ°€ 꽉 차지 μ•Šμ•˜λ‹€λ©΄
      return;
    }

    String lruKey = accessOrder.iterator().next();
    storage.remove(lruKey);
  }
}

LinkedHashSet 은 μ‚½μž…λœ element 의 μˆœμ„œλ₯Ό μ•Œκ³  μžˆλ‹€.

 

κ·Έλž˜μ„œ storage 에 put 을 ν•  λ•Œλ§ˆλ‹€ μ‚­μ œ -> μ‚½μž… 과정을 거쳐 access 에 λŒ€ν•œ order λ₯Ό tracking ν•  수 있게 ν•˜λŠ” 것이 핡심이닀

 

4-2. 이외에 μ–΄λ–€ Cache Replacement μ „λž΅μ΄ μžˆμ„κΉŒ?

 

이외에도 λ‹€μ–‘ν•œ Cache Replacement μ „λž΅μ΄ μ‘΄μž¬ν•œλ‹€.

 

ν•˜μ§€λ§Œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ€ LRU 와 LFU μ΄λ―€λ‘œ 이 λ‘κ°€μ§€λ§Œ μ•Œκ³  μžˆμ–΄λ„ μΆ©λΆ„ν•˜λ©° λ‹€λ₯Έ μ•Œκ³ λ¦¬μ¦˜λ“€μ΄ 크게 어렡지 μ•Šλ‹€

 

  • LFU (Least Frequently Used)
    • LRU 와 λ™μΌν•˜κ²Œ μ°Έμ‘° 지역성을 μ΄μš©ν•˜μ˜€μœΌλ‚˜ accessOrder κ°€ μ•„λ‹ˆλΌ μ‚¬μš© λΉˆλ„λ₯Ό tracking ν•œλ‹€
    • access 에 λŒ€ν•œ counter λ₯Ό κ΅¬ν˜„ν•˜μ—¬ λΉˆλ„λ₯Ό tracking ν•˜λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„λœλ‹€
  • MRU (Most Recently Used)
    • LRU 와 λ°˜λŒ€λ‘œ κ°€μž₯ μ΅œκ·Όμ— μ‚¬μš©λœ νŽ˜μ΄μ§€λ₯Ό κ΅μ²΄ν•˜λŠ” μ „λž΅μ΄λ‹€
      • 이 컨셉은 ν•œ 번 μ‚¬μš©λ˜λ©΄ κ°€κΉŒμš΄ λ―Έλž˜μ— μ‚¬μš©λ˜μ§€ μ•ŠλŠ” νŒ¨ν„΄μ„ μ΄μš©ν•œλ‹€
    • κ·Έλž˜μ„œ νŒ¨ν„΄μ΄ μ‘΄μž¬ν•˜λŠ” νŠΉμ • μˆœν™˜ 주기의 데이터λ₯Ό μ œμ™Έν•˜κ³ μ„œλŠ” 자주 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€
  • RR (Random Replacement)
    • 말 κ·ΈλŒ€λ‘œ λžœλ€ν•˜κ²Œ ꡐ체λ₯Ό ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄λ‹€.
    • κ΅¬ν˜„ν•˜κΈ° κ°€μž₯ κ°„λ‹¨ν•˜μ§€λ§Œ cache μ„±λŠ₯이 맀우 λ–¨μ–΄μ§ˆ 수 있기 λ•Œλ¬Έμ— μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€

 

μ—¬λ‹΄μœΌλ‘œ Global Cache 의 λŒ€ν‘œκ²©μΈ Redis λŠ” 4.0 버전 이후뢀터 LRU 뿐만 μ•„λ‹ˆλΌ LFU μ•Œκ³ λ¦¬μ¦˜μ„ μ§€μ›ν•˜κΈ° μ‹œμž‘ν–ˆλ‹€.

 

ν•˜μ§€λ§Œ κΈ°λ³Έμ μœΌλ‘œλŠ” λ‹€μŒ μ‹œκ°„μ— μ•Œμ•„λ³Ό λ‚΄μš©μ΄μ§€λ§Œ, TTL(Time To Live) 을 μ΄μš©ν•œ LRU λ₯Ό 톡해 κ΄€λ¦¬λœλ‹€

 


5. cache λŠ” μ–Έμ œ μ‚¬μš©ν•˜λŠ” 것이 효과적일까?

 

cache λŠ” λΉ„μ‹Έλ‹€.

 

os μ±…μ—μ„œ 봀을 memory hierarchy 의 λΉ„μš© 그림은 λ„ˆλ¬΄λ‚˜λ„ 유λͺ…ν•˜λ‹€

 

λΉ λ₯Ό 수둝, cpu 와 가깝고 비싸진닀

cache memory λŠ” λΉ„μ‹Έλ‹€. κ·Έλž˜μ„œ λΉ„μš© νš¨μœ¨μ„±μ„ 따진닀면 backing store 보닀 cache λŠ” 훨씬 μž‘κ²Œ μœ μ§€ν•˜λŠ” 편이 일반적이고 νš¨μœ¨μ μ΄λ‹€.

 

μš°λ¦¬κ°€ 적재 μ μ†Œμ— μΊμ‹œλ₯Ό 잘 λ°°μΉ˜ν•˜μ˜€λ‹€λ©΄ μΊμ‹œμ˜ 크기가 μž‘λ”λΌλ„ κ°•λ ₯ν•œ μ΅œμ ν™” 도ꡬ가 될 수 μžˆλ‹€.

 

κ·Έλž˜μ„œ μ–Έμ œ μ¨μ•Όν•˜μ§€?

 

결둠만 μ΄μ•ΌκΈ°ν•˜μžλ©΄ μΊμ‹œλŠ” 자주 μ‚¬μš©λ˜λ©° 잘 λ°”λ€Œμ§€ μ•ŠλŠ” 데이터일 κ²½μš°μ— μ ν•©ν•˜λ‹€

 

μš°λ¦¬λŠ” cache replacement 에 λŒ€ν•΄μ„œ 이제 μ•Œκ³ μžˆλ‹€.

 

아무리 쒋은 ꡐ체 μ•Œκ³ λ¦¬μ¦˜μ„ μ μš©ν•˜λ”λΌλ„ κ²°κ΅­ ꡐ체가 μ• μ΄ˆμ— λ˜μ§€ μ•ŠλŠ” 상황을 λ§Œλ“œλŠ” 것이 μ’‹λ‹€.

 

cache hit ratio κ°€ 높을 수둝 eviction & replacement 에 λ“€μ–΄κ°€λŠ” μ˜€λ²„ν—€λ“œλ₯Ό 쀄일 수 있기 λ•Œλ¬Έμ΄λ‹€.

 

자주 λ°”λ€ŒλŠ” 데이터에 λŒ€ν•΄μ„œλŠ” cache λ₯Ό μ μš©ν•˜λŠ” 것 λ˜ν•œ 쒋은 선택은 μ•„λ‹ˆλ‹€

 

마치며

 

이제 cache 에 λŒ€ν•œ 기초λ₯Ό λ–Όμ—ˆλ‹€κ³  λ³Ό 수 μžˆλ‹€.

 

μ•žμœΌλ‘œ cache 에 λŒ€ν•΄μ„œ μ•Œμ•„μ•Ό ν•  것듀과 λ„˜μ–΄μ•Ό ν•  산이 맀우 높은데, 이번 μ‹œκ°„μ„ ν†΅ν•΄μ„œ 기본적인 κ·Έ κΈ°λ³ΈκΈ°λ₯Ό λ‹€μ‘Œλ‹€κ³  μƒκ°ν•˜λ©΄ 될것 κ°™λ‹€

 

μ•žμœΌλ‘œ μΊμ‹œμ™€ κ΄€λ ¨λœ 글을 κ³„μ†ν•΄μ„œ 올릴 μ˜ˆμ •μ΄λ‹ˆ λ‹€λ₯Έ 글도 μ°Έκ³ ν•˜κΈΈ λ°”λž€λ‹€

λŒ“κΈ€