- ์ฃผ์ : ์ฃผ๋ฌธ ์ฒ๋ฆฌ ๋ฐ ์ฒด๊ฒฐ ์์ง ๊ณ ๋ํ
- ๋ชฉํ: ๋ค์ค ์ข ๋ชฉ + ๋ค์ค ์ฌ์ฉ์ ํ๊ฒฝ์์์ ์ฒ๋ฆฌ ์ฑ๋ฅ ํ๋ณด
- ๊ธฐ์ ์คํ: Spring Boot, MySQL, WebSocket, JPA, HikariCP, Concurrent Collection
- ์ฌ์ฉ์๋ก๋ถํฐ ์ฃผ๋ฌธ ์์ฒญ์ ์์
- ๊ฐ๊ฒฉ ์ ํจ์ฑ, ๋ณด์ ์์ฐ ๊ฒ์ฆ (Account/Asset ์๋น์ค ์ฐ๋)
- ๊ฒ์ฆ ํต๊ณผ ์ ์ฃผ๋ฌธ ๋ฑ๋ก
- ์ข
๋ชฉ๋ณ๋ก
ConcurrentSkipListMap<Price, ConcurrentSkipListSet<Order>>์ฌ์ฉ - ๊ฐ๊ฒฉ ์ฐ์ โ ์๊ฐ ์ ์ฐ์ ์ฒด๊ฒฐ ๋ฐฉ์
- ์ฒด๊ฒฐ๋ ์ฃผ๋ฌธ์
TradeHistory์ ์ ์ฅ
- ์ฃผ๋ฌธ ์ฒด๊ฒฐ ์ WebSocket์ ํตํด ํด๋ผ์ด์ธํธ๋ก ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก
@Scheduled๋ฅผ ํ์ฉํ 15์ด ๋จ์ Candle ๊ฐฑ์
- ์๋ฒ ์์ ์ DB์์ ๊ฑฐ๋ ๋ด์ญ์ ๋ก๋ฉ ํ ์ฐจํธ ์ด๊ธฐํ
- ์ข
๋ชฉ๋ณ Lock (
ReentrantReadWriteLock)์ ํ์ฉํ ๋ณ๋ ฌ ์ ๊ทผ ์ ์ด
- ์ข ๋ชฉ ์: 20๊ฐ
- ์ฌ์ฉ์ ์: 1,000๋ช
- ๋์ ์๊ฐ: 10๋ถ
- ํ ์คํธ ๋๊ตฌ: NGrinder
- ์ด ์์ฒญ ์: ์ฝ 140,000๊ฑด
- ๊ธฐ์กด TreeMap + PriorityQueue ์ฌ์ฉ
- Order:
ReentrantLock - Account: ๋น๊ด์ ๋ฝ (Pessimistic Lock)
- Order:
ReentrantLock - Account: ๋น๊ด์ ๋ฝ (Pessimistic Lock)
- ์ฟผ๋ฆฌ ํ๋
- Order:
ReentrantLock - Account: ๋น๊ด์ ๋ฝ (Pessimistic Lock)
- ์ฟผ๋ฆฌ ํ๋
- ์ปค๋ฅ์ ํ ํ๋
- Order:
synchronized - Account: ๋๊ด์ ๋ฝ (Optimistic Lock)
- Order:
synchronized - Account: ๋๊ด์ ๋ฝ (Optimistic Lock)
- ์ฟผ๋ฆฌ ํ๋
- Order:
synchronized - Account: ๋๊ด์ ๋ฝ (Optimistic Lock)
- ์ฟผ๋ฆฌ ํ๋
- ์ปค๋ฅ์ ํ ํ๋
| ๊ตฌ๋ถ | TPS | ์ต๊ณ TPS | ์๋ฌ |
|---|---|---|---|
| Before | 145.5 | 191.0 | 7,677 |
| After | 235.7 | 276.0 | 0 |
- Before: TreeMap + PriorityQueue
- After:
ConcurrentSkipListMap+ConcurrentSkipListSet+ ์ฟผ๋ฆฌ ํ๋ + ์ปค๋ฅ์ ํ ํ๋ - ๊ฒฐ๊ณผ: ์ข ๋ชฉ 20๊ฐ, ์ ์ 1000๋ช ๊ธฐ์ค โ ์ฝ 62% ์ฑ๋ฅ ํฅ์
- ํด๊ฒฐ:
ConcurrentSkipListMap+ConcurrentSkipListSet+ Lock ๊ธฐ๋ฐ ์ ์ด
- ํด๊ฒฐ: HikariCP max pool โ 30, MySQL max_connections โ 300
- ํด๊ฒฐ: ์กฐ๊ฑด๋ถ Fetch Join ์ ์ฉ์ผ๋ก ์ฟผ๋ฆฌ ์ ๊ฐ์
์ฒด๊ฒฐ ๋ก์ง๊ณผ Account ๋๊ธฐํ๋ฅผ ๋ชจ๋ ๊ณ ๋ คํ๋ฉฐ ๋ค์ํ ๋ฝ ์ ๋ต ๋ฐ ๊ตฌ์กฐ ์กฐํฉ์ ํ ์คํธํ์ต๋๋ค.
์ค์ ํธ๋ํฝ ํ๊ฒฝ์ ๊ธฐ๋ฐ์ผ๋ก ์ฑ๋ฅ์ ์์นํํ๊ณ , ๋ถ์ฐ ๊ตฌ์กฐ๋ก์ ํ์ฅ์ ์ํ ๊ธฐ๋ฐ์ ์์ฑํ ๋จ๊ณ์์ต๋๋ค.