ํฐ์คํ ๋ฆฌ ๋ทฐ
๐ฏ Kafka Concurrency Control
Race Condition
๊ฒฝ์์ํ๋ ๋ ๊ฐ ์ด์์ ์ค๋ ๋๊ฐ ๊ณต์ ๋ฐ์ดํฐ์ ์ก์ธ์ค ํ ์ ์๊ณ , ๋์์ ๋ณ๊ฒฝ์ ํ๋ ค๊ณ ํ ๋ ๋ฐ์ํ๋ ๋ฌธ์
- Race Condition ์ผ๋ก ๋์์ ๋ค์ด์ค๋ ์์ฒญ๋ค์ด ๊ฐฑ์ ์ ๊ฐ์ ์ฝ๊ณ , ์์ ํ๋ฉด์
- ์ค์ ๊ฐฑ์ ์ด ๋๋ฝ๋๋ ํ์์ด ๋ฐ์
Series
๐น Kafka
๋ถ์ฐ ์คํธ๋ฆฌ๋ฐ ํ๋ซํผ์ผ๋ก, ์ฃผ๋ก ๋๊ท๋ชจ ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ๋ฉ์์ง์ ์ฌ์ฉ
๋ฆฌ๋ ์ ์ถ(Leader Election) ๋๋ ํ์กฐ์ ์๋น์ ํจํด(Cooperative Consumer Pattern) ์ ํ์ฉํ์ฌ ํน์ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ์กฐ์จ
.
๋์ ๋ฐฉ์.
- ๋ฆฌ๋ ์ ์ถ์ ํตํ ๋ฝ
- Kafka์ ํํฐ์
๊ณผ ์คํ์
์ ์ด์ฉํ์ฌ, ํน์ ์์
์ ์ํํ ๋ฆฌ๋ ์ ์ถ
- ํ๋์ Kafka ํํฐ์ ์์ ๋ฉ์์ง๋ฅผ ์๋นํ๋ ์ฌ๋ฌ ์ปจ์๋จธ ์ค ํ๋๊ฐ ๋ฆฌ๋๊ฐ ๋์ด ํน์ ๋ฆฌ์์ค์ ๋ํ ์์ ์ ์ํ โ ์ด ๋ฆฌ๋ ์ญํ ์ด ์ผ์ข ์ ๋ฝ ์ญํ
- ๋ง์ฝ ๋ฆฌ๋๊ฐ ์คํจํ๊ฑฐ๋ ํน์ ์๊ฐ ๋์ ์๋ตํ์ง ์์ผ๋ฉด, ๋ค๋ฅธ ์ปจ์๋จธ๊ฐ ์๋ก์ด ๋ฆฌ๋๋ก ์ ์ถ๋์ด ์์ ์ ์ด์ด๋ฐ์
- Kafka์ ํํฐ์
๊ณผ ์คํ์
์ ์ด์ฉํ์ฌ, ํน์ ์์
์ ์ํํ ๋ฆฌ๋ ์ ์ถ
- ํ์กฐ์ ์๋น์ ํจํด:
- ์ฌ๋ฌ ์ปจ์๋จธ๊ฐ ๋์ผํ Kafka ํ ํฝ์์ ๋ฉ์์ง๋ฅผ ์๋นํ ๋, ์๋ก ํ๋ ฅํ์ฌ ํน์ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ์กฐ์จ
- ํน์ ๋ฆฌ์์ค๋ฅผ ๋์์ ์ ๊ทผํ์ง ์๋๋ก ํ์ํ๋ ๊ณผ์ ์ด ํ์ โ ๋ฝ๊ณผ ์ ์ฌํ ๊ธฐ๋ฅ์ ๊ตฌํ ๊ฐ๋ฅ
- ๋ถ์ฐ ํธ๋์ญ์
๊ด๋ฆฌ:
- Kafka ํธ๋์ญ์ ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ, ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๋ฉด์ ๋ฝ์ ์ค์ ํ๊ณ ํด์
- ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๋ ๋์ ํธ๋์ญ์ ์ ์ ์งํ๊ณ , ์์ ์ด ๋๋๋ฉด ํธ๋์ญ์ ์ ์ปค๋ฐํ๋ฉด์ ๋ฝ์ ํด์ ํ๋ ๋ฐฉ์
์ฅ์ .
๋์ ํ์ฅ์ฑ
- ๋๊ท๋ชจ์ ๋ถ์ฐ ์์คํ ์์ ๋์ ํ์ฅ์ฑ์ ์ ๊ณตํ๋๋ก ์ค๊ณ
- ์ฌ๋ฌ ์ปจ์๋จธ๊ฐ ๋์ผํ Kafka ํด๋ฌ์คํฐ์์ ๋ฝ์ ๊ด๋ฆฌ
๋ด๊ฒฐํจ์ฑ
- ๋ด๊ฒฐํจ์ฑ(fault-tolerance)์ ์ง์
- ๋ฆฌ๋ ์ ์ถ ๋ฐฉ์์ด๋ ํ์กฐ์ ์๋น์ ํจํด์ ์ฌ์ฉํ๋ฉด ํน์ ๋ ธ๋๊ฐ ์คํจํ๋๋ผ๋ ๋ค๋ฅธ ๋ ธ๋๊ฐ ์์ ์ ์ด์ด๋ฐ์ ๋ฝ์ ์์ ์ฑ์ ๋ณด์ฅ
์ค์ ์ง์คํ๋ ๊ด๋ฆฌ
- Kafka ํ ํฝ์ ์ด์ฉํ์ฌ ๋ฝ ์ํ๋ ์์ ์ํ๋ฅผ ์ค์์์ ๊ด๋ฆฌ
- ์์คํ ์ ๋ฐ์ ์ํ๋ฅผ ์ฝ๊ฒ ๋ชจ๋ํฐ๋งํ๊ณ ๊ด๋ฆฌ
๋ณต์กํ ํธ๋์ญ์ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- Kafka ํธ๋์ญ์ ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉด ๋ฉ์์ง ์ฒ๋ฆฌ์ ํจ๊ป ๋ณต์กํ ํธ๋์ญ์ ์ ๊ด๋ฆฌ
- ๋ฝ์ ์ ์งํ๋ฉด์๋ ๋ณต์กํ ์์ ์ ์์ ํ๊ฒ ์ํ
๋จ์ .
๋ณต์ก์ฑ ์ฆ๊ฐ
- ํนํ, ๋ฆฌ๋ ์ ์ถ์ด๋ ํ์กฐ์ ์๋น์ ํจํด์ ๊ตฌํํ๋ ค๋ฉด ๋ ๋ง์ ์ฝ๋ฉ๊ณผ ์ค์ ์ด ํ์
์ง์ฐ ์๊ฐ
- Kafka ๋ถ์ฐ ์ํคํ ์ฒ์ ๋ฐ์ดํฐ ์ ๋ฌ ์ง์ฐ์ผ๋ก ์ธํด ๋ฝ ํด์ ๋ ๋ฆฌ๋ ์ ์ถ ๊ณผ์ ์์ ์ง์ฐ ๋ฐ์
- ์ค์๊ฐ ์ฒ๋ฆฌ๊ฐ ์ค์ํ ํ๊ฒฝ์์๋ ๋จ์
์ค๋ฒํค๋
- ๋ฝ ๊ด๋ฆฌ๋ฅผ ์ํด ๋ฉ์์ง์ ์์ฐ, ์๋น, ๋ฆฌ๋ ์ ์ถ ๊ณผ์ ์์ ์ถ๊ฐ์ ์ธ ์ค๋ฒํค๋๊ฐ ๋ฐ์
- ํนํ, ๋ฝ์ ์์ฃผ ์ค์ ํ๊ณ ํด์ ํ๋ ์์ ์ด ๋ง๋ค๋ฉด ์ฑ๋ฅ์๋ ์ํฅ
์ผ๊ด์ฑ ๋ฌธ์
- ๋ฝ์ ๊ด๋ฆฌํ๋ ๋ฐ ์์ด์ ์ผ๊ด์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์
- ๋ฆฌ๋๊ฐ ์ ์ถ๋๊ธฐ ์ ๊น์ง ์ฌ๋ฌ ์ปจ์๋จธ๊ฐ ๋์ผํ ๋ฆฌ์์ค์ ์ ๊ทผํ๋ ค๋ ๊ฒฝํฉ์ด ๋ฐ์
- ์ผ๊ด์ฑ ๋ฌธ์ ํด๊ฒฐ์ ์ํด ์ถ๊ฐ์ ์ธ ์ ์ด ๋ก์ง์ด ํ์
- ๋ฝ์ ๊ด๋ฆฌํ๋ ๋ฐ ์์ด์ ์ผ๊ด์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์
ํธ๋์ญ์ ๊ด๋ฆฌ์ ๋ณต์ก์ฑ
- Kafka ํธ๋์ญ์ ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๋ฝ์ ๊ด๋ฆฌํ๋ ค๋ฉด, ๋ณต์กํ ํธ๋์ญ์ ์ ์ด๊ฐ ํ์
- ํธ๋์ญ์ ์ด ๊ธธ์ด์ง๊ฑฐ๋ ๋ง์ ๋ฆฌ์์ค๋ฅผ ์ ๊ทธ๋ ๊ฒฝ์ฐ, ์ฑ๋ฅ ์ ํ๋ ๋ฐ๋๋ฝ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐ
์ฌ๋ก.
- ๋ถ์ฐ ์์คํ
์์์ ๋ฆฌ๋ ์ ์ถ
- ์ฌ๋ฌ ๋ ธ๋๊ฐ ๋์ผํ ์์ ์ ์ํํ๋ ค๊ณ ํ ๋, ํ๋์ ๋ ธ๋๋ฅผ ๋ฆฌ๋๋ก ์ ์ถํ์ฌ ์์ ์ ์กฐ์ ํ๋ ์ํฉ
- ex) ์ฌ๋ฌ ๋ง์ดํฌ๋ก์๋น์ค๊ฐ ๋์ผํ ์์ ์ ์ํํ์ง ์๋๋ก ๋ฆฌ๋๋ฅผ ์ ์ถํ๋ ๋ฐ ์ฌ์ฉ
- ํ์กฐ์ ์์
์ํ
- ์ฌ๋ฌ ์ปจ์๋จธ๊ฐ ๋์ผํ Kafka ํ ํฝ์์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ฉด์, ํน์ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ์กฐ์จํด์ผ ํ๋ ๊ฒฝ์ฐ
- ex) ์ฌ๋ฌ ์ปจ์๋จธ๊ฐ ๋์ผํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ ๊ทผํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋, Kafka ๋ฝ์ ์ฌ์ฉํด ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์ ์ง
- ๋ณต์กํ ๋ถ์ฐ ํธ๋์ญ์
- ๋ถ์ฐ ํธ๋์ญ์ ์ ๊ด๋ฆฌํ๋ ์ํฉ์์ Kafka์ ํธ๋์ญ์ ๊ธฐ๋ฅ๊ณผ ๋ฝ์ ๊ฒฐํฉํ์ฌ, ์์ ํ๊ฒ ์์ ์ ์ํ
- ex) ๋ฉ์์ง ์ฒ๋ฆฌ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๋ฐ์ดํธ๊ฐ ๋์์ ์ด๋ฃจ์ด์ง๋ ์ํฉ์์ Kafka ๋ฝ์ ํตํด ์ผ๊ด์ฑ์ ๋ณด์ฅ
- ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ
- ๋๊ท๋ชจ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ๋ผ์ธ์์ ์ฌ๋ฌ ์์ ์ ์กฐ์จํ๊ณ ๊ด๋ฆฌํด์ผ ํ๋ ๊ฒฝ์ฐ ์์ ๊ฐ์ ์์์ ์ผ๊ด์ฑ์ ์ ์ง
...
Start Kafka
- docker-compose.yml
version: '3' # Docker Compose ํ์ผ ๋ฒ์ ์ง์
services: # ์ฌ๋ฌ๊ฐ์ Docker ์ปจํ
์ด๋ ์๋น์ค ์ ์
zookeeper: # Zookeeper ์๋น์ค ์ ์
image: wurstmeister/zookeeper:3.4.6
container_name: zookeeper
ports:
- "2181:2181" # ํธ์คํธ์ 2181 ํฌํธ๋ฅผ ์ปจํ
์ด๋์ 2181 ํฌํธ์ ๋ฐ์ธ๋ฉ
kafka: # kafka ์๋น์ค ์ ์
image: wurstmeister/kafka:2.12-2.5.0
container_name: kafka
ports:
- "9092:9092" # ํธ์คํธ์ 9092 ํฌํธ๋ฅผ ์ปจํ
์ด๋์ 9092 ํฌํธ์ ๋ฐ์ธ๋ฉ
environment: # kafka ์ปจํ
์ด๋์ ํ๊ฒฝ ๋ณ์ ์ค์
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:29092,OUTSIDE://localhost:9092 # ๋ด/์ธ๋ถ์์ ์ ๊ทผํ ์ ์๋ ๋ฆฌ์ค๋ ์ฃผ์ ์ค์
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT # ๋ฆฌ์ค๋์ ๋ณด์ ํ๋กํ ์ฝ ๋งคํ
KAFKA_LISTENERS: INSIDE://0.0.0.0:29092,OUTSIDE://0.0.0.0:9092 # ์ปจํ
์ด๋ ๋ด๋ถ์์ ์ฌ์ฉํ ๋ฆฌ์ค๋ ์ฃผ์ ์ค์
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE # ๋ธ๋ก์ปค ๊ฐ ํต์ ์ ์ฌ์ฉํ ๋ฆฌ์ค๋ ์ด๋ฆ
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 # Kafka๊ฐ Zookeeper์ ์ฐ๊ฒฐํ๊ธฐ ์ํ ์ฃผ์
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Docker ์์ผ์ ์ปจํ
์ด๋์ ๊ณต์ ํ์ฌ Docker ์ด๋ฒคํธ๋ฅผ ๊ด๋ฆฌํ ์ ์๋๋ก ์ค์
kafka-ui:
image: provectuslabs/kafka-ui
container_name: kafka-ui
ports:
- "8989:8080"
restart: always
environment:
- KAFKA_CLUSTERS_0_NAME=local
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:29092
- KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181
- run kafka
# ์นดํ์นด ์คํ
$ docker-compose up -d
or
$ docker-compose -f docker-compose.yml up
# ํ ํฝ์์ฑ
$ docker exec -it kafka kafka-topics.sh --bootstrap-server localhost:9092 --create --topic stock_decrease
Created topic testTopic.
# ํ๋ก๋์ ์คํ
$ docker exec -it kafka kafka-console-producer.sh --topic stock_decrease --broker-list 0.0.0.0:9092
>Hello
# ์ปจ์๋จธ ์คํ
$ docker exec -it kafka kafka-console-consumer.sh --topic stock_decrease --bootstrap-server localhost:9092
Hello
# ์นดํ์นด ์ข
๋ฃ
$ docker-compose down
.
commit log.
...
๐ง kafka + redis ์ ์ฉ ๋ฐฉ์
- Producer๋ ๋ฉ์์ง ๋ฐํ ์ ๋ ๋์ค๋ก ์๊ณ๊ฐ ์ ์ด
- ์๊ณ๊ฐ์ด ๋์ง ์์์ ๊ฒฝ์ฐ: ์ดํ ๋น์ฆ๋์ค ๋ก์ง ์ฒ๋ฆฌ๋ฅผ ์ํด Consumer์๊ฒ ๋ฉ์์ง ์ ์ก
- ์๊ณ๊ฐ์ด ๋์์ ๊ฒฝ์ฐ: ๋ฉ์์ง ๋ฏธ๋ฐํ ๋ฐ ์ฌ์ฉ์์๊ฒ ์ฒ๋ฆฌ ๋ถ๊ฐ ์๋ฆผ
- Consumer๋ ๋น์ฆ๋์ค ๋ก์ง๋ง ์ํ
์ด๋ ๊ฒ ํ ๊ฒฝ์ฐ ์๊ณ๊ฐ์ ๋ ๋์ค๋ฅผ ํตํด ๋น ๋ฅด๊ฒ ํ์ธํ๊ณ , ์ค์ ์ฒ๋ฆฌ๋ ์ปจ์๋จธ๊ฐ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
public void decrease(final Long userId, final Long stockId) {
final KafkaStock stock = stockRepository.findById(stockId).orElseThrow();
// ๋ ๋์ค๋ฅผ ํตํด ์๊ณ๊ฐ์ ํ์ธ
final Long count = redisIncrRepository.increment(stockId);
stock.validQuantity(count);
// ์ค์ ์ฒ๋ฆฌ๋ ์ปจ์๋จธ๊ฐ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ
stockDecreaseProducer.create(userId, stockId);
}
.
๐ ๏ธ ์ฑ๋ฅ ํ ์คํธ.
ํ์ ์๋: 50,000
User: 296
Processes: 8
Threads: 37
Duration: 3 min (01:52)
๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์ ํํ๊ฒ 50,000 ๊ฑด๋ง ์ฑ๊ณต์ผ๋ก ์ฒ๋ฆฌ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
00:46 ์ดํ์๋ ๋ชจ๋ ์๋์ด 0์ผ๋ก ์กฐํ๋์ด, ์ฌ๊ณ ๋ถ์กฑ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
Kafka ๋ฉ์์ง๋ ์ ํํ 50,000 ๊ฑด๋ง ์ ์ก์ด ๋์๋ค.
๋ง์ผ ์ปจ์๋จธ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ๋ณ๋๋ก ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋๋ก ๋ก๊ทธ๋ฅผ ๋จ๊ฒจ๋ ์๋ ์๋ค.
'Web > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Monitoring] Prometheus & Grafana (0) | 2024.10.04 |
---|---|
[๋์์ฑ] Java, Database, Redis, Kafka ๋ฐฉ์ ์ฑ๋ฅ ๋น๊ต (0) | 2024.08.25 |
[๋์์ฑ] Redis Concurrency Control(incr, Lettuce, Redisson Lock) (0) | 2024.08.18 |
[๋์์ฑ] DataBase Concurrency Controll(Pessimistic, Optimistic, Named Lock) (0) | 2024.08.17 |
[๋์์ฑ] Java Concurrency Control(asynchronous, synchronized) (2) | 2024.08.16 |