Dev-Kyuu
article thumbnail

이번주 λ©˜ν† λ§ μ‹œ λ©˜ν† λ‹˜κ»˜μ„œ λ‚΄κ°€ λ§Œλ“  Redis Cache + Scheduler + Spring Batchλ₯Ό μ΄μš©ν•œ Update처리 둜직 κ΄€λ ¨ν•΄μ„œ

λ™μ‹œμ— μ—¬λŸ¬ μ„œλ²„κ°€ μ ‘κ·Όν•˜λ©΄ μ–΄λ–»κ²Œ 될 것 κ°™λ‚˜μš”? λΌλŠ” μ§ˆλ¬Έμ„ λ˜μ Έμ£Όμ…¨κ³  λ©˜ν† λ§ μ§μ „κΉŒμ§€ ν•΄λ‹Ή λ‘œμ§μ„ λ§Œλ“€μ–΄λ‚΄λŠ”λ°μ— κΈ‰κΈ‰ν–ˆλ˜ λ‚˜λŠ”

 

πŸ™‹πŸ» Redisμ„œλ²„λ₯Ό 각 λ‘œμ»¬μ— μƒμ„±ν•œλ‹€λ©΄ 아무 λ¬Έμ œκ°€ 없지 μ•Šμ„κΉŒμš© ? 이라고 λŒ€λ‹΅μ„ ν•˜μ˜€λ‹€.

 

μ• κΈ°λ“€ μ„Έλͺ…이 였락기 ν•˜λ‚˜ 가지고 μ‹Έμš°κ³ μžˆλŠ”λ° 이걸 μ–΄λ–»κ²Œ μ‚¬μ΄μ’‹κ²Œ λ‚˜λˆ μ„œ 놀도둝 ν•  수 μžˆμ„κΉŒ? λŒ€ν•œ μ§ˆλ¬Έμ„ 

였락기λ₯Ό μ„Έκ°œλ₯Ό 두면 λ˜μ§€ μ•Šλ‚˜μš”?의 닡변을 ν•œ μ…ˆμž„

λŒ€λ‹΅μ΄ ν‹€λ Έλ‹€κ³  ν• μˆ˜λŠ” μ—†μ§€λ§Œ λ™μ‹œμ„± μ œμ–΄ 뢀뢄을 μ•„μ˜ˆ 생각도 μ•ˆν•œκ±Έ λ°”λ‘œ λ“€ν‚¬μˆ˜ μžˆλŠ” κ΅¬λ¬Έμ΄μ˜€λ‹€ 

γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹γ…‹

 

κ·Έλž˜μ„œ ν•œλ°œ λŠ¦μ—ˆμ§€λ§Œ μ„±λŠ₯ κ°œμ„ μ„ μœ„ν•΄μ„œ κ³΅λΆ€ν•΄λ³΄λŠ” 뢄산락 기법 πŸ’ͺ🏻

 


πŸ– 뢄산락

: μ„œλ²„κ°€ μ—¬λŸ¬λŒ€μΈ μƒν™©μ—μ„œ λ™μΌν•œ 데이터에 λŒ€ν•œ 동기화λ₯Ό 보μž₯ν•˜κΈ° μœ„ν•΄μ„œ μ‚¬μš©

: μ„œλ²„κ°€ ν•œλŒ€κ°€ μ•„λ‹ˆλΌ μ—¬λŸ¬λŒ€μΈ 경우 μ—¬λŸ¬ μ„œλ²„λ‘œ APIκ°€ λΆ„μ‚° 호좜되게 λœλ‹€

: μ„œλ²„λ“€κ°„μ˜ λ™κΈ°ν™”λœ μ²˜λ¦¬κ°€ ν•„μš”ν•˜κ³ , μ—¬λŸ¬ μ„œλ²„μ— κ³΅ν†΅λœ 락을 μ μš©ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— 뢄산락을 μ‚¬μš©ν•œλ‹€.

 

πŸ™‹πŸ» μ–΄λ–€ κ²½μš°μ— 뢄산락 μ‚¬μš©μ΄ ν•„μš”ν• κΉŒ?

λ™μ‹œμ— 2개의 νŠΈλžœμž­μ…˜μ΄ ν•˜λ‚˜μ˜ λ ˆμ½”λ“œμ— μ ‘κ·Όν•˜λŠ” 경우 같은 λ ˆμ½”λ“œ 버전을 κ°–κ²Œ λ˜λŠ”λ°,
μ΄λ•Œ 2개의 νŠΈλžœμž­μ…˜μ΄ λ™μ‹œμ— 데이터λ₯Ό λ³€κ²½ν•œλ‹€λ©΄ ν•œ νŠΈλžœμž­μ…˜μ—μ„œ λ³€κ²½ν•œ 데이터 λ³€κ²½κ°’ κ²°κ³ΌλŠ” μžƒμ–΄λ²„λ¦¬κ³ 
μš°μ„ μ μœΌλ‘œ 처리 ν•œ νŠΈλžœμž­μ…˜μ˜ 결과만 λ‚¨κ²Œλ˜κ±°λ‚˜, λ§ˆμ§€λ§‰μœΌλ‘œ μ²˜λ¦¬ν•œ 결과만 λ‚¨κ²Œ λœλ‹€ .. ! 

상황에 따라 λ§ˆμ§€λ§‰ 결과만 반영되면 λ˜λŠ” κ²½μš°μ—λŠ” 뢄산락 처리λ₯Ό λ³„λ„λ‘œ 해주지 μ•Šμ•„λ„ λ˜μ§€λ§Œ,
처리된 νŠΈλžœμž­μ…˜μ˜ κ²°κ³Όκ°€ μ΄ν›„μ˜ νŠΈλžœμž­μ…˜μ˜ 결과에도 영ν–₯이 μžˆλ‹€λ©΄ νŠΈλžœμž­μ…˜μ΄ 순차적으둜 처리 λ˜μ–΄μ•Όν•œλ‹€.

 

μ—¬λŸ¬κ°€μ§€ 기술 쀑 λ™μ‹œμ— μš”μ²­μ΄ 와도 μž‘μ—…μ΄ λˆ„λ½λ˜μ§€ μ•Šκ³ , μ •μƒμ μœΌλ‘œ 처리 λ˜μ–΄μ•Όν•œλ‹€λŠ” 뢀뢄에 μ΄ˆμ μ„ λ§žμΆ˜λ‹€λ©΄ 

μ‚¬μš©ν•  수 μžˆλŠ” κΈ°μˆ λ“€μ€ μ•„λž˜μ™€ κ°™λ‹€.

 

  • JPA Version 방식을 ν™œμš©ν•œ 낙관적 락(Optimistic Locking)
  • MySQL의 User Lock ν™œμš©ν•˜κΈ°
  • Redis Java Client μ€‘μ˜ ν•˜λ‚˜μΈ Redisson의 RLock을 ν™œμš©ν•˜κΈ°

1) 낙관적 락(Optimistic Locking)

 

낙관적락은 이전 ν¬μŠ€νŒ…μ˜ λ‚΄μš©μ²˜λŸΌ μΆ©λŒμ„ κ°μ§€ν•˜μ—¬ 좩돌이 λ°œμƒν•  경우 μž¬μ‹œλ„ν•˜κ±°λ‚˜, 좩돌이 λ°œμƒν•œ 데이터에 λŒ€ν•΄μ„œ λ‘€λ°±ν•˜λŠ” μž‘μ—…μ„ λ³„λ„λ‘œ κ΅¬ν˜„ν•΄μ•Όν•œλ‹€.

 

2) Mysql의 User Lock

 

μ‚¬μš©μžκ°€ νŠΉμ • λ¬Έμžμ—΄μ— Lock을 κ±Έ 수 μžˆλŠ” Lock으둜 μ–΄λ– ν•œ μž‘μ—…μ΄ μ˜€λž˜κ±Έλ¦°λ‹€λ©΄ μž‘μ—… μ‹œκ°„λ§ŒνΌ Lock을 μ†Œμœ ν•˜λŠ” 기법

Connetion Poolκ³Ό Lock을 νšλ“ν•˜λŠ” DB Connetion Pool을 λΆ„λ¦¬ν•˜λŠ” μž‘μ—…μ΄ ν•„μš”ν•˜λ‹€.

 

3) Redis 기반 뢄산락

  • Lettuce Client의 뢄산락 기법 :
    • Lock의 νƒ€μž„μ•„μ›ƒμ΄ μ§€μ •λ˜μ–΄μžˆμ§€ μ•ŠμŒ
    • μŠ€ν•€λ½μ„ μ‚¬μš©ν•œ κ΅¬ν˜„ κΈ°λ²•μœΌλ‘œ 락을 νšλ“ν•˜μ§€ λͺ»ν•œ 경우 Redisμ—κ²Œ 락을 νšλ“ν•˜κΈ° μœ„ν•΄ 계속 μš”μ²­μ„ λ³΄λ‚΄μ„œ μ„œλ²„ λΆ€ν•˜ λ°œμƒ
    • Lock-Unlockν•˜λŠ” 과정이 μ•„μ£Ό μ§§μ•„μ„œ 락 ν•˜λŠ” κ²½μš°κ°€ λ“œλ¬Έ κ²½μš°μ—λŠ” μœ μš©ν•¨
  • Redisson Client의 뢄산락 기법 : 
    • Lock에 νƒ€μž„μ•„μ›ƒμ„ 지정할 수 μžˆμ–΄μ„œ λ¬΄ν•œμ • λŒ€κΈ° μƒνƒœλ‘œ 빠질 수 μžˆλŠ” μœ„ν—˜μ΄ μ—†μŒ
    • pub/sub방식을 μ‚¬μš©ν•˜λ―€λ‘œ μŠ€ν•€λ½μ„ μ‚¬μš©ν•˜μ§€ μ•ŠμŒ 
      -> 락이 ν•΄μ œλ˜λ©΄ 락을 subscribeν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ 락이 ν•΄μ œλ˜μ—ˆλ‹€λŠ” μ‹ ν˜Έλ₯Ό λ³΄λ‚΄μ€Œ
      -> ν΄λΌμ΄μ–ΈνŠΈλ“€μ€ 더이상 락 νšλ“ 확인 μš”μ²­μ„ redis둜 보내지 μ•ŠμŒ

πŸŒ€ 0. 별첨 | μŠ€ν•€λ½

: μŠ€ν•€λ½μ€ 락을 걸지 λͺ»ν•˜λ©΄ λ¬΄ν•œ 루프λ₯Ό λŒλ©΄μ„œ 계속 락을 μ–»μœΌλ €κ³  μ‹œλ„ν•˜λŠ” 동기화 기법

 

μ™Όμͺ½  : Lock / 였λ₯Έμͺ½ : Spin Lock

 

: '쑰금만 기닀리면 λ°”λ‘œ μ“Έ 수 μžˆλŠ”λ° ꡳ이 Context Switching으둜 λΆ€ν•˜λ₯Ό 쀄 ν•„μš”κ°€ μžˆλ‚˜?'λΌλŠ” μ»¨μ…‰μœΌλ‘œ 개발된 기법

: 락을 얻지 λͺ»ν• κ²½μš° μ‰¬μ§€μ•Šκ³  계속 락을 μ–»μœΌλ €λŠ” μ‹œλ„λ₯Ό ν•˜κΈ° λ•Œλ¬Έμ— λ½ν•˜λŠ” κ²½μš°κ°€ μž¦μ€ 경우 μ„œλ²„μ— λ§Žμ€ λΆ€ν•˜λ₯Ό 쀌

: Lock-Unlockν•˜λŠ” 과정이 μ•„μ£Ό μ§§μ•„μ„œ 락 ν•˜λŠ” κ²½μš°κ°€ λ“œλ¬Έ κ²½μš°μ—λŠ” μœ μš©ν•¨

 

κ²°λ‘  

 

- CPUλ‚˜ ν•˜λ‚˜μ˜ μ½”μ–΄λ§Œ μžˆλŠ” κ²½μš°μ—λŠ” μœ μš©ν•˜μ§€ μ•ŠμŒ

- μŠ€ν•€λ½μ€ 기본적으둜 λ¬΄ν•œ for루프λ₯Ό λŒλ©΄μ„œ Lock을 κΈ°λ‹€λ¦¬λ―€λ‘œ ν•˜λ‚˜μ˜ μŠ€λ ˆλ“œκ°€ lock을 μ˜€λž«λ™μ•ˆ 가지고 μžˆλ‹€λ©΄,
   λ‹€λ₯Έ Blocking된 μŠ€λ ˆλ“œλŠ” busy Waiting을 ν•˜λ―€λ‘œ CPUλ₯Ό μ“ΈλŒ€μ—†μ΄ λ‚­λΉ„ν•˜κ²Œ 됨

   ( Busy Waiting = λ¬΄ν•œ 루프λ₯Ό λŒλ©΄μ„œ μ΅œλŒ€ν•œ λ‹€λ₯Έ μŠ€λ ˆλ“œμ—κ²Œ CPUλ₯Ό μ–‘λ³΄ν•˜μ§€ μ•ŠλŠ” 것 )

 

  


Redis μ„œλ²„λ₯Ό 이미 κ΅¬μΆ•ν•΄λ‘μ—ˆκΈ° λ•Œλ¬Έμ— Redis의 두 기법 쀑에 고민해보면 될 것 같은데 

μ–΄λ–€ Lock 기법을 μ‚¬μš©ν•˜λŠ”κ²Œ λ§žμ„μ§€ 쑰금 더 고민이 ν•„μš”ν•  것 κ°™λ‹€ πŸ€”

'πŸ“ JPA' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

λ™μ‹œμ„± μ œμ–΄ Chap 1 | 비관적 락, 낙관적 락 ?  (0) 2023.01.24
JPA | JPA With Native Query  (0) 2022.12.14
JPA | 연관관계  (0) 2022.12.08
profile

Dev-Kyuu

@kyuu_ng

ν¬μŠ€νŒ…μ΄ μ’‹μ•˜λ‹€λ©΄ "μ’‹μ•„μš”β€οΈ" λ˜λŠ” "κ΅¬λ…πŸ‘πŸ»" ν•΄μ£Όμ„Έμš”!