๐Ÿš€AWS ECS Fargate๋ฅผ ํ™œ์šฉํ•œ ํ• ์ธ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์‹œ์Šคํ…œ - 3


2๋‹จ๊ณ„ : Redis ๋„์ž…

์ด ์ „ํŽธ์—์„œ ํ™•์ธํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ๋น„๊ด€์  ๋ฝ์˜ ํ•œ๊ณ„๋Š” ๋ถ„๋ช…ํžˆ ์กด์žฌํ–ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‚˜๋Š” redis๋ฅผ ๋„์ž…ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

Redis

๋ ˆ๋””์Šค๋Š” key, value ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์ €์žฅ์†Œ๋กœ ๋‹ค์–‘ํ•œ ์ธ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์ง‘ํ•ฉ์„ ์ œ๊ณตํ•œ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.

์™œ Redis?

๋ ˆ๋””์Šค๋ฅผ ์„ ํƒํ•œ ์ด์œ ๋Š”

  1. ๋†’์€ ์„ฑ๋Šฅ ๋ฉ”๋ชจ๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์— ์•„์ฃผ ๋น ๋ฅธ ์‘๋‹ต ์‹œ๊ฐ„์„ ์ œ๊ณตํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ฟ ํฐ ๋ฐœํ–‰ ๊ฐ™์€ ๋งค์šฐ ๋น ๋ฅธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š”๋ฐ DB ๋””์Šคํฌ์—์„œ ๋ฝ ํš๋“ vs ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฝ ํš๋“/ํ•ด์ œ ์ฒ˜๋ฆฌ ์ค‘ ๋‹น์—ฐํžˆ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ฆ‰์‹œ ๋ฝ ํš๋“ ํ•˜๊ณ  ํ•ด์ œ๊ฐ€ ๋งค์šฐ ๋นจ๋ผ์„œ ๋Œ€๊ธฐ ์‹œ๊ฐ„ ๋•Œ๋ฌธ์— ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ํ•œ๊ณ„๋“ค์„ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ๋ถ„์‚ฐ ํ™˜๊ฒฝ ์ง€์› ๋ ˆ๋””์Šค๋Š” Redisson๊ฐ™์€ ๋ถ„์‚ฐ๋ฝ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌํ˜„์ฒด๋“ค์„ ์ œ๊ณตํ•˜๋Š”๋ฐ ์ด๋ฅผ ํ†ตํ•ด ๋ถ„์‚ฐ ๋ฝ์„ ์•ˆ์ •์ ์œผ๋กœ ๊ตฌํ˜„ํ•ด ๋†“์•˜๋‹ค.

    ๋ถ„์‚ฐ๋ฝ(Distributed Lock) : ์—ฌ๋Ÿฌ ์„œ๋ฒ„๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผ ํ•  ๋•Œ, ์˜ค์ง ํ•˜๋‚˜์˜ ์„œ๋ฒ„๋‚˜ ํ”„๋กœ์„ธ์Šค๋งŒ ํ•ด๋‹น ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์ž‡๋„๋ก ์ œ์–ดํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜

  3. ์œ ์—ฐํ•œ ๋ฝ ๊ด€๋ฆฌ ๋ฝ์˜ ํš๋“ ๋ถ€ํ„ฐ ๋ฝ์˜ ์œ ํšจ์‹œ๊ฐ„ ์ง€์ •์ด๋ผ๋“ ์ง€ ๋ฐ๋“œ๋ฝ ์ƒํ™ฉ์„ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ๋“ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

์šฐ์„  redis์˜ ๋น ๋ฅธ ์ฒ˜๋ฆฌ ์†๋„์™€ DB ๋ถ€ํ•˜ ๊ฐ์†Œ๋ฅผ ํ•˜๋ฉด์„œ ํšจ๊ณผ์ ์œผ๋กœ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด Redis๋Š” ์ฟ ํฐ์˜ ์žฌ๊ณ  ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ์†Œ์Šค๋กœ ์‚ฌ์šฉํ•˜๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

๋น„๊ด€์  ๋ฝ๋งŒ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ์™€ Redis์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ–ˆ์„๋•Œ์˜ ์ฐจ์ด๋Š”

Smart-Select-20241129-175350-Flexcil.jpg Smart-Select-20241129-175358-Flexcil.jpg

  1. ์ฒ˜๋ฆฌ ์†๋„
    • ๋น„๊ด€์  ๋ฝ : ๋ชจ๋“  ์š”์ฒญ์ด DB๋ฝ์„ ์–ป๊ธฐ ์œ„ํ•ด ๋Œ€๊ธฐํ•ด์•ผํ•œ๋‹ค.
    • Redis + DB : Redis์—์„œ ๋น ๋ฅด๊ฒŒ ์žฌ๊ณ  ํ™•์ธ๊ณผ ๊ฐ์†Œ๊ฐ€ ์ด๋ฃจ์–ด์ง€๋ฏ€๋กœ, ์žฌ๊ณ ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ DB ํŠธ๋žœ์žญ์…˜ ์—†์ด ์ฆ‰์‹œ ์‹คํŒจ ์‘๋‹ต์ด ๊ฐ€๋Šฅ
  2. ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ
    • ๋น„๊ด€์  ๋ฝ : DB ์ˆ˜์ค€์—์„œ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค
    • Redis + DB : Redis์—์„œ ๋จผ์ € ๋น ๋ฅธ ์žฌ๊ณ  ์ฒดํฌ๊ฐ€ ์ด๋ฃจ์–ด์ ธ์„œ, ์‹ค์ œ DB ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•œ ์š”์ฒญ๋งŒ DB์— ๋„๋‹ฌํ•œ๋‹ค
  3. ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ
    • ๋น„๊ด€์  ๋ฝ : ๋ชจ๋“  ์š”์ฒญ์ด DB ์ปค๋„ฅ์…˜์„ ํ•„์š”๋กœ ํ•œ๋‹ค.
    • Redis + DB : ๋ ˆ๋””์Šค์—์„œ ๊ฑธ๋Ÿฌ์ง„ ์š”์ฒญ์€ DB ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค

=> ๊ฒฐ๋ก ์ ์œผ๋กœ Redis๋ฅผ ๋„์ž…ํ•˜๋ฏ€๋กœ์จ ๋ถˆํ•„์š”ํ•œ DB ์ปค๋„ฅ์…˜์„ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๊ณ , ์‹œ์Šคํ…œ์˜ ์ „์ฒด์ ์ธ ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋œ๋‹ค.

์–ด๋–ป๊ฒŒ Redis ์ ์šฉ?

1ํŽธ์—์„œ Redis ์˜์กด์„ฑ ์ถ”๊ฐ€๋ฅผ ํ•˜๊ณ  ์„ค์ • ํด๋ž˜์Šค๊นŒ์ง€ ์ž‘์„ฑ์„ ํ•ด๋ดค๋‹ค. ๐Ÿš€AWS ECS Fargate๋ฅผ ํ™œ์šฉํ•œ ํ• ์ธ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์‹œ์Šคํ…œ - 1 | Sung Jaeโ€™s Blog

์ฟ ํฐ ๋ฐœ๊ธ‰ํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ •๋ฆฌํ•ด๋ณด์ž

  1. ์ฟ ํฐ ๋ฐœ๊ธ‰ ์š”์ฒญ
  2. ์ค‘๋ณต ๋ฐœ๊ธ‰ ๊ฒ€์ฆ
  3. ์ฟ ํฐ ๋ฐœ๊ธ‰์„ ์œ„ํ•œ ๋ถ„์‚ฐ lockํš๋“
  4. ์žฌ๊ณ  ํ™•์ธ ๋ฐ ์ฒ˜๋ฆฌ
  5. ์ฟ ํฐ ๋ฐœ๊ธ‰ ์ฒ˜๋ฆฌ
  6. ๋ฝ ํ•ด์ œ
  7. ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜ ์˜ ์ˆœ์„œ๋Œ€๋กœ ์ฟ ํฐ์ด ๋ฐœ๊ธ‰์ด ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ํ•ต์‹ฌ์ด ๋˜๋Š” ๋ถ€๋ถ„์€ 3~6์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. 3~5 ๊ฐ ๋‹จ๊ณ„๋Š” ์–ด๋–ค์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž

์ฟ ํฐ ๋ฐœ๊ธ‰์„ ์œ„ํ•œ ๋ถ„์‚ฐ lockํš๋“

2024-12-13-152346.png

  • acquireLock ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Redis๋ฅผ ํ†ตํ•ด ๋ถ„์‚ฐ ๋ฝ์„ ํš๋“ํ•œ๋‹ค.
  • ๋งŒ์•ฝ ๋ฝ ํš๋“์— ์‹คํŒจํ•˜๋ฉด
    • ๋ฐœ๊ธ‰ ์ด๋ ฅ์ด ๊ธฐ๋ก๋˜๊ณ 
    • fail ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ฝ์„ ํš๋“ํ•˜๋ฉด

์žฌ๊ณ  ํ™•์ธ ๋ฐ ์ฒ˜๋ฆฌ

2024-12-13-155225.png 2024-12-13-155328.png

  • Redis์˜ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ๊ฐ์†Œ์‹œํ‚จ๋‹ค.
  • ์žฌ๊ณ  ๊ฐ์†Œ์— ์‹คํŒจํ•œ๋‹ค๋ฉด
    • ์‹คํŒจ ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๊ณ 
    • ์‹คํŒจ ์ด๋ ฅ์„ ์ €์žฅํ•˜๊ณ 
    • fail ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ฟ ํฐ ๋ฐœ๊ธ‰ ์ฒ˜๋ฆฌ

2024-12-13-155552.png ![[Pasted image 20241213155720.png]]

  • Redis์—์„œ ์žฌ๊ณ ๋ฅผ ๊ฐ์†Œ์‹œํ‚จ ํ›„ ์‹ค์ œ DB์—์„œ ์‹ค์ œ๋กœ ์ฟ ํฐ์„ ๋ฐœ๊ธ‰ํ•œ๋‹ค.
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ฟ ํฐ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ฐœ๊ธ‰ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋ฅผ ๊ฐ์†Œํ•œ๋‹ค.
    • ์ฟ ํฐ ๋ฐœ๊ธ‰ ๊ธฐ๋ก์„ ์ €์žฅํ•œ๋‹ค

ํ…Œ์ŠคํŠธ

ํ˜„์žฌ ์•„์ง AWS์— ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•œ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฌํ”„ํ•˜๊ฒŒ ๋กœ์ปฌ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ ํ•ด๋ดค๋‹ค.

  1. ๋™์‹œ์„ฑ ์ œ์–ด๊ฐ€ ์ž˜๋˜๋Š”์ง€
  2. Redis์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ฒฐํ•ฉํ•œ ์žฌ๊ณ  ์ฒ˜๋ฆฌ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๋˜๋Š”์ง€ ๋ฅผ ์ค‘์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋Š”

  • ์ฟ ํฐ 10000๊ฐœ
  • ์ด ์š”์ฒญ ๊ฐœ์ˆ˜ 1000๋ฒˆ
  • ๋™์‹œ ์š”์ฒญ์ˆ˜ 1000๋ฒˆ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Test  
void performanceTest() throws InterruptedException {  
    // given  
    ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);  
    CountDownLatch latch = new CountDownLatch(TOTAL_THREAD_COUNT);  
  
    long currentTime = System.currentTimeMillis();  
    // when  
    for (int i = 0; i < TOTAL_THREAD_COUNT; i++) {  
        final long userId = i; // ๋ณ€์ˆ˜ ์บก์ฒ˜๋ฅผ ์œ„ํ•ด final๋กœ ์„ ์–ธ  
        executorService.submit(() -> {  
            try {  
                CouponIssueRequest request = new CouponIssueRequest(  
                        code,  
                        userId,  
                        requestIp);  
                couponService.issueCoupon(request);  
            } catch (Exception e) {  
                // ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๋กœ๊น…  
                System.err.println("Error processing request: " + e.getMessage());  
            } finally {  
                latch.countDown();  
            }  
        });  
    }  
    System.out.println("Total time: " + (System.currentTimeMillis() - currentTime) + "ms");  
  
    // then  
    latch.await();  
    executorService.shutdown(); // ์Šค๋ ˆ๋“œ ํ’€ ์ •๋ฆฌ  
  
    // ๊ฒฐ๊ณผ ๊ฒ€์ฆ  
    Coupon updatedCoupon = couponRepository.findByCode(code).orElseThrow();  
    int issuedCount = couponIssueRepository.countByCouponCode(code);  
  
    assertThat(updatedCoupon.getRemainStock()).isEqualTo(Math.max((STOCK_COUNT - TOTAL_THREAD_COUNT), 0));  
  
    assertThat(issuedCount).isEqualTo(Math.min(STOCK_COUNT, TOTAL_THREAD_COUNT));  
}

2024-12-13-173749.png 2024-12-13-173829.png redis ์žฌ๊ณ ๋„ ์ •์ƒ์ ์œผ๋กœ 1000๊ฐœ๋งŒ ๋ฐœ๊ธ‰ ๋˜์—ˆ๋‹ค.

๋‹ค์Œ ํŽธ์€ Redis์— ๋Œ€ํ•ด ์ข€ ๋” ์‹ฌ์ธต์ ์œผ๋กœ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ๋“ค์„ ํฌ์ŠคํŒ…ํ•  ์˜ˆ์ •์ด๋‹ค.