TIL

[TIL] 뢄산락

s00ng 2024. 10. 21. 01:56

πŸ“Œ 뢄산락 μ΄λž€?

 λ‹€μˆ˜μ˜ μ„œλ²„(λ˜λŠ” ν”„λ‘œμ„ΈμŠ€)κ°€ λ™μ‹œμ— 같은 μžμ›μ„ μ ‘κ·Όν•  λ•Œ, λ°œμƒν•  수 μžˆλŠ” λ™μ‹œμ„± 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜λŠ” 동기화 λ§€μ»€λ‹ˆμ¦˜. ‘μ€‘μ•™ν™”λœ 락 관리 μ‹œμŠ€ν…œ' μ„ μ‚¬μš©ν•˜μ—¬ λΆ„μ‚°λœ ν™˜κ²½μ—μ„œ 락을 κ±Έκ³  κ΄€λ¦¬ν•œλ‹€.

  • 락 관리 : λ§Œλ£Œμ‹œκ°„ μ„€μ •, 락 κ°±μ‹ , 락 ν•΄μ œ
  • μž₯점: μ„œλ²„ λΆ„μ‚° ν™˜κ²½μ—μ„œλ„ ν”„λ‘œμ„ΈμŠ€λ“€μ˜ μ›μžμ  연산이 κ°€λŠ₯.

  • 락을 νšλ“ν•œ ν”„λ‘œμ„ΈμŠ€ λ˜λŠ” μŠ€λ ˆλ“œ 만이 κ³΅μœ μžμ›(or Critical Section)에 μ ‘κ·Όν•  수 μžˆλ„λ‘ ν•˜λŠ” 것.
  • νŠΉμ • μžμ›μ— λŒ€ν•œ 접근을 μ œμ–΄ν•˜κΈ° μœ„ν•΄ λ„€νŠΈμ›Œν¬λ₯Ό 톡해 락 μ„€μ •

 

πŸ“Œ 뢄산락을 κ΅¬ν˜„ν•˜λŠ” μ—¬λŸ¬κ°€μ§€ 방법

  • μ •ν™•νžˆ λ§ν•˜μžλ©΄, 락을 κ΄€λ¦¬ν•˜λŠ” 쀑앙 관리 μ‹œμŠ€ν…œμ„ λ¬΄μ—‡μœΌλ‘œ ν• μ§€

1) Zookeeper

 λΆ„μ‚° μ„œλ²„ κ΄€λ¦¬μ‹œμŠ€ν…œμœΌλ‘œ λΆ„μ‚° μ„œλΉ„μŠ€ λ‚΄ μ„€μ • 등을 κ³΅μœ ν•΄μ£ΌλŠ” μ‹œμŠ€ν…œ.ν•˜μ§€λ§Œ 좔가적인 인프라 ꡬ성이 ν•„μš”ν•˜κ³  μ„±λŠ₯ νŠœλ‹μ„ μœ„ν•œ λŸ¬λ‹μ»€λΈŒκ°€ 쑴재. ν˜„μž¬λŠ” 뢄산락 이외에 μ΄μš©ν•  μš©λ„κ°€ μ—†μœΌλ―€λ‘œ μ΄μš©ν•˜μ§€ μ•ŠλŠ”κ²ƒμ΄ μ’‹λ‹€κ³  νŒλ‹¨.

 

2) MySQL

MySQL은 좔가적인 인프라 ꡬ성없이 λ¬Έμžμ—΄λ‘œ κ±°λŠ” User Level Lock으둜 뢄산락을 직접 κ΅¬ν˜„ν•  수 μžˆλ‹€. ν•˜μ§€λ§Œ μ•„λž˜μ˜ 단점이 μžˆλ‹€.

  • 락을 μžλ™μœΌλ‘œ λ°˜λ‚©ν•  수 μ—†μ–΄(timeout X) λͺ…μ‹œμ μœΌλ‘œ 락을 release μ‹œμΌœμ•Ό ν•œλ‹€.
  • DBμ—μ„œ 락을 κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— DB에 뢀담이 μ—¬μ „νžˆ μ‘΄μž¬ν•œλ‹€.
  • 락 νšλ“ μ‹œλ„λŠ” μŠ€ν•€λ½μœΌλ‘œ κ΅¬ν˜„ν•΄μ•Όν•˜κΈ° λ•Œλ¬Έμ— WAS에도 뢀담이 μ‘΄μž¬ν•œλ‹€.

 

3) Redis (선택)

Zookeeper와 λ§ˆμ°¬κ°€μ§€λ‘œ λ³„λ„μ˜ 인프라λ₯Ό κ΅¬μΆ•ν•˜κ³  κ΄€λ¦¬ν•΄μ•Όν•˜μ§€λ§Œ μ•„λž˜μ˜ μž₯점이 μžˆλ‹€.

  • 인메λͺ¨λ¦¬ DB둜 속도가 λΉ λ₯΄λ‹€.(μ΄ˆλ‹Ή 100,000 QPS 의 속도)
  • μ‹±κΈ€μŠ€λ ˆλ“œ λ°©μ‹μœΌλ‘œ λ™μ‹œμ„± λ¬Έμ œκ°€ ν˜„μ €νžˆ 적닀.
  • μΊμ‹œ μ €μž₯μ†Œλ‘œ ν™œμš©μ΄ κ°€λŠ₯ν•˜λ‹€.(λ‹€μ–‘ν•œ 자료ꡬ쑰 지원)

 

πŸ˜€ 뢄산락 κ΅¬ν˜„ λ°©μ‹μœΌλ‘œ λ ˆλ””μŠ€λ₯Ό μ„ νƒν•œ 이유

 

βœ… μ§€κΈˆκΉŒμ§€μ˜ 문제 & μ•žμœΌλ‘œμ˜ λͺ©ν‘œ

πŸ“ 문제

 

[ 결제 μƒν’ˆ 재고 관리]

⇒ 비관적 락을 μ΄μš©ν•΄ κ΅¬ν˜„ν–ˆμ—ˆλ‹€.

  • DB μžμ²΄μ— 락을 κ±°λŠ” 방식이라 μ‘λ‹΅μ‹œκ°„μ΄ λ™μ‹œ 200건 μ²˜λ¦¬μ— 6초둜 λŠ¦μ–΄μ§.
  • λ™μ‹œ μš”μ²­ 건수λ₯Ό 늘리면, timeout으둜 μ‹€νŒ¨ν•˜λŠ” μš”μ²­μ΄ λ§Žμ•„μ§
  • DB μ„±λŠ₯에 따라, 단일 병λͺ©μ§€μ μ΄ λ˜μ–΄λ²„λ¦΄ 수 μžˆλ‹€.
  • νŠΈλžœμž­μ…˜μ΄ μ •μƒμ μœΌλ‘œ μ’…λ£Œλ˜μ§€ μ•ŠμœΌλ©΄, DB에 Lock이 κ±Έλ¦° μƒνƒœλ‘œ λ‚¨μ•„μžˆμ–΄ λ°λ“œλ½μ˜ μœ„ν—˜μ„±μ΄ μžˆμ—ˆλ‹€. (이건 DBMSκ°€ νŠΈλžœμž­μ…˜ timeout으둜 μ²˜λ¦¬ν•¨)

 

[ λŒ€κΈ°μ—΄ 순번 처리 ]

⇒ Redis의 Sorted Set을 μ΄μš©ν•΄ κ΅¬ν˜„ν•œ λŒ€κΈ°μ—΄μ—μ„œ ν˜„μž¬ λŒ€κΈ°μ—΄μ— μžˆλŠ” μ‚¬μš©μžλ₯Ό μ‘°νšŒν•˜κ³  μ‚¬μš©μžμˆ˜+1

  • rankλ₯Ό μ‘°νšŒν•΄μ„œ λ¦¬ν„΄ν•˜λŠ” κ³Όμ •μ—μ„œ λ™μ‹œμ„± μ œμ–΄κ°€ λ˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ λ°œμƒ.
  • κ΅¬μ²΄μ μœΌλ‘œλŠ” μ‚¬μš©μž A와 μ‚¬μš©μž Bκ°€ λ™μ‹œμ— κ΅¬λ§€ν•˜κΈ° λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œ, λ‘˜λ‹€ 순번이 1둜 λ–΄λ‹€.

 

πŸ“ λͺ©ν‘œ

  • Redisλ₯Ό μ΄μš©ν•΄ 뢄산락을 κ΅¬ν˜„ν•΄μ„œ 결제 μƒν’ˆ 재고 κ΄€λ¦¬μ‹œ 응닡속도 ν–₯상(정말 μ€„μ–΄λ“œλŠ”μ§€ 체크 해봐야함)
  • λŒ€κΈ°μ—΄ λ™μ‹œμ„± μ œμ–΄

 

🐀 Redisλ₯Ό μ΄μš©ν•œ 뢄산락 κ΅¬ν˜„

βœ”οΈ λŒ€ν‘œμ μΈ μžλ°”μ˜ Redis ν΄λΌμ΄μ–ΈνŠΈ

Lettuce

  • Spring 2.x.x 이후뢀터, default둜 μ‚¬μš©λ˜λŠ” redis ν΄λΌμ΄μ–ΈνŠΈ
  • Lettuce둜 뢄산락을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” setnx , setex 등을 μ΄μš©ν•΄μ„œ 뢄산락을 직접 κ΅¬ν˜„ν•΄μ•Όν•¨
  • κ°œλ°œμžκ°€ 직접 retry, timeoutκ³Ό 같은 κΈ°λŠ₯을 κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” λ²ˆκ±°λ‘œμ›€μ΄ 있음

μŠ€ν•€λ½μ΄λΌλŠ” μΌμ’…μ˜ polling 기법을 ν™œμš©ν•΄μ„œ Lock νšλ“μ„ μ‹œλ„ (주기적으둜 계속 μš”μ²­)

 

Redission (선택)

  • RedLock μ•Œκ³ λ¦¬μ¦˜μ„ μžλ°”λ‘œ κ΅¬ν˜„ν•œ 라이브러리
  • λ³„λ„μ˜ Lock interface 지원. (락에 λŒ€ν•΄ timeoutκ³Ό 같은 μ„€μ • 지원)

⇒ Redis의 pub/sub κΈ°λŠ₯을 μ‚¬μš©ν•΄ Lock νšλ“μ„ μž¬μ‹œλ„.

  • Lock νšλ“μ„ μ‹€νŒ¨ν•˜λ©΄, Redission은 νŠΉμ • 채널을 κ΅¬λ…ν•˜κ³ , Lock이 λ‹€μ‹œ νšλ“ν•  수 μžˆλŠ” μƒνƒœκ°€ λλ‹€λŠ” 이벀트λ₯Ό λ°›μ•˜μ„ λ•Œ, λ‹€μ‹œ Lock νšλ“ μ‹œλ„

 

πŸ˜€ Redis client둜 Redission μ„ νƒν•œ 이유

 

βœ… Redission으둜 Redis ν΄λΌμ΄μ–ΈνŠΈ μ„€μ •ν•˜κΈ°

build.gradle에 μ˜μ‘΄μ„± μΆ”κ°€
implementation 'org.redisson:redisson-spring-boot-starter:3.18.0'