1. Raft Consensus Algorithm
ํด๋ฌ์คํฐ๊ฐ ์ฌ๋ฌ๊ฐ์ ๋
ธ๋๋ก ๊ตฌ์ฑ๋์ด ์์๋, ๋
ธ๋๋ค์ด ์๋ก ๋์ผํ ์ํ๋ฅผ ์ ์งํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
์ด๋ก ๋นผ๊ณ ์ค์
zookeeper
vi docker-compose.yml
Copy version: '3.8'
services:
zk1:
image: confluentinc/cp-zookeeper:7.4.1
hostname: zk1
container_name: zk1
environment:
ZOOKEEPER_SERVER_ID: 1
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ZOOKEEPER_INIT_LIMIT: 5
ZOOKEEPER_SYNC_LIMIT: 2
ZOOKEEPER_SERVERS: zk1:2888:3888;zk2:2888:3888;zk3:2888:3888
zk2:
image: confluentinc/cp-zookeeper:7.4.1
hostname: zk2
container_name: zk2
environment:
ZOOKEEPER_SERVER_ID: 2
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ZOOKEEPER_INIT_LIMIT: 5
ZOOKEEPER_SYNC_LIMIT: 2
ZOOKEEPER_SERVERS: zk1:2888:3888;zk2:2888:3888;zk3:2888:3888
zk3:
image: confluentinc/cp-zookeeper:7.4.1
hostname: zk3
container_name: zk3
environment:
ZOOKEEPER_SERVER_ID: 3
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
ZOOKEEPER_INIT_LIMIT: 5
ZOOKEEPER_SYNC_LIMIT: 2
ZOOKEEPER_SERVERS: zk1:2888:3888;zk2:2888:3888;zk3:2888:3888
kafka1:
image: confluentinc/cp-kafka:7.4.1
hostname: kafka1
container_name: kafka1
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zk1:2181,zk2:2182,zk3:2183
KAFKA_LISTENERS: INTERNAL://kafka1:9092
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
kafka2:
image: confluentinc/cp-kafka:7.4.1
hostname: kafka2
container_name: kafka2
environment:
KAFKA_BROKER_ID: 2
KAFKA_ZOOKEEPER_CONNECT: zk1:2181,zk2:2182,zk3:2183
KAFKA_LISTENERS: INTERNAL://kafka2:9092
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka2:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
kafka3:
image: confluentinc/cp-kafka:7.4.1
hostname: kafka3
container_name: kafka3
environment:
KAFKA_BROKER_ID: 3
KAFKA_ZOOKEEPER_CONNECT: zk1:2181,zk2:2182,zk3:2183
KAFKA_LISTENERS: INTERNAL://kafka3:9092
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka3:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
kafka-ui:
image: provectuslabs/kafka-ui:latest
hostname: kafka-ui
container_name: kafka-ui
ports:
- 8080:8080
environment:
KAFKA_CLUSTERS_0_NAME: kafka
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:9092,kafka2:9092,kafka3:9092
depends_on:
- kafka1
- kafka2
- kafka3
Copy cd 'sample/raft/zookeeper-3-node'
docker-compose up -d
์ด์ zookeeper๋ฅผ ํ๋ ์ฃฝ์ฌ๋ด
๋๋ค.
Copy docker stop zk3
kafka-topics --bootstrap-server kafka1:9092 --create --topic test2
๋์
ํ๋ ๋ ์ฃฝ์ฌ๋ด
๋๋ค.
Copy docker stop zk2
kafka-topics --bootstrap-server kafka1:9092 --create --topic test3
์๋ฌ๋ฉ๋๋ค. ์์ฑ๋์ง ์์ต๋๋ค.
3๊ฐ์์๋ 2๊ฐ ์ฃฝ์ผ๋ฉด ํด๋ฌ์คํฐ ํญ๋ฐ..
kraft
3๊ฐ node kraft kafka cluster๋ฅผ ๊ตฌ์ฑํ๋ค.
vi docker-compose.yml
Copy version: '3'
services:
controller1:
image: confluentinc/cp-kafka:7.4.0
hostname: controller
container_name: controller
# ports:
# - '9093:9093'
environment:
KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
KAFKA_LISTENERS: 'CONTROLLER://controller1:9093'
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_PROCESS_ROLES: 'controller'
KAFKA_NODE_ID: 11
KAFKA_CONTROLLER_QUORUM_VOTERS: '11@controller1:9093,12@controller2:9093,13@controller3:9093'
# Replace CLUSTER_ID with a unique base64 UUID using "bin/kafka-storage.sh random-uuid"
# See https://docs.confluent.io/kafka/operations-tools/kafka-tools.html#kafka-storage-sh
CLUSTER_ID: 'ciWo7IWazngRchmPES6q5A=='
controller2:
image: confluentinc/cp-kafka:7.4.0
hostname: controller2
container_name: controller2
environment:
KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
KAFKA_LISTENERS: 'CONTROLLER://controller2:9093'
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_PROCESS_ROLES: 'controller'
KAFKA_NODE_ID: 12
KAFKA_CONTROLLER_QUORUM_VOTERS: '11@controller1:9093,12@controller2:9093,13@controller3:9093'
# Replace CLUSTER_ID with a unique base64 UUID using "bin/kafka-storage.sh random-uuid"
# See https://docs.confluent.io/kafka/operations-tools/kafka-tools.html#kafka-storage-sh
CLUSTER_ID: 'ciWo7IWazngRchmPES6q5A=='
controller3:
image: confluentinc/cp-kafka:7.4.0
hostname: controller3
container_name: controller3
environment:
KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER'
KAFKA_LISTENERS: 'CONTROLLER://controller3:9093'
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_PROCESS_ROLES: 'controller'
KAFKA_NODE_ID: 13
KAFKA_CONTROLLER_QUORUM_VOTERS: '11@controller1:9093,12@controller2:9093,13@controller3:9093'
# Replace CLUSTER_ID with a unique base64 UUID using "bin/kafka-storage.sh random-uuid"
# See https://docs.confluent.io/kafka/operations-tools/kafka-tools.html#kafka-storage-sh
CLUSTER_ID: 'ciWo7IWazngRchmPES6q5A=='
kafka1:
image: confluentinc/cp-kafka:7.4.0
container_name: kafka1
hostname: kafka1
ports:
- '9092:9092'
environment:
KAFKA_NODE_ID: 1
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: '11@controller1:9093,12@controller2:9093,13@controller3:9093'
KAFKA_LISTENERS: 'INTERNAL://kafka1:9092'
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,INTERNAL:PLAINTEXT'
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_PROCESS_ROLES: 'broker'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
KAFKA_JMX_PORT: 9999
KAFKA_JMX_HOSTNAME: kafka1
KAFKA_LOG_DIRS: '/tmp/kraft-combined-logs'
# Replace CLUSTER_ID with a unique base64 UUID using "bin/kafka-storage.sh random-uuid"
# See https://docs.confluent.io/kafka/operations-tools/kafka-tools.html#kafka-storage-sh
CLUSTER_ID: 'ciWo7IWazngRchmPES6q5A=='
depends_on:
- controller1
- controller2
- controller3
kafka2:
image: confluentinc/cp-kafka:7.4.0
container_name: kafka2
hostname: kafka2
environment:
KAFKA_NODE_ID: 2
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: '11@controller1:9093,12@controller2:9093,13@controller3:9093'
KAFKA_LISTENERS: 'INTERNAL://kafka2:9092'
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka2:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,INTERNAL:PLAINTEXT'
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_PROCESS_ROLES: 'broker'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
KAFKA_JMX_PORT: 9999
KAFKA_JMX_HOSTNAME: kafka2
KAFKA_LOG_DIRS: '/tmp/kraft-combined-logs'
# Replace CLUSTER_ID with a unique base64 UUID using "bin/kafka-storage.sh random-uuid"
# See https://docs.confluent.io/kafka/operations-tools/kafka-tools.html#kafka-storage-sh
CLUSTER_ID: 'ciWo7IWazngRchmPES6q5A=='
depends_on:
- controller1
- controller2
- controller3
kafka3:
image: confluentinc/cp-kafka:7.4.0
container_name: kafka3
hostname: kafka3
environment:
KAFKA_NODE_ID: 3
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: '11@controller1:9093,12@controller2:9093,13@controller3:9093'
KAFKA_LISTENERS: 'INTERNAL://kafka3:9092'
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka3:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,INTERNAL:PLAINTEXT'
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_PROCESS_ROLES: 'broker'
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 3
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 2
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 3
KAFKA_JMX_PORT: 9999
KAFKA_JMX_HOSTNAME: kafka3
KAFKA_LOG_DIRS: '/tmp/kraft-combined-logs'
# Replace CLUSTER_ID with a unique base64 UUID using "bin/kafka-storage.sh random-uuid"
# See https://docs.confluent.io/kafka/operations-tools/kafka-tools.html#kafka-storage-sh
CLUSTER_ID: 'ciWo7IWazngRchmPES6q5A=='
depends_on:
- controller1
- controller2
- controller3
kafka-ui:
image: provectuslabs/kafka-ui:latest
restart: always
hostname: kafka-ui
container_name: kafka-ui
ports:
- 8080:8080
environment:
KAFKA_CLUSTERS_0_NAME: kafka
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:9092,kafka2:9092,kafka3:9092
# KAFKA_CLUSTERS_0_KAFKACONNECT_0_ADDRESS: http://kafka1:8083
# KAFKA_CLUSTERS_0_KAFKACONNECT_0_NAME: kafka1-connect
depends_on:
- kafka1
- kafka2
- kafka3
- controller1
- controller2
- controller3
Copy cd kafka/sample/raft/3-node
docker-compose up -d
docker exec -it kafka1 bash
# create topic
kafka-topics --bootstrap-server kafka1:9092,kafka2:9092,kafka3:9092 --create --topic test
๋์ํฉ๋๋ค.
์ด์ controler๋ฅผ ํ๋ ์ฃฝ์ฌ๋ด
๋๋ค.
Copy docker stop controller3
kafka-topics --bootstrap-server kafka1:9092,kafka2:9092,kafka3:9092 --create --topic test2
์ฌ์ ํ ๋์ํฉ๋๋ค.
ํ๋ ๋ ์ฃฝ์ฌ๋ด
๋๋ค.
Copy docker stop controller2
kafka-topics --bootstrap-server kafka1:9092,kafka2:9092,kafka3:9092 --create --topic test2
Copy Error while executing topic command : Call(callName=createTopics, deadlineMs=1705497739741, tries=1, nextAllowedTryMs=1705497739889) timed out at 1705497739789 after 1 attempt(s)
[2024-01-17 13:22:19,792] ERROR org.apache.kafka.common.errors.TimeoutException: Call(callName=createTopics, deadlineMs=1705497739741, tries=1, nextAllowedTryMs=1705497739889) timed out at 1705497739789 after 1 attempt(s)
Caused by: org.apache.kafka.common.errors.DisconnectException: Cancelled createTopics request with correlation id 3 due to node 2 being disconnected
(kafka.admin.TopicCommand$)
์์ฑ๋์ง ์์ต๋๋ค. ์ด์ ๋ controller๊ฐ ์ ์กฑ์(2๊ฐ)๋ฅผ ๋์ง ๋ชปํด์ ์
๋๋ค.
๊ฒฐ๋ก
kraft๋ ์ฌ์ ํ Raft Consensus Algorithm ์ ์ฌ์ฉํ๊ธฐ๋๋ฌธ์ ์ ์กฑ์๋ฅผ ๋์ง ๋ชปํ๋ฉด ๋์ํ์ง ์์ต๋๋ค.
์ฐธ๊ณ
https://thesecretlivesofdata.com/raft/ ์ด ์ฌ์ดํธ ์ ๊ธฐํ๋ค์
๋ด๊ฒฐํจ์ฑ์ ์ํ ์ต์ ์ ๋
ธ๋ ์
ํฉ์ ์๊ณ ๋ฆฌ์ฆ(Consensus Algorithm)์ ์ฑํํ ๋ถ์ฐ ์์คํ
์์๋ ์ ์ฒด ๋
ธ๋ ์๋ฅผ ๊ฐ๊ธ์ 3๊ฐ ์ด์์ ํ์๋ก ์ ์งํ๋ ๊ฒ์ด ๊ถ์ฅ๋๋ค. ์ด์ ๋ ์๋์ ๊ฐ๋ค.
์ ์ฒด ๋
ธ๋ ์
ํ์ ์ ์กฑ์ ํ์ฉ
๊ฐ๋ฅ ์ฅ์ ๋
ธ๋ ์
... ... ... 2k (์ง์) k+1 k-1 2k+1 (ํ์) k+1 k
์ ์ฒด ๋
ธ๋ ์๊ฐ 3๊ฐ ์ด์์ด์ด์ผ ํ์ฉ ๊ฐ๋ฅํ ์ฅ์ ๋
ธ๋๊ฐ ์๊ธด๋ค. ๊ทธ ๋ฏธ๋ง์ผ๋ก๋ ๋ด๊ฒฐํจ์ฑ์ ๊ฐ์ถ ์ ์๋ค.
2๊ฐ์ ๋
ธ๋๋ก ํด๋ฌ์คํฐ๋ฅผ ๊ตฌ์ฑํ๋ ๊ฒ์ ์์ ๊ด๋ฆฌ์ ์ธก๋ฉด์์๋ ๋ด๊ฒฐํจ์ฑ์ ์ธก๋ฉด์์๋ ๋ชจ๋ ๋นํจ์จ์ ์ธ ๋ฐฉ์์์ ์ ์ ์๋ค.
zookeeper๋ controller ํด๋ฌ์คํฐ๋ฅผ ์ด์ผ๊ธฐํ๋๊ฒ์
๋๋ค. kafka ํด๋ฌ์คํฐ๋ ๋ค๋ฅธ ์ด์ผ๊ธฐ์
๋๋ค.