๐Ÿ–ฅ๏ธ ์ด์ปค๋จธ์Šคํ”„๋กœ์ ํŠธ/๐Ÿ› ๏ธ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

[ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…] ์ฟ ํฐ ๋ฐœ๊ธ‰ํ•˜๋‹ค ํ„ฐ์ง„ Deadlock, ๊ทธ๋ฆฌ๊ณ  Redisson์œผ๋กœ ํ•ด๊ฒฐํ•œ ์ด์•ผ๊ธฐ

carrot0911 2025. 5. 13. 11:43

๐Ÿ’ฃ ๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ ์ค‘ Deadlock ๋ฐœ์ƒ! ๊ทธ๋ฆฌ๊ณ  Redisson ๋ฝ๊นŒ์ง€ ๋„์ž…ํ•œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

 

์„ ์ฐฉ์ˆœ ํ• ์ธ ์ฟ ํฐ ๋ฐœ๊ธ‰ ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๋ฉด์„œ ๊ฒช์—ˆ๋˜ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๊ณผ์ •์„ ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค!
Deadlock์ด ์‹ค์ œ๋กœ ๋ฐœ์ƒํ–ˆ๋˜ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ์™€, ๋ฝ ์ „๋žต์„ ๊ณ ๋ฏผํ•˜๊ณ  ์ตœ์ข…์ ์œผ๋กœ Redisson ๋ฝ์„ ๋„์ž…ํ•˜๊ธฐ๊นŒ์ง€์˜ ์‹ค์ œ ๊ฒฝํ—˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ’€์–ด๋‚ธ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๊ธฐ๋ก์ด๋‹ค!

 

๐Ÿ›ซ  ๋ฌธ์ œ ์ƒํ™ฉ: Deadlock ๋ฐœ์ƒ ์‹คํ—˜

๊ธฐ๋ณธ์ ์ธ ์ฟ ํฐ ๋ฐœ๊ธ‰ API๋งŒ ์ž‘์„ฑํ•œ ์ƒํƒœ์—์„œ, ๋‹ค์ˆ˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ๋ฐœ๊ธ‰์„ ์š”์ฒญํ•˜๋ฉด ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ๊นŒ ๊ถ๊ธˆํ–ˆ๋‹ค.
๊ทธ๋ž˜์„œ JMeter๋ฅผ ์ด์šฉํ•ด ๊ฐ„๋‹จํ•œ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด ๋ดค๋‹ค.

ํ…Œ์ŠคํŠธ ์กฐ๊ฑด

ํ…Œ์ŠคํŠธ ์กฐ๊ฑด

ํ•ญ๋ชฉ ๊ฐ’
ํ…Œ์ŠคํŠธ ๋„๊ตฌ Apache JMeter
์Šค๋ ˆ๋“œ ์ˆ˜ 100๋ช…
๋ฃจํ”„ ํšŸ์ˆ˜ 1ํšŒ (1๋ช…๋‹น 1ํšŒ ๋ฐœ๊ธ‰ ์‹œ๋„)
์ฟ ํฐ ์ˆ˜๋Ÿ‰ 10๊ฐœ
๋Œ€์ƒ API /api/coupons/{couponId}/issue
๋ฝ ์ ์šฉ ์—ฌ๋ถ€ ์—†์Œ (๊ธฐ๋ณธ ๋ฐœ๊ธ‰ ๋กœ์ง)

โšก ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๊ฒฐ๊ณผ

ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ๋ฆฌ์ž๋งˆ์ž ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ์Ÿ์•„์กŒ๋‹ค..

Deadlock found when trying to get lock; try restarting transaction

์ƒ์„ธ ์—๋Ÿฌ ๋กœ๊ทธ๋ฅผ ์‚ดํŽด๋ดค๋”๋‹ˆ..

com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException:
Deadlock found when trying to get lock; try restarting transaction
SQL [update coupons set ... where id=?]

coupon.issueCount๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๊ณผ์ •์—์„œ Deadlock์ด ๋ฐœ์ƒํ•˜๊ณ , ์ผ๋ถ€ ํŠธ๋žœ์žญ์…˜์ด ๊ฐ•์ œ ๋กค๋ฐฑ๋˜๊ณ  ์žˆ์—ˆ๋‹ค..

๐Ÿ” Deadlock ์›์ธ ๋ถ„์„

Deadlock์ด ๋ฐœ์ƒํ•œ ์›์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
1. 100๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ์ฟ ํฐ ๋ฐœ๊ธ‰ ์š”์ฒญ
2. DB๋Š” ๋ชจ๋‘ ๊ฐ™์€ ์ฟ ํฐ์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๊ณ  ์‹œ๋„
3. row-level ๋ฝ์„ ์žก์œผ๋ ค๋‹ค๊ฐ€, ์„œ๋กœ ์ˆœ์„œ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ˆœํ™˜ ๋Œ€๊ธฐ๊ฐ€ ๋ฐœ์ƒ
4. ๊ฒฐ๊ณผ์ ์œผ๋กœ Deadlock ๊ฐ์ง€ → ์ผ๋ถ€ ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ

 

๐Ÿง  ์™œ ์ด๊ฑธ ์ค‘์š”ํ•˜๊ฒŒ ๋ด์•ผ ํ–ˆ์„๊นŒ?

๐Ÿ‘‰  ๋‹จ์ˆœํ•œ coupon.issueCount++ ๊ฐ™์€ ๋กœ์ง๋„ ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆฌ๋ฉด ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
๐Ÿ‘‰  race condition ๋ฟ ์•„๋‹ˆ๋ผ, Deadlock๊นŒ์ง€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ง์ ‘ ๊ฒฝํ—˜ํ–ˆ๋‹ค.
๐Ÿ‘‰  "์ž˜ ๋˜๊ฒ ์ง€"๋ผ๋Š” ๋ง‰์—ฐํ•œ ๋ฏฟ์Œ์ด ์•„๋‹ˆ๋ผ, ์‹ค์ œ ํ…Œ์ŠคํŠธ๋กœ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ตํ›ˆ์„ ์–ป์—ˆ๋‹ค.

 

๐Ÿงฉ ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•œ Lock ์ „๋žต ๊ณ ๋ฏผ

Deadlock์„ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๋™์‹œ์„ฑ ์ œ์–ด๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค.
๊ทธ๋ž˜์„œ ์—ฌ๋Ÿฌ Lock ์ „๋žต์„ ์ •๋ฆฌํ•˜๊ณ  ๋น„๊ตํ•ด ๋ดค๋‹ค.

์ „๋žต ์„ค๋ช… ์žฅ์  ๋‹จ์ 
๋น„๊ด€์  ๋ฝ
(Pessimistic Lock)
DB SELECT ... FOR UPDATE ์‚ฌ์šฉ ๊ฐ•๋ ฅํ•œ ์ •ํ•ฉ์„ฑ ๋ณด์žฅ
๋‹จ์ผ ์„œ๋ฒ„์—์„  ๋น ๋ฆ„
ํ™•์žฅ์„ฑ ๋ถ€์กฑ
DB ๋ณ‘๋ชฉ ๊ฐ€๋Šฅ์„ฑ
๋‚™๊ด€์  ๋ฝ
(Optimistic Lock)
๋ฒ„์ „ ํ•„๋“œ ๊ธฐ๋ฐ˜ ์ถฉ๋Œ ๊ฐ์ง€ ๋ฝ ์—†์ด ๋น ๋ฆ„ ์ถฉ๋Œ ์‹œ ์žฌ์‹œ๋„ ํ•„์š”
์‹ค์‹œ๊ฐ„์„ฑ ๋–จ์–ด์ง
Redisson ๋ถ„์‚ฐ ๋ฝ Redis๋ฅผ ์ด์šฉํ•œ ๊ธ€๋กœ๋ฒŒ ๋ฝ ๋ถ„์‚ฐ ํ™˜๊ฒฝ ๋Œ€์‘
์‹ค์‹œ๊ฐ„ ์ œ์–ด ๊ฐ€๋Šฅ
๋„คํŠธ์›Œํฌ ์˜ค๋ฒ„ํ—ค๋“œ
์„ค์ • ๋ณต์žก
๋ฉ”์‹œ์ง€ ํ ์ฒ˜๋ฆฌ Kafka ๋“ฑ์œผ๋กœ ์„ ์ฐฉ์ˆœ ํ ์ฒ˜๋ฆฌ ๋Œ€๋Ÿ‰ ์ฒ˜๋ฆฌ์— ๊ฐ•ํ•จ
์žฅ์•  ๋ณต์›๋ ฅ ์šฐ์ˆ˜
์‹ค์‹œ๊ฐ„์„ฑ ๋ถ€์กฑ
์„ค๊ณ„ ๋ณต์žก

 

๐Ÿงช ์ง์ ‘ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ ํ™•์ธ

๋‹จ์ผ ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„œ ๊ฐ๊ฐ์˜ ๋ฝ ์ „๋žต์„ ์ ์šฉํ•˜๊ณ  JMeter ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ ๋Œ๋ ธ๋‹ค.

์ „๋žต ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„ ์ค‘๋ณต ์—ฌ๋ถ€ ๋น„๊ณ 
๋น„๊ด€์  ๋ฝ 14ms ์—†์Œ DB ํŠธ๋žœ์žญ์…˜ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฐ€์žฅ ๋น ๋ฆ„
Redisson ๋ฝ 413ms ์—†์Œ Redis ํ†ต์‹  ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ

โœ… ๋น„๊ด€์  ๋ฝ์ด ๋‹จ์ผ ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„  ์••๋„์ ์œผ๋กœ ๋น ๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์˜€๋‹ค.

 

๐Ÿ›ค๏ธ ์ตœ์ข… ์„ ํƒ: Redisson ๋ถ„์‚ฐ ๋ฝ

๊ทธ๋Ÿผ์—๋„ ์ตœ์ข…์ ์œผ๋กœ Redisson ๋ถ„์‚ฐ ๋ฝ์„ ์„ ํƒํ–ˆ๋‹ค. ์ด์œ ๋Š” ๋ช…ํ™•ํ–ˆ๋‹ค.

๊ณ ๋ ค์‚ฌํ•ญ ์„ค๋ช…
์ˆ˜ํ‰ ํ™•์žฅ์„ฑ ์„œ๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€๊ฐ€ ๋˜์–ด๋„ ์ผ๊ด€์„ฑ ์œ ์ง€ ๊ฐ€๋Šฅ
์‹ค์‹œ๊ฐ„์„ฑ ๋ฉ”์‹œ์ง€ ํ๋ณด๋‹ค ๋น ๋ฅธ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
์œ ์ง€๋ณด์ˆ˜์„ฑ Redis ์บ์‹œ ๊ตฌ์กฐ์™€ ํ†ตํ•ฉ ์šด์šฉ ๊ฐ€๋Šฅ
์„ค๊ณ„ ์œ ์—ฐ์„ฑ DB ํŠธ๋žœ์žญ์…˜๊ณผ ๋…๋ฆฝ๋œ ๋ฝ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ

๋น„๊ด€์  ๋ฝ์€ DB ์•ˆ์—์„œ๋งŒ ๋ฝ์„ ๊ฑธ ์ˆ˜ ์žˆ๊ณ , ์ˆ˜ํ‰ ํ™•์žฅ ์‹œ(์„œ๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€๋กœ ๋Š˜์–ด๋‚˜๋ฉด) ๋ฝ ์ผ๊ด€์„ฑ ์œ ์ง€๊ฐ€ ์–ด๋ ค์› ๋‹ค.
๊ทธ๋ž˜์„œ ๋ฏธ๋ž˜ ํ™•์žฅ์„ ๊ณ ๋ คํ•˜์—ฌ, ์กฐ๊ธˆ ๋А๋ฆฌ๋”๋ผ๋„ Redisson ๋ฝ์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฑธ ์„ ํƒํ–ˆ๋‹ค.

 

๋‹จ์ˆœํ•œ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ๊ฐ€๋ณ๊ฒŒ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์‹ค์ œ ํŠธ๋ž˜ํ”ฝ ์ƒํ™ฉ์—์„œ๋Š” race condition, Deadlock ๊ฐ™์€ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ์„ ์ง์ ‘ ๊ฒฝํ—˜ํ–ˆ๋‹ค.
๋ฌธ์ œ๋ฅผ ํ…Œ์ŠคํŠธ๋กœ ์žฌํ˜„ํ•˜๊ณ , ๋‹ค์–‘ํ•œ ๋Œ€์•ˆ์„ ๋น„๊ตํ•˜๊ณ , ๋ฏธ๋ž˜ ํ™•์žฅ์„ฑ๊นŒ์ง€ ๊ณ ๋ คํ•˜์—ฌ ๊ธฐ์ˆ ์  ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๋Š” ๊ฒฝํ—˜์€ ๊ฐœ๋ฐœ์ž๋กœ์„œ ์œ ์ตํ•œ ์‹œ๊ฐ„์ด์—ˆ๋‹ค.