์ธํ๋ฐ Inflearn - ์ฌ๊ณ ์์คํ ์ผ๋ก ์์๋ณด๋ ๋์์ฑ ์ด์ ํด๊ฒฐ๋ฐฉ๋ฒ ๊ฐ์๋ฅผ ์๊ฐํ์์ต๋๋ค.
ํ๋์ ์ํ์ด 100๊ฐ์ ์ฌ๊ณ ๋ฅผ ๊ฐ์ง๊ณ ์์ ๋ ๋จ์ํ๊ฒ ์๊ฐํ๋ฉด ํ๋งค๋ ๋ ์ฌ๊ณ ๋ฅผ -1 ํ ํ ์ ์ฅํด์ฃผ๋ฉด ๋ ๊ฑฐ๋ผ๊ณ ์๊ฐํ ์ ์์ง๋ง, ์ค๋ฌด์์๋ ๋ค์ํ ์ผ์ด์ค๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ํ์ ์ผ๋ก, ํ๋์ ์ํ์ ์ฃผ๋ฌธ์ด ๋์์ (ms ์ฐจ์ด ์์ค) ๋ค์ด์จ๋ค๊ณ ๊ฐ์ ์ ํ๋ค. ์ด๋ด ๋, Race Condition์ด ๋ฐ์ํ์ฌ ๋ง์ง๋ง ์ฌ๊ณ ๊ฐ์ด ์ด์ํ๊ฒ ๋์ฌ ์ ์๋ค.
100๊ฐ์ ์ฐ๋ ๋๊ฐ ๊ฐ์ ์ํ์ ์ฌ๊ณ ๋ฅผ ๊ฐ์์์ผฐ์ ๋ ์ต์ข ์ฌ๊ณ ๋ 0์ ๊ธฐ๋ํ์ง๋ง ์ค์ ํ ์คํธ๋ ์คํจํ๋ ๊ฒ์ ํ์ธ ํ ์ ์๋ค.
Java์ ๊ธฐ๋ณธ Syncronized ํค์๋๋ฅผ ์ฌ์ฉํด์ ํ๋์ ์ฐ๋ ๋์ฉ ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถ ํ ์ ์๋๋ก ์์ ํ๋ค.
์์์ฒ๋ผ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ์ฐ๋ ๋ ๋๊ธฐํ๋ฅผ ํตํด ํด๊ฒฐํ๋ค๊ณ ์๊ฐํ ์ ์์ง๋ง, ๊ฒฐ๊ณผ๋ ์คํจํ๋ค.
์ด์ ๋ @Transactiional
Proxy ๋ฐฉ์ ๋๋ฌธ์ Proxy๊ฐ (Commit)์ข
๋ฃ๋๊ธฐ ์ ์ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ํด๋น ์์์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ฐ์ ๋ณ๊ฒฝ๋์ง ์์์ ์ ์๋ค.
์๋น์ค์ ๋ถ์ด์๋ @Transactional
์ ์์ค๋ค.
@Transactional
์ ์ ๊ฑฐํ๋ฉด Proxy๋ก ๋์ํ์ง ์๊ธฐ ๋๋ฌธ์ ํด๊ฒฐ์ ํ ์๋ ์๋ค.
Syncronized๋ ํ๋์ ํ๋ก์ธ์ค์์๋ง ๋๊ธฐํ๋ฅผ ๋ณด์ฅํ๋ค. ํ๋์ ์ดํ๋ฆฌ์ผ์ด์ ์ 2๋ ์ด์์ ์๋ฒ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ Syncronized ๋ก๋ ๋ณด์ฅํ ์ ์๋ค.
- ์ค์ ๋ฐ์ดํฐ์ Lock์ ๊ฑธ์ด์ ์ ํฉ์ฑ์ ๋ง์ถ๋ ๋ฐฉ๋ฒ
- Exclusive Lock์ ๊ฑธ๊ฒ๋๋ฉด ๋ค๋ฅธ ํธ๋์ญ์ ์์ ๋ Lock์ด ํด์ ๋๊ธฐ ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ๊ฐ ์ ์๋ค.
- Dead Lock์ด ๊ฑธ๋ฆด ์ ์๊ธฐ ๋๋ฌธ์ ์ฃผ์ํ๊ธฐ
select stock0_.id as id1_0_, stock0_.product_id as product_2_0_, stock0_.quantity as quantity3_0_ from stock stock0_ where stock0_.id=? for update
select..for update
๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น row๋ฅผ ๋ค๋ฅธ ์ธ์
์์ ๊ฑด๋ค ์ ์๋๋ก Lock์ ๊ฑด๋ค.
- ์ถฉ๋์ด ๋น๋ฒํ๊ฒ ์ผ์ด๋๋ฉด Optimistic Lock๋ณด๋ค ์ฑ๋ฅ์ด ์ข์ ์ ์์
- Lock์ ์ก๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ ์งํฌ ์ ์์
- ์ฑ๋ฅ๊ฐ์
- ์ค์ Lock์ ์ด์ฉํ์ง ์๊ณ ๋ฒ์ ์ ์ด์ฉํจ์ผ๋ก์จ ์ ํฉ์ฑ์ ๋ง์ถ๋ ๋ฐฉ๋ฒ
- ๋จผ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ update๋ฅผ ์ํํ ๋ ํ์ฌ ๋ด๊ฐ ์ฝ์ ๋ฒ์ ์ด ๋ง๋์ง ํ์ธํ์ฌ ์ ๋ฐ์ดํธ
- ๋ด๊ฐ ์ฝ์ ๋ฒ์ ์์ ์์ ์ฌํญ์ด ์๊ฒผ์ ๊ฒฝ์ฐ application ๋จ์์ ๋ค์ ์ฝ์ ํ ์์ ์ ์ํํด์ผ ํจ
- ๋ณ๋์ Lock์ด ์๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ์ ์ด์
- ์คํจํ์ ์ ๋ก์ง์ ๊ฐ๋ฐ์๊ฐ ์ง์ ๋ง๋ค์ด์ผํจ
- ์ถฉ๋์ด ๋น๋ฒํ ์ผ์ด๋๋ฉด ์ฑ๋ฅ์ ์ํด
- ์ด๋ฆ์ ๊ฐ์ง Metadata Locking (Table/Row Lock ์ด ์๋)
- ์ด๋ฆ์ ๊ฐ์ง Lock์ ํ๋ํ ํ ํด์ ํ ๋ ๊น์ง ๋ค๋ฅธ ์ธ์ ์ ์ด Lock ์ ํ๋ํ ์ ์๋๋ก ํฉ๋๋ค.
- Transaction์ด ์ข ๋ฃ๋ ๋ ์๋์ผ๋ก ํด์ ๋์ง ์์
- ๋ณ๋์ ๋ช ๋ น์ด๋ก ํด์ /์ ์ ์๊ฐ์ด ๋๋์ผ ํด์ Transaction์ด ์ข ๋ฃ๋ ๋ Lock์ด ์๋์ผ๋ก ํด์ ๋์ง ์์.
- JPA Native Query๋ฅผ ์ด์ฉ
- Connction Pool ์ด ๋ถ์กฑํด์ง ์ ์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ Datasource๋ฅผ ์ด์ฉํ๊ธฐ๋ฅผ ์ถ์ฒ
setnx
๋ช ๋ น์ด ์ฌ์ฉ- spin lock ๋ฐฉ์
- Lock์ ํ๋ํ๋ ค๋ ์ค๋ ๋๊ฐ Lock์ ํ๋ํ ์ ์๋์ง ๋ฐ๋ณต์ ์ผ๋ก ํ์ธํ๋ฉด์ Lock ํ๋ ์๋
- retry ๋ก์ง ํ์
- ๊ตฌํ์ด ๊ฐ๋จํ๋ค
- spring data redis ๋ฅผ ์ด์ฉํ๋ฉด lettuce ๊ฐ ๊ธฐ๋ณธ์ด๊ธฐ๋๋ฌธ์ ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋๋ค.
- spin lock ๋ฐฉ์์ด๊ธฐ๋๋ฌธ์ ๋์์ ๋ง์ ์ค๋ ๋๊ฐ lock ํ๋ ๋๊ธฐ ์ํ๋ผ๋ฉด redis ์ ๋ถํ๊ฐ ๊ฐ ์ ์๋ค.
- Thread.sleep์ผ๋ก ๋ถํ๋ฅผ ์ค์ฌ์คฌ์
- Pub-Sub ๊ธฐ๋ฐ์ Lock ๊ตฌํ ์ ๊ณต
- ์ฑ๋์ ๋ง๋ค๊ณ Lock์ ํ๋ํ Thread๊ฐ Lockํ๋์ ์๋ํ๋ Thread์๊ฒ ํด์ ๋์์์ ์๋ ค์ฃผ๋ ๋ฐฉ์
- ๋ฝ ํ๋ ์ฌ์๋๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณตํ๋ค.
- ๋ณ๋์ repository๋ฅผ ์์ฑํ์ง ์์๋ ๋๋ค.
- pub-sub ๋ฐฉ์์ผ๋ก ๊ตฌํ์ด ๋์ด์๊ธฐ ๋๋ฌธ์ lettuce ์ ๋น๊ตํ์ ๋ redis ์ ๋ถํ๊ฐ ๋ ๊ฐ๋ค.
- ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ผํ๋ค.
- lock ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฐจ์์์ ์ ๊ณตํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ๋ฒ์ ๊ณต๋ถํด์ผ ํ๋ค.
- ์คํจ ์ ์ฌ์๋๊ฐ ํ์ํ์ง ์์ lock ์ lettuce ํ์ฉ
- ์คํจ ์ ์ฌ์๋๊ฐ ํ์ํ ๊ฒฝ์ฐ์๋ redisson ๋ฅผ ํ์ฉ
๐ ExecutorService
- ExecutorService๋, ๋ณ๋ ฌ ์์ ์ ์ฌ๋ฌ ๊ฐ์ ์์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ ๊ณต๋๋ JAVA ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
- ExecutorService๋ ์์ฝ๊ฒ ThreadPool์ ๊ตฌ์ฑํ๊ณ Task๋ฅผ ์คํํ๊ณ ๊ด๋ฆฌํ ์ ์๋ ์ญํ ์ ํฉ๋๋ค.
- Executors ๋ฅผ ์ฌ์ฉํ์ฌ ExecutorService ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉฐ, ์ฐ๋ ๋ ํ์ ๊ฐ์ ๋ฐ ์ข ๋ฅ๋ฅผ ์ง์ ํ ์ ์๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค.
๐ CountDownLatch
- CountDownLatch๋, ์ด๋ค ์ค๋ ๋๊ฐ ๋ค๋ฅธ ์ฐ๋ ๋์์ ์์ ์ด ์๋ฃ๋ ๋ ๊ฐ์ง ๊ธฐ๋ค๋ฆด ์ ์๋๋ก ํด์ฃผ๋ ํด๋์ค๋ค.
- CountDownLatch ๋ฅผ ์ด์ฉํ์ฌ, ๋ฉํฐ์ค๋ ๋๊ฐ 100๋ฒ ์์ ์ด ๋ชจ๋ ์๋ฃํ ํ, ํ ์คํธ๋ฅผ ํ๋๋ก ๊ธฐ๋ค๋ฆฌ๊ฒ ํ๋ค.
https://github.com/dev-alxndr/concurrency-stock
https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_exclusive_lock
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html