First Come First Served

First Come First Served Event

์‹ค์Šต์œผ๋กœ ๋ฐฐ์šฐ๋Š” ์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์š”์•ฝํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

Intro

์š”๊ตฌ์‚ฌํ•ญ.

  • ์„ ์ฐฉ์ˆœ 100๋ช…์—๊ฒŒ ํ• ์ธ์ฟ ํฐ์„ ์ œ๊ณตํ•˜๋Š” ์ด๋ฒคํŠธ

  • ์„ ์ฐฉ์ˆœ 100๋ช…์—๊ฒŒ๋งŒ ์ง€๊ธ‰๋˜์–ด์•ผํ•œ๋‹ค.

  • 101๊ฐœ ์ด์ƒ์ด ์ง€๊ธ‰๋˜๋ฉด ์•ˆ๋œ๋‹ค.

  • ์ˆœ๊ฐ„์ ์œผ๋กœ ๋ชฐ๋ฆฌ๋Š” ํŠธ๋ž˜ํ”ฝ์„ ๋ฒ„ํ‹ธ ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค.

์„ ์ฐฉ์ˆœ ์ด๋ฒคํŠธ ์ง„ํ–‰ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ .

  • ์ฟ ํฐ์ด ๊ฐœ์ˆ˜๋ณด๋‹ค ๋” ๋งŽ์ด ๋ฐœ๊ธ‰๋˜์—ˆ์„ ๊ฒฝ์šฐ

  • ์ด๋ฒคํŠธ ํŽ˜์ด์ง€ ์ ‘์†์ด ์•ˆ ๋  ๊ฒฝ์šฐ

  • ์ด๋ฒคํŠธ๋ž‘ ์ƒ๊ด€์—†๋Š” ํŽ˜์ด์ง€๋„ ๋А๋ ค์งˆ ๊ฒฝ์šฐ

๋ฌธ์ œ ํ•ด๊ฒฐ.

  • ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ ธ์„ ๋•Œ ๋Œ€์ฒ˜ํ•  ๋ฐฉ๋ฒ•

  • Redis ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ๋ฐœ๊ธ‰ ๊ฐœ์ˆ˜ ๋ณด์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•

  • Kafka ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋“ค์— ๋Œ€ํ•œ ์˜ํ–ฅ๋„๋ฅผ ์ค„์ด๋Š” ๋ฐฉ๋ฒ•

Race Condition

์•„๋ž˜ ํ…Œ์ŠคํŠธ์—์„œ 100์˜ ๊ฒฐ๊ณผ๋ฅผ ์˜ˆ์ƒํ–ˆ์ง€๋งŒ, ๋™์‹œ์— ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ๋“ค์ด ๊ฐฑ์‹  ์ „ ๊ฐ’์„ ์ฝ๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด์„œ ์˜ˆ์ƒํ–ˆ๋˜ ๊ฐœ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

Concurrency issues ์—์„œ ๋ฐฐ์šด ๊ฒƒ๊ณผ ๊ฐ™์ด Java Synchronized ๋ฅผ ์ ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ,

์„œ๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๋Œ€๊ฐ€ ๋œ๋‹ค๋ฉด Race Condition ์ด ๋‹ค์‹œ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ์ ์ ˆํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

.

๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ MySQL, Redis ๋ฅผ ํ™œ์šฉํ•œ ๋ฝ์„ ๊ตฌํ˜„ํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™์ง€๋งŒ,

์ฟ ํฐ ๊ฐœ์ˆ˜์— ๋Œ€ํ•œ ์ •ํ•ฉ์„ฑ์„ ์›ํ•˜๋Š”๋ฐ ๋ฝ์„ ํ™œ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋ฉด, ๋ฐœ๊ธ‰๋œ ์ฟ ํฐ์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์ฟ ํฐ์„ ์ƒ์„ฑํ•  ๋•Œ๊นŒ์ง€ ๋ฝ์„ ๊ฑธ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๋ฝ์„ ๊ฑฐ๋Š” ๊ตฌ๊ฐ„์ด ๊ธธ์–ด์ง€๋‹ค๋ณด๋‹ˆ ์„ฑ๋Šฅ์— ๋ถˆ์ด์ต(๋ฝ์ด ํ’€๋ฆด ๋•Œ๊นŒ์ง€ ์ฟ ํฐ ๋ฐœ๊ธ‰์„ ๊ธฐ๋‹ค๋ ค์•ผ ํ•˜๋Š”)์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Redis

Redis incr ๋ช…๋ น์–ด๋Š” ํ‚ค์— ๋Œ€ํ•œ ๊ฐ’์„ 1์”ฉ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ๋ช…๋ น์–ด์ž…๋‹ˆ๋‹ค.

Redis ๋Š” ์‹ฑ๊ธ€์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜์—ฌ ๋ ˆ์ด์Šค ์ปจ๋””์…˜์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„ ๋ฟ ์•„๋‹ˆ๋ผ incr ๋ช…๋ น์–ด๋Š” ์„ฑ๋Šฅ๋„ ๊ต‰์žฅํžˆ ๋น ๋ฅธ ๋ช…๋ น์–ด์ž…๋‹ˆ๋‹ค.

incr ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐœ๊ธ‰๋œ ์ฟ ํฐ ๊ฐœ์ˆ˜๋ฅผ ์ œ์–ดํ•œ๋‹ค๋ฉด ์„ฑ๋Šฅ๋„ ๋น ๋ฅด๋ฉฐ ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ๋„ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

commit

Problems

1) ์ฟ ํฐ์˜ ๊ฐœ์ˆ˜

  • ๋ฐœ๊ธ‰ํ•˜๋Š” ์ฟ ํฐ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ถ€ํ•˜๋ฅผ ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋‹ค๋ฅธ ๊ณณ์—์„œ๋„ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค๋ฉด ์„œ๋น„์Šค ์žฅ์• ๊นŒ์ง€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2) ์งง์€ ์‹œ๊ฐ„์— ๋งŽ์€ ์š”์ฒญ

  • ์งง์€ ์‹œ๊ฐ„ ๋‚ด์— ๋งŽ์€ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ฒŒ ๋  ๊ฒฝ์šฐ DB ์„œ๋ฒ„์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๋ถ€ํ•˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค ์ง€์—ฐ ํ˜น์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Kafka

๋ถ„์‚ฐ ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ ํ”Œ๋žซํผ

  • ์ด๋ฒคํŠธ ์ŠคํŠธ๋ฆฌ๋ฐ: ์†Œ์Šค์—์„œ ๋ชฉ์ ์ง€๊นŒ์ง€ ์ด๋ฒคํŠธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐ ํ•˜๋Š” ๊ฒƒ

Start Kafka

docker-compose.yml

example

Producer

api/KafkaProducerConfig.java

api/CouponCreateProducer.java

KafkaProducerConfig CouponCreateProducer

Consumer

consumer/KafkaConsumerConfig.java

consumer/CouponCreatedConsumer.java

using Consumer

Limit the number of coupons

๋ฐœ๊ธ‰ ๊ฐ€๋Šฅํ•œ ์ฟ ํฐ ๊ฐœ์ˆ˜ 1์ธ๋‹น 1๊ฐœ๋กœ ์ œํ•œํ•˜๊ธฐ.

(1) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์œ ๋‹ˆํฌํ‚ค ์‚ฌ์šฉํ•˜๊ธฐ

  • userId, couponType ์— ์œ ๋‹ˆํฌ ํ‚ค๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•.

  • ๋ณดํ†ต ์„œ๋น„์Šค๋Š” ํ•œ ์œ ์ €๊ฐ€ ๊ฐ™์€ ํƒ€์ž…์˜ ์ฟ ํฐ์„ ์—ฌ๋Ÿฌ๊ฐœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‹ค์šฉ์ ์ธ ๋ฐฉ๋ฒ•์€ ์•„๋‹˜.

(2) ๋ฒ”์œ„๋กœ ๋ฝ์„ ์žก๊ณ  ์ฒ˜์Œ์— ์ฟ ํฐ ๋ฐœ๊ธ‰ ์—ฌ๋ถ€๋ฅผ ๊ฐ€์ ธ์™€์„œ ํŒ๋‹จํ•˜๋Š” ๋ฐฉ์‹

  • ์ฟ ํฐ ๋ฐœ๊ธ‰ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋งŒ ํŒ๋‹จํ•˜๊ณ  ์‹ค์ œ ์ฟ ํฐ ์ƒ์„ฑ์€ ์ปจ์Šˆ๋จธ์—์„œ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์‹œ๊ฐ„์ฐจ๋กœ 2๊ฐœ ์ด์ƒ์˜ ์ฟ ํฐ์ด ๋ฐœ๊ธ‰๋  ์ˆ˜ ์žˆ์Œ.

  • ์ง์ ‘ ์ฟ ํฐ์„ ๋ฐœ๊ธ‰ํ•˜๋”๋ผ๋„ ๋ฝ์˜ ๋ฒ”์œ„๊ฐ€ ๋„“์–ด์„œ ๋‹ค๋ฅธ ์š”์ฒญ๋“ค์€ ๋ฝ์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ์ƒํƒœ๊ฐ€ ๋˜๋ฏ€๋กœ ์„ฑ๋Šฅ์ด ์•ˆ ์ข‹์•„์งˆ ์ˆ˜ ์žˆ์Œ.

(3) Rest ์—์„œ Set ํ™œ์šฉํ•˜๊ธฐ

AppliedUserRepository.java

commit

Error issuing coupon

(1) ์‹คํŒจ ์ด๋ฒคํŠธ ๊ด€๋ฆฌ ํ…Œ์ด๋ธ” ํ™œ์šฉํ•˜๊ธฐ

  • ์ปจ์Šˆ๋จธ์—์„œ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ FailedEvent ํ…Œ์ด๋ธ”์— ์‹คํŒจํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

  • ์ดํ›„ ๋ฐฐ์น˜๋ฅผ ํ†ตํ•ด FailedEvent ํ…Œ์ด๋ธ”์— ์Œ“์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์ฝ์–ด์„œ ์ฟ ํฐ์„ ๋ฐœ๊ธ‰ํ•ด ์ค€๋‹ค๋ฉด ๊ฒฐ๊ณผ์ ์œผ๋กœ ํŠน์ • ์ˆ˜๋Ÿ‰์˜ ์ฟ ํฐ์ด ๋ชจ๋‘ ๋ฐœ๊ธ‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(3) Saga Pattern ์ ์šฉํ•˜๊ธฐ

  • ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋“ค๋ผ๋ฆฌ ์ด๋ฒคํŠธ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์•„ ํŠน์ • ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์—์„œ์˜ ์ž‘์—…์ด ์‹คํŒจํ•˜๋ฉด ์ด์ „๊นŒ์ง€์˜ ์ž‘์—…์ด ์™„๋ฃŒ๋œ ๋งˆ์ดํฌ์„œ๋น„์Šค๋“ค์—๊ฒŒ ๋ณด์ƒ(complemetary) ์ด๋ฒคํŠธ๋ฅผ ์†Œ์‹ฑํ•จ์œผ๋กœ์จ ๋ถ„์‚ฐ ํ™˜๊ฒฝ์—์„œ ์›์ž์„ฑ(atomicity)์„ ๋ณด์žฅํ•˜๋Š” ํŒจํ„ด

commit

Last updated