πΈμΊμ μ€ν¬νΌλ νμμ΄λ?
μΊμ μ€ν¬νΌλ νμ: νλμ μΊμ νλͺ©μ΄ λ§λ£λμμ λ λ€μμ μμ²μ΄ λμμ μΊμλ₯Ό κ°±μ νλ €κ³ νλ©΄μ λ°μνλ λ¬Έμ
λ λμ€λ₯Ό μΊμλ‘ νμ©ν λ λͺ¨λ ν€μ λν΄ λ§λ£ μκ°μ μ€μ νλ κ²μ κΆμ₯λμ§λ§, λκ·λͺ¨ νΈλν½ νκ²½μμ λ§λ£μκ°μ μ΄λ»κ² μ€μ νλλμ λ°λΌ μΊμ μ€ν¬νΌλμ κ°μ μμμΉ λͺ»ν λ¬Έμ μν©μ΄ λ°μν μ μλ€.
μμ κ·Έλ¦Όμμ, μ ν리μΌμ΄μ
1κ³Ό 2λ look aside λ°©μμΌλ‘ λ λμ€λ₯Ό μ¬μ©νκ³ μλ€κ³ μκ°ν΄λ³΄μ.
look aside λ°©μμμ μ ν리μΌμ΄μ
μ λ λμ€μ λ¨Όμ λ°μ΄ν°κ° μλμ§ μ§μν ν λ°μ΄ν°κ° μμ λ λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό μ½μ΄μ€λ κ³Όμ μ λ°λ³΅νλ€.
μ΄λ, λ λμ€μμ νΉμ ν€κ° λ§λ£λλ μμ μ μκ°ν΄λ³΄μ.
1οΈβ£ λ€μμ μ ν리μΌμ΄μ μ΄ λμΌν μΊμ ν€λ₯Ό μμ²
↓
2οΈβ£ μΊμκ° λ§λ£(TTL μ΄κ³Ό)λλ©΄μ λ°μ΄ν°κ° μμ λ¨
↓
3οΈβ£ λͺ¨λ μμ²μ΄ λμμ DBλ‘ μ λ¦Ό (Duplicate Read λ°μ)
↓
4οΈβ£ DBμμ λ°μ΄ν°λ₯Ό κ°μ Έμ¨ ν μΊμμ λ€μ μ μ₯
↓
5οΈβ£ μ¬λ¬ μ ν리μΌμ΄μ μ΄ λμμ μΊμμ λ°μ΄ν°λ₯Ό μ μ₯ (Duplicate Write λ°μ)
μ΄ κ³Όμ μμ DB λΆνκ° κΈμ¦νκ³ μμ€ν μλ΅ μκ°μ΄ λλ €μ§κ±°λ μ₯μ κ° λ°μν μ μλ€.
νλ² μΊμ μ€ν¬νΌλ νμμ΄ λ°μνλ©΄ κ²°κ³Όμ μΌλ‘ λ λ§μ λ°μ΄ν°κ° μ΄ νμμ μν₯μ λ°κ² λΌ, λ ν° λ¬Έμ λ‘ μ΄μ΄μ§ μ μλ€. μ΄λ° μ΄μ λ‘ κ³λ¨μ μ€ν¨(cascading failure)λΌκ³ λ λΆλ₯Έλ€.
πΈν΄κ²° λ°©λ²
μΊμ μ€ν¬νΌλ νμμ λ°©μ§ν μ μλ λͺ κ°μ§ λ°©λ²μ λν΄ μ΄ν΄λ³΄κ³ μ νλ€.
1οΈβ£ TTL μ€μ
πΉ1. μ μ ν λ§λ£ μκ° μ€μ
μΊμ μ€ν¬νΌλλ₯Ό μ€μ΄κΈ° μν κ°μ₯ κ°λ¨ν λ°©λ²μ λ§λ£ μκ°μ λ무 μ§§μ§ μκ² μ€μ νλ κ²μ΄λ€.
μ¬λ¬ μ ν리μΌμ΄μ μμ νκΊΌλ²μ μ κ·Όν΄μΌ νλ λ°μ΄ν°μ΄λ©°, λ°λ³΅μ μΌλ‘ μ¬μ©λΌμΌ νλ λ°μ΄ν°λΌλ©΄ μ μ₯ μμ λΆν° λ§λ£ μκ°μ μΆ©λΆν κΈΈκ² μ€μ ν΄μ£Όλ κ²μ΄ μ’λ€.
πΉ2. λλ€ TTL μ μ©
val ttl = 300 + Random.nextInt(30) // 300μ΄ ~ 330μ΄ μ¬μ΄ λλ€ TTL μ μ©
redisTemplate.expire("cache-key", ttl, TimeUnit.SECONDS)
TTL κ°μ μΌμ λ²μ λ΄μμ λλ€νκ² μ€μ νμ¬ λμΌν μκ°μ μΊμκ° λ§λ£λμ§ μλλ‘ ν μ μλ€.
2οΈβ£ μ κ³μ°
μΊμκ° λ§λ£λκΈ° μ μ 미리 λ°μ΄ν°λ₯Ό κ°±μ (μ κ³μ°)νλ κΈ°λ²
πΉκΈ°μ‘΄μ λ¬Έμ μ
def fetch(key):
value = redis.get(key)
if not value:
value = db.fetch(key) # DBμμ λ°μ΄ν° μ‘°ν
redis.set(key, value) # μΊμμ μ μ₯
return value
κΈ°μ‘΄μ λμ λ°©μμ λ€μκ³Ό κ°λ€.
1οΈβ£λ λμ€μμ key κ°μ μ‘°ν
↓
2οΈβ£κ°μ΄ μλ€λ©΄ DBμμ λ°μ΄ν°λ₯Ό κ°μ Έμ΄
↓
3οΈβ£κ°μ Έμ¨ λ°μ΄ν°λ₯Ό λ λμ€μ μ μ₯ ν λ°ν
νμ§λ§ μμ κ°μ λ°©μμ μ¬λ¬ μ ν리μΌμ΄μ μ΄ λμμ μΊμ λ§λ£λ₯Ό μΈμ§νκ³ DBλ₯Ό μ‘°ννλ©΄ νΈλν½ νμ¦μ΄ λ°μνλ©° μ€λ³΅ μ½κΈ°μ μ€λ³΅ μ°κΈ°κ° λ°μνλ€.
πΉμ κ³μ° κΈ°λ²
import random
def fetch(key, expiry_gap):
ttl = redis.ttl(key) # νμ¬ λ¨μ TTL νμΈ
if ttl - (random.random() * expiry_gap) > 0:
return redis.get(key) # μΊμλ κ° λ°ν
else:
value = db.fetch(key) # DBμμ λ°μ΄ν° μ‘°ν
redis.set(key, value, KEY_TTL) # μΊμ κ°±μ
return value
# μ¬μ© μμ
fetch("hello", 2)
μμ μ½λμ λμ λ°©μμ λ€μκ³Ό κ°λ€.
1οΈβ£TTL μ‘°νrandom()μ μ¬μ©ν΄ λλ€ν νλ₯ λ‘ TTLμ κ°μμν΄
→ λ§μ½ TTL - λλ€ κ° > 0μ΄λ©΄ μΊμλ λ°μ΄ν°λ₯Ό κ·Έλλ‘ μ¬μ©
→ κ·Έλ μ§ μλ€λ©΄ DBμμ λ°μ΄ν°λ₯Ό κ°μ Έμ μΊμμ μ μ₯
↓
2οΈβ£κ²°κ³Όμ μΌλ‘ μΊμκ° μμ ν λ§λ£λκΈ° μ μ μΌλΆ μμ²μ΄ 미리 μΊμλ₯Ό κ°±μ νλλ‘ μ λ
μ΄λ¬ν λμ λ°©μμ ν΅ν΄μ μ¬λ¬ μ ν리μΌμ΄μ μ΄ λμμ DBλ₯Ό μ‘°ννλ λ¬Έμ λ₯Ό λ°©μ§νκ³ μΊμ κ°±μ μ λΆμ°νμ¬ λμ DB λΆνλ₯Ό μ€μΌ μ μλ€.
(π¨μ΄λ, μ μ ν expiry_gap μ€μ μ΄ μ€μνλ€.)
3οΈβ£ PER(Probabilistic Early Refresh) μκ³ λ¦¬μ¦
μΊμ μ€ν¬νΌλνμμ λ°©μ§νκΈ° μν΄ μΊμκ° λ§λ£λκΈ° μ μ νλ₯ μ μΌλ‘ λ°μ΄ν°λ₯Ό κ°±μ νλ κΈ°λ²
μΊμκ° λ§λ£λκΈ° μ§μ μλ§ λ°μ΄ν°λ₯Ό κ°±μ νλ κ²μ΄ μλλΌ, λ§λ£ μκ°μ΄ κ°κΉμμ§μλ‘ μ μ§μ μΌλ‘ κ°±μ νλ₯ μ λμ¬ DB λΆνλ₯Ό λΆμ°νλ λ°©μμ΄λ€.
πΉ 1. PER μκ³ λ¦¬μ¦μ ν΅μ¬ μμ
currentTime - ( timeToCompute * beta * log(rand()) ) > expiry
κ° λ³μμ μλ―Έλ λ€μκ³Ό κ°λ€.
- currentTime : νμ¬ λ¨μμλ μΊμ λ§λ£ μκ°
- timeToCompute : μΊμλ κ°μ λ€μ κ³μ°νλ λ° κ±Έλ¦¬λ μκ°
- beta (β) : κΈ°λ³Έμ μΌλ‘ 1.0λ³΄λ€ ν° κ°μΌλ‘ μ€μ κ°λ₯ (κ°±μ νλ₯ μ‘°μ )
- rand() : 0 ~ 1 μ¬μ΄μ λλ€ κ°μ λ°ννλ ν¨μ
- expiry : ν€λ₯Ό μ¬μ€μ ν λ μλ‘ μ μ©ν λ§λ£ μκ°
πΉ2. λμ μ리
1οΈβ£ currentTimeμ΄ expiryμ κ°κΉμΈμλ‘ rand()λ₯Ό ν΅ν΄ 무μμ νλ₯ λ‘ μΊμλ₯Ό κ°±μ ν μ§ κ²°μ
↓
2οΈβ£ log(rand()) κ°μ μ¬μ©νμ¬ λ§λ£ μκ°μ κ°κΉμμ§μλ‘ κ°±μ νλ₯ μ μ μ§μ μΌλ‘ μ¦κ°
↓
3οΈβ£ beta κ°μ μ‘°μ νμ¬ κ°±μ μ΄ λ λΉ λ₯΄κ² λλ λλ¦¬κ² μΌμ΄λλλ‘ μ‘°μ κ°λ₯
↓
4οΈβ£ currentTimeμμ timeToCompute * beta * log(rand())λ₯Ό λΉΌμ λμ¨ κ°μ΄ expiryλ³΄λ€ μλ€λ©΄ μΊμκ° λ§λ£λκΈ° μ μ κ°±μ μν
μ¦, μμ ν λ§λ£λκΈ° μ μ μΌμ νλ₯ λ‘ μΊμλ₯Ό 미리 κ°±μ νμ¬ μΊμ μ€ν¬νΌλ νμμ λ°©μ§νλ λ°©μμ΄λ€.
π μΆμ²
<κ°λ°μλ₯Ό μν λ λμ€> - κΉκ°λ¦Ό
'Redis' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[Redis] λΆμ°λ½μ κΉκ² λ€λ€λ³΄μ. (RedLock, Redisson) (2) | 2025.07.10 |
---|---|
λ λμ€ μΊμ± μ λ΅, μΊμ λ§λ£, maxmemory-policy (3) | 2025.02.04 |
Redisλ? (λ λμ€κ° μ±κΈμ°λ λλ‘ λμνλ μ΄μ ) (0) | 2025.01.30 |