2 minute read

κ³„μΈ΅ν˜•(μΉ΄ν…Œκ³ λ¦¬ μ„±) 데이터와 캐싱

였늘 ν¬μŠ€νŒ… ν•  λ‚΄μš©μ€ κ³„μΈ΅ν˜• 데이터λ₯Ό λ ˆλ””μŠ€ μΊμ‹œλ₯Ό μ΄μš©ν•˜μ—¬ 효율적으둜 κ°œμ„ ν–ˆλ˜ κ²½ν—˜μ— λŒ€ν•΄μ„œ κ°„λ‹¨ν•˜κ²Œ ν›„κΈ°λ₯Ό 남기렀고 ν•©λ‹ˆλ‹€.

λ¨Όμ € μ—¬κΈ°μ„œ λ§ν•˜λŠ” κ³„μΈ΅ν˜• λ°μ΄ν„°λž€ μ•„λž˜μ™€ 같이 ν•˜λ‚˜μ˜ ν…Œμ΄λΈ” λ‚΄μ—μ„œ, λΆ€λͺ¨ - μžμ‹ κ°„μ˜ 관계가 μ •μ˜λœ ν˜•νƒœλ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

νŠΉμ • μžμ‹μ΄ μ£Όμ–΄μ‘Œμ„ λ•Œ, μ΅œμƒμœ„ λΆ€λͺ¨λ₯Ό μ•Œμ•„μ•Ό ν•˜λŠ” κ²½μš°κ°€ λ°œμƒν•œλ‹€λ©΄ μ–΄λ–»κ²Œ λ‘œμ§μ„ ν’€μ–΄λ‚΄λŠ” 게 μ’‹μ„κΉŒμš”?

Mysql μ—μ„œ μ œκ³΅ν•˜λŠ” μž¬κ·€μ  CTE λ₯Ό μ‚¬μš©ν•˜λ©΄ μ–΄λ–¨κΉŒμš”?

μ΅œκ·Όμ— Real Mysql 2 ꢌ μŠ€ν„°λ””λ₯Ό μ§„ν–‰ν•˜κ³  μžˆλŠ” 김에 ν•œλ²ˆ μž¬κ·€μ  CTE 쿼리λ₯Ό μž‘μ„±ν•΄λ³ΌκΉŒμš”!?

with recursive cte as (
    select id, name, parent_id, id as root_id
    from category
    where parent_id is null

    union all

    select child.id,
           child.name,
           child.parent_id,
           root.root_id
    from category child
         inner join cte root
                      on child.parent_id = root.id)
select cte.id, cte.name, root_id
from cte

μœ„μ™€ 같은 쿼리둜 μ‰½κ²Œ κ΅¬ν˜„ν•  수 μžˆκ² κ΅°μš”!

ν•˜μ§€λ§Œ, QueryDsl, JPA μ—μ„œλŠ” μž¬κ·€μ  CTE λ₯Ό κ³΅μ‹μ μœΌλ‘œ μ œκ³΅ν•˜κ³  μžˆμ§€ μ•ŠμœΌλ―€λ‘œ

@Query μ–΄λ…Έν…Œμ΄μ…˜ λ‚΄μ—μ„œ 쿼리λ₯Ό λ¬Έμžμ—΄λ‘œ 잘 μž‘μ„±ν•΄μ„œ λ„€μ΄ν‹°λΈŒ 쿼리둜 싀행해도둝 ν•΄μ•Όλ§Œ ν•˜κ² μ£ .

ν•˜μ§€λ§Œ 이 방법은 λ¬Έμžμ—΄λ‘œ 쿼리λ₯Ό μž‘μ„±ν•˜λ‹€λ³΄λ‹ˆ,

쿼리에 였λ₯˜κ°€ μžˆμ—ˆμ–΄λ„ 컴파일 λ‹¨κ³„μ—μ„œ μž‘μ§€ λͺ»ν•œλ‹€λŠ” 치λͺ…적인 단점이 μžˆμŠ΅λ‹ˆλ‹€.

μ‹€μ œλ‘œ ν•΄λ‹Ή 쿼리 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” μ‹œμ μ— 였λ₯˜κ°€ λ°œμƒν•  수 밖에 μ—†λŠ”λ°μš”,

μ΄λŸ¬ν•œ κ΅¬μ‘°λŠ” μΆ”ν›„ μœ μ§€λ³΄μˆ˜ν•˜λŠ” κ΄€μ μ—μ„œ 쒋지 μ•Šμ„ 게 λΆ„λͺ…ν•˜λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

λ‹€λ₯Έ 방법은 μ—†μ„κΉŒμš”?

λ§Œμ•½ ν•΄λ‹Ή ν…Œμ΄λΈ”μ— λŒ€ν•΄μ„œ read μ—°μ‚°λ§Œ λ°œμƒν•œλ‹€κ³  κ°€μ •ν•œλ‹€λ©΄ 캐싱을 해두어 μ‚¬μš©ν•΄λ„ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€.

image

μΊμ‹œ λ©”λͺ¨λ¦¬λŠ” 보톡 λ ˆλ””μŠ€λ₯Ό 많이 μ‚¬μš©ν•˜λŠ”λ°μš”,

인메λͺ¨λ¦¬ db 이기 λ•Œλ¬Έμ— λΉ λ₯Έ I/O κ°€ κ°€λŠ₯ν•˜λ©°, μ €μž₯λ˜λŠ” λ°μ΄ν„°λ§ˆλ‹€μ˜ ttl 을 λ³„λ„λ‘œ μ§€μ •ν•΄μ€„μˆ˜λ„ 있고

μ‚¬μš©μ΄ 맀우 κ°„νŽΈν•˜λ©° λ ˆνΌλŸ°μŠ€λ„ λ‹€μ–‘ν•œ 점이 μž₯점인 것 κ°™μ•„μš”.

캐싱을 적절히 μ‚¬μš©ν•˜λ©΄ API μ„±λŠ₯을 λ†’μ΄λŠ” 데에 μ•„μ£Ό 쒋은 효과λ₯Ό λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.


λ§Œμ•½μ— μΉ΄ν…Œκ³ λ¦¬ ν…Œμ΄λΈ”μ— λŒ€ν•œ update / delete κΈ°λŠ₯이 μΆ”κ°€κ°€ λœλ‹€λ©΄

TTL λ™μ•ˆ 데이터 정합성이 λ§žμ§€ μ•ŠλŠ” λ¬Έμ œκ°€ λ°œμƒν•  것 κ°™μŠ΅λ‹ˆλ‹€.

이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œλŠ” μΉ΄ν…Œκ³ λ¦¬μ— λŒ€ν•œ update / delete λ₯Ό μˆ˜ν–‰ν•  λ•Œ cache 에 μ €μž₯된 데이터도 μˆ˜μ •ν•΄μ„œ 싱크λ₯Ό λ§žμΆ”μ–΄μ£ΌλŠ” 방법을 μ‚¬μš©ν•˜κ±°λ‚˜,

ν˜Ήμ€ λ¬΄νš¨ν™”ν•΄μ„œ λ‹€μ‹œ μΊμ‹±ν•˜κ²Œλ” ν•˜λŠ” 것도 κ°€λŠ₯ν•˜κ² μ£ .

상황에 따라 적절히 선택해주면 될 것 κ°™μ•„μš”!

또 ν•˜λ‚˜ κ³ λ €ν•΄μ•Ό ν•  점은 μΊμ‹œ μŠ€νƒ¬ν”Όλ“œ(Cache Stampede) 에 μ˜ν•œ duplicated read/write κ°€ λ°œμƒν•˜μ—¬ μ„±λŠ₯이 μ €ν•˜λ  μˆ˜λ„ μžˆλ‹€λŠ” κ±°μ—μš”.

image

λ‹¨μˆœνžˆ μΊμ‹œ λ©”λͺ¨λ¦¬μ—μ„œ 데이터λ₯Ό get ν•˜κΈ°λ³΄λ‹€λŠ”,

API 호좜 μ‹œμ μ—,

TTL 이 λ§Œλ£Œλ˜κΈ°κΉŒμ§€ μ–Όλ§ˆ 남지 μ•Šμ•˜λ”λΌλ©΄, μƒˆλ‘œ μΊμ‹±ν•˜λ„λ‘ ν•˜λ©΄ ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

TTL 이 λ§Œλ£Œλ˜κΈ°κΉŒμ§€ μ–Όλ§ˆ 남지 μ•Šμ•˜λŠ”μ§€ νŒλ‹¨ν•˜λŠ” 방법은 주둜 PER ( Probabilistic Early Recomputation ) Algorithm 을 μ‚¬μš©ν•˜λŠ” 것 κ°™μ•„μš”.

λ§ˆμ§€λ§‰μœΌλ‘œ μΊμ‹œ λ°μ΄ν„°μ˜ μ’…λ₯˜λ§ˆλ‹€ λ‹€λ₯Έ TTL 을 μ μš©ν•΄μ•Όλ§Œ ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒμš”?

ν˜„μž¬μ˜ μš”κ΅¬μ‚¬ν•­μ—μ„œλŠ” μΊμ‹œ λ°μ΄ν„°λ§ˆλ‹€ λ³„λ„μ˜ TTL 을 μ μš©ν•˜μ§€ μ•Šμ•„λ„ 되기 λ•Œλ¬Έμ—,

RedisConfig μ—μ„œ μΌκ΄„μ μœΌλ‘œ λ™μΌν•œ TTL 을 μ„€μ •ν•΄λ‘μ—ˆμ§€λ§Œ μ•žμœΌλ‘œλŠ” μΊμ‹œ λ°μ΄ν„°λ§ˆλ‹€ TTL 을 λ‹€λ₯΄κ²Œ μ£Όμ–΄μ•Ό ν•  상황이 생길 μˆ˜λ„ μžˆμ„ 것 κ°™μ•„μš”.

그러면 μΊμ‹œ 데이터 μ’…λ₯˜λ§ˆλ‹€ redisCacheManager 을 λ³„λ„λ‘œ Bean 으둜 λ“±λ‘ν•˜μ—¬ μ‚¬μš©ν•˜λ©΄ λ κΉŒμš”?

λ¬Όλ‘  κ°€λŠ₯ν•˜μ§€λ§Œ, 쒋은 κ΅¬μ‘°λŠ” μ•„λ‹Œ 것 κ°™μŠ΅λ‹ˆλ‹€.

ν•˜λ£¨ν•˜λ£¨κ°€ μ‹œκ°„μ΄ λΆ€μ‘±ν•˜λ„€μš”..!! πŸ₯²

μΆ”ν›„ μ—…λ‘œλ“œν•  ν¬μŠ€νŒ…μ—μ„œ 깊게 닀루어보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€!

Categories:

Updated:

Leave a comment