Skip to content

Commit

Permalink
add: πŸ“° [Chapter 05] ν”„λ‘œκ·Έλž¨ λ‚΄μ—μ„œ μ½”λ“œλ‘œ μΉ΄ν”„μΉ΄ κ΄€λ¦¬ν•˜κΈ°
Browse files Browse the repository at this point in the history
  • Loading branch information
Shinminjin committed Dec 15, 2024
1 parent 28fd7a0 commit ed17074
Showing 1 changed file with 310 additions and 0 deletions.
310 changes: 310 additions & 0 deletions _posts/kafka/2024-12-15-chapter05.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
---
title: Chapter 05. ν”„λ‘œκ·Έλž¨ λ‚΄μ—μ„œ μ½”λ“œλ‘œ μΉ΄ν”„μΉ΄ κ΄€λ¦¬ν•˜κΈ°
date: 2024-12-15 10:00:00 +0900
categories: [μΉ΄ν”„μΉ΄ ν•΅μ‹¬κ°€μ΄λ“œ]
tags: [μΉ΄ν”„μΉ΄ ν•΅μ‹¬κ°€μ΄λ“œ]
---

## **1.1. AdminClient κ°œμš”** πŸ’‘

### **AdminClient의 μ£Όμš” κΈ°λŠ₯**

- ν† ν”½ 쑰회, 생성, μ‚­μ œ
- ν΄λŸ¬μŠ€ν„° 상세 정보 확인
- ACL 및 μ„€μ • 관리


### **비동기 처리**

- `AdminClient`의 λ©”μ„œλ“œλŠ” **비동기**둜 μž‘λ™ν•˜λ©°, κ²°κ³Όλ₯Ό **`Future` 객체**둜 λ°˜ν™˜
- λ°˜ν™˜λœ `Future` 객체λ₯Ό 톡해 μž‘μ—… κ²°κ³Όλ₯Ό ν™•μΈν•˜κ±°λ‚˜, μ·¨μ†Œ 및 λŒ€κΈ° κ°€λŠ₯
- μž‘μ—…μ΄ μ™„λ£Œλ˜λ©΄ 후속 μž‘μ—… 싀행을 μœ„ν•œ λ©”μ„œλ“œλ„ 제곡
- ex. `AdminClient.createTopics` λ©”μ„œλ“œ
- `CreateTopicsResult` 객체 λ°˜ν™˜ν•˜λ©°, μƒμ„±λœ 각 ν† ν”½μ˜ μƒνƒœλ₯Ό κ°œλ³„μ μœΌλ‘œ 확인 κ°€λŠ₯


### **μ΅œμ’…μ  일관성(Eventual Consistency)**

- μΉ΄ν”„μΉ΄μ˜ λ©”νƒ€λ°μ΄ν„°λŠ” λΉ„λ™κΈ°μ μœΌλ‘œ μ „νŒŒ
- μƒˆ ν† ν”½ 생성 μ‹œ λͺ¨λ“  λΈŒλ‘œμ»€μ— λ™κΈ°ν™”λ˜κΈ°κΉŒμ§€ μ‹œκ°„μ΄ ν•„μš”



## **1.2. AdminClient μ˜΅μ…˜ βš™οΈ**

### **λ©”μ„œλ“œλ³„ μ˜΅μ…˜**

- `AdminClient`λŠ” μž‘μ—…μ— 따라 μ „μš© μ˜΅μ…˜ 객체λ₯Ό 제곡
- ex. `listTopics` β†’ `ListTopicsOptions` , `describeCluster` β†’ `DescribeClusterOptions`
- 각 μ˜΅μ…˜μ„ 톡해 μž‘μ—…μ˜ μ„ΈλΆ€ λ™μž‘μ„ μ„Έλ°€ν•˜κ²Œ μ„€μ • κ°€λŠ₯


### **곡톡 λ§€κ°œλ³€μˆ˜ μ˜΅μ…˜**

- `timeoutMs`둜 ν΄λŸ¬μŠ€ν„° 응닡 λŒ€κΈ° μ‹œκ°„ μ„€μ •
- 응닡 μ‹œκ°„ 초과 μ‹œ `TimeoutException` λ°œμƒ



## **1.3. AdminClient의 ꡬ쑰적 νŠΉμ§• πŸ—οΈ**

### **μˆ˜ν‰μ  섀계**

- `AdminClient`λŠ” **`KafkaAdminClient` ν”„λ‘œν† μ½œ**둜 μž‘μ—… μˆ˜ν–‰
- 객체 κ°„ 의쑴 κ΄€κ³„λ‚˜ λ„€μž„μŠ€νŽ˜μ΄μŠ€ 없이 ν•„μš”ν•œ λ©”μ„œλ“œμ— 직접 μ ‘κ·Ό κ°€λŠ₯
- λ³΅μž‘ν•œ ꡬ쑰 없이 κ°„κ²°ν•˜κ²Œ 섀계됨


### **μ‚¬μš©μž μΉœν™”μ„±**

- JavaDoc λ¬Έμ„œμ™€ IDE μžλ™μ™„μ„±μœΌλ‘œ λ©”μ„œλ“œλ₯Ό μ‰½κ²Œ 탐색할 수 있음



## **1.4. μΆ”κ°€ μ°Έκ³  πŸ“š**

### **μž‘μ—… μœ ν˜•λ³„ 처리 μœ„μΉ˜**

- ν΄λŸ¬μŠ€ν„° λ³€κ²½ μž‘μ—…(`create`, `delete`, `alter`)은 **컨트둀러**κ°€ λ‹΄λ‹Ή
- 쑰회 μž‘μ—…(`list`, `describe`)은 λΆ€ν•˜κ°€ 적은 λΈŒλ‘œμ»€μ—μ„œ μ²˜λ¦¬λ˜μ–΄ νš¨μœ¨μ„± κ·ΉλŒ€ν™”


### **주킀퍼 μˆ˜μ • κΈˆμ§€**

- μΉ΄ν”„μΉ΄λŠ” 주킀퍼 μ˜μ‘΄μ„±μ„ 점차 μ œκ±°ν•˜λŠ” λ°©ν–₯으둜 λ°œμ „ 쀑
- 주킀퍼λ₯Ό 직접 μˆ˜μ •ν•˜λŠ” μž‘μ—…μ€ ꢌμž₯λ˜μ§€ μ•ŠμœΌλ©°, μ˜ˆμƒμΉ˜ λͺ»ν•œ 문제λ₯Ό μ΄ˆλž˜ν•  수 있음



## **2. AdminClient μ‚¬μš©λ²•: 생성, μ„€μ •, λ‹«κΈ° πŸ”‘**

### **AdminClient 생성 및 λ‹«κΈ°**

```java
Properties props = new Properties();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");

AdminClient admin = AdminClient.create(props);

admin.close(Duration.ofSeconds(30));
```

- `Properties` 객체λ₯Ό 톡해 `AdminClient` 생성
- `bootstrap.servers` μ„€μ •μœΌλ‘œ μΉ΄ν”„μΉ΄ ν΄λŸ¬μŠ€ν„°μ™€ μ—°κ²°
- `close()` 호좜 μ‹œ, 진행 쀑인 μž‘μ—…μ΄ μ™„λ£Œλ˜κΈ°λ₯Ό μ΅œλŒ€ 30초 λŒ€κΈ°
- 30초λ₯Ό μ΄ˆκ³Όν•œ λ―Έμ™„λ£Œ μž‘μ—…μ— λŒ€ν•΄ μ˜ˆμ™Έ λ°œμƒ


### **DNS κ΄€λ ¨ μ„€μ •**

- **`client.dns.lookup=resolve_canonical_bootstrap_server_only`**
- **DNS 별칭**을 μ‚¬μš©ν•˜λŠ” 경우, λͺ¨λ“  브둜컀 μ΄λ¦„μœΌλ‘œ μžλ™ 등둝 κ°€λŠ₯
- **`client.dns.lookup=use_all_dns_ips`**
- **λ‹€μˆ˜μ˜ IP μ£Όμ†Œ**λ₯Ό 가진 DNS 이름을 ν™œμš©ν•˜μ—¬ μ—°κ²° μ•ˆμ •μ„±μ„ 높일 수 있음


### **응닡 λŒ€κΈ° μ‹œκ°„ μ„€μ •**

- `request.timeout.ms`
- `AdminClient`κ°€ μž‘μ—… 응닡을 κΈ°λ‹€λ¦¬λŠ” μ΅œλŒ€ μ‹œκ°„
- μ œν•œ μ‹œκ°„ 초과 μ‹œ μ˜ˆμ™Έ λ°œμƒ
- μ„œλΉ„μŠ€ μ΄ˆκΈ°ν™” 쀑 νŠΉμ • ν† ν”½μ˜ 쑴재 μ—¬λΆ€λ₯Ό 확인할 λ•Œ ν™œμš© κ°€λŠ₯



## **3. ν•„μˆ˜μ μΈ ν† ν”½ 관리 κΈ°λŠ₯ πŸ“Š**

### **ν† ν”½ 쑰회**

```java
ListTopicsResult topics = admin.listTopics(); // Future 객체 포함
topics.names.get().forEach(System.out::println); // λͺ¨λ“  토픽이름 좜λ ₯
```

- `admin.listTopics()`λŠ” `ListTopicsResult`객체 λ°˜ν™˜
- `Future` 객체λ₯Ό 톡해 λΉ„λ™κΈ°μ μœΌλ‘œ 결과처리
- `Future.get()` 호좜 μ‹œ ν† ν”½ 이름 λͺ©λ‘μ„ 받을 λ•ŒκΉŒμ§€ λŒ€κΈ°ν•˜λ©°, νƒ€μž„μ•„μ›ƒ μ‹œ μ˜ˆμ™Έ λ°œμƒ


### **ν† ν”½ 생성 및 μ‚­μ œ**

- `admin.createTopics` , `admin.deleteTopics` λ©”μ„œλ“œλ‘œ ν† ν”½ 생성 및 μ‚­μ œ μˆ˜ν–‰
- μ‚­μ œλŠ” 볡ꡬ가 λΆˆκ°€λŠ₯ν•˜λ―€λ‘œ μ‹ μ€‘νžˆ 진행


### **ν† ν”½ 쑰건 확인**

- **1개의 νŒŒν‹°μ…˜**으둜 데이터 μˆœμ„œ 보μž₯
- **μ΅œμ†Œ 3개의 λ ˆν”Œλ¦¬μΉ΄**둜 κ°€μš©μ„±κ³Ό μ•ˆμ •μ„± 확보
- **μ••μ°©(compaction) μ„€μ •**으둜 였래된 데이터도 μœ μ§€ κ°€λŠ₯


### **비동기 처리둜 νš¨μœ¨μ„± ν–₯상**

- `Future.get()`을 μ‚¬μš©ν•œ λΈ”λ‘œν‚Ή 방식은 λŒ€κ·œλͺ¨ μš”μ²­ ν™˜κ²½μ—μ„œ λΉ„νš¨μœ¨μ 
- λŒ€μ‹  비동기 방식을 ν™œμš©ν•΄ μ„œλ²„ νš¨μœ¨μ„±μ„ κ·ΉλŒ€ν™”
- HTTP μ„œλ²„λŠ” μΉ΄ν”„μΉ΄ 응닡을 기닀리지 μ•Šκ³  λ‹€λ₯Έ μš”μ²­ 처리 κ°€λŠ₯
- μΉ΄ν”„μΉ΄ 응닡 도착 μ‹œ ν΄λΌμ΄μ–ΈνŠΈμ— μ¦‰μ‹œ 전달, 처리 속도 μ΅œμ ν™”




## **4. μ„€μ • 관리 πŸ› οΈ**

### **ConfigResource 객체 ν™œμš©**

- **브둜컀, 둜그, ν† ν”½**의 섀정을 μ‘°νšŒν•˜κ±°λ‚˜ μˆ˜μ • κ°€λŠ₯
- CLI 툴(`kafka-configs.sh`)외에도 μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ½”λ“œλ‘œ μ„€μ • μž‘μ—… κ°€λŠ₯


### **μ••μ°©(compaction) μ„€μ •**

- μ••μ°© 섀정은 데이터 일관성과 보쑴을 μœ„ν•΄ μ€‘μš”
- 주기적으둜 μ••μ°© μ„€μ • μ—¬λΆ€λ₯Ό μ κ²€ν•˜κ³ , λˆ„λ½ μ‹œ μžλ™μœΌλ‘œ μˆ˜μ • κ°€λŠ₯



## **5. 컨슈머 κ·Έλ£Ή 관리 πŸ‘₯**

- μΉ΄ν”„μΉ΄λŠ” 이전 데이터λ₯Ό λ™μΌν•œ μˆœμ„œλ‘œ μž¬μ²˜λ¦¬ν•  수 μžˆλŠ” κΈ°λŠ₯ 제곡
- νŠΈλŸ¬λΈ”μŠˆνŒ… 및 μž¬ν•΄ 볡ꡬ와 같은 μƒν™©μ—μ„œ 유용



## **5.1. 컨슈머 κ·Έλ£Ή μ‚΄νŽ΄λ³΄κΈ° πŸ‘€**

### **컨슈머 κ·Έλ£Ή λͺ©λ‘ 쑰회**

```java
admin.listConsumerGroups().valid().get().forEach(System.out::println);
```

- `valid()`λŠ” μ—λŸ¬ 없이 λ°˜ν™˜λœ 그룹만 포함
- μ˜ˆμ™ΈλŠ” `errors()` λ©”μ„œλ“œλ‘œ 확인 κ°€λŠ₯


### κ·Έλ£Ή 상세 정보 확인

```java
ConsumerGroupDescription groupDescription = admin
.describeConsumerGroups(CONSUMER_GRP_LIST)
.describedGroups().get(CONSUMER_GROUP).get();

System.out.println("Description of group " + CONSUMER_GROUP + ":" + groupDescription);
```
- `ConsumerGroupDescription` 객체둜 **κ·Έλ£Ή 멀버, ν• λ‹Ήλœ νŒŒν‹°μ…˜, κ·Έλ£Ή 코디넀이터 정보** 확인 κ°€λŠ₯
- **λ§ˆμ§€λ§‰ μ»€λ°‹λœ μ˜€ν”„μ…‹**κ³Ό **지연 μƒνƒœ(lag)**λ₯Ό νŒŒμ•… κ°€λŠ₯



## **5.2. 컨슈머 κ·Έλ£Ή μˆ˜μ •ν•˜κΈ° πŸ”„**

### **지원 κΈ°λŠ₯**

- 컨슈머 κ·Έλ£Ή μ‚­μ œ
- νŠΉμ • 멀버 μ œμ™Έ
- μ»€λ°‹λœ μ˜€ν”„μ…‹ μ‚­μ œ 및 λ³€κ²½


### **μ˜€ν”„μ…‹ λ³€κ²½**

- μ˜€ν”„μ…‹ μ‚­μ œλ‘œ μ»¨μŠˆλ¨Έκ°€ μ²˜μŒλΆ€ν„° 데이터λ₯Ό 읽도둝 μ„€μ • κ°€λŠ₯
- `auto.offset.reset` 값에 따라 처리 μ‹œμž‘ 지점을 μ‘°μ • κ°€λŠ₯


### **μ£Όμ˜μ‚¬ν•­**

- ν™œμ„±ν™”λœ 컨슈머 그룹의 μ˜€ν”„μ…‹ λ³€κ²½ λΆˆκ°€(ex. `UnknownMemberIdException` λ°œμƒ)
- μƒνƒœ μ €μž₯μ†Œλ₯Ό ν•¨κ»˜ μ‘°μ •ν•˜μ§€ μ•ŠμœΌλ©΄ 쀑볡 계산 κ°€λŠ₯μ„± 쑴재
- μ˜€ν”„μ…‹ 변경은 μ»¨μŠˆλ¨Έκ°€ μƒˆλ‘œμš΄ νŒŒν‹°μ…˜μ„ ν• λ‹Ήλ°›κ±°λ‚˜ μž¬μ‹œμž‘ν•  λ•Œ 반영



## **6. κ³ κΈ‰ μ–΄λ“œλ―Ό μž‘μ—… πŸ”¬**

- 일반적으둜 잘 μ‚¬μš©λ˜μ§€ μ•Šμ§€λ§Œ, νŠΉμ • μƒν™©μ—μ„œλŠ” 맀우 μœ μš©ν•œ μž‘μ—…
- 특히 사고 볡ꡬ 쀑인 SREμ—κ²Œ μ€‘μš”ν•œ λ„κ΅¬λ‘œ ν™œμš© κ°€λŠ₯


## **6.1. 토픽에 νŒŒν‹°μ…˜ μΆ”κ°€ν•˜κΈ° βž•**

- ν† ν”½μ˜ νŒŒν‹°μ…˜ μˆ˜λŠ” 생성 μ‹œ κ²°μ •λ˜λ©°, 일반적으둜 λ³€κ²½λ˜μ§€ μ•ŠμŒ
- λΆ€ν•˜κ°€ νŒŒν‹°μ…˜μ˜ μ΅œλŒ€ μ²˜λ¦¬λŸ‰μ„ μ΄ˆκ³Όν•˜λŠ” 경우, νŒŒν‹°μ…˜ μΆ”κ°€κ°€ ν•„μš”

```java
Map<String, NewPartitions> newPartitions = new HashMap<>();
newPartitions.put(TOPIC_NAME, NewPartitions.increaseTo(NUM_PARTITIONS + 2));
admin.createPartitions(newPartitions).all().get();
```
- 데이터 무결성이 깨질 수 μžˆμœΌλ―€λ‘œ μ‹ μ€‘νžˆ 처리



## **6.2. ν† ν”½μ—μ„œ λ ˆμ½”λ“œ μ‚­μ œν•˜κΈ° πŸ—‘οΈ**

### **ν•„μš”μ„±**

- κ°œμΈμ •λ³΄ λ³΄ν˜Έλ²• λ“±μœΌλ‘œ 인해 νŠΉμ • 데이터 μ‚­μ œκ°€ μš”κ΅¬λ˜λŠ” 경우
- μ§€μ •λœ μ˜€ν”„μ…‹ μ΄μ „μ˜ λͺ¨λ“  λ ˆμ½”λ“œ μ‚­μ œ κ°€λŠ₯


### **μ‚¬μš© 방법**

- `deleteRecords` λ©”μ„œλ“œλ‘œ νŠΉμ • μ˜€ν”„μ…‹ μ΄μ „μ˜ λ ˆμ½”λ“œ μ‚­μ œ
- μ‚­μ œλœ λ ˆμ½”λ“œμ˜ μ΅œλŒ€ μ˜€ν”„μ…‹ 값을 λ°˜ν™˜ν•΄ μ‚­μ œ μ™„λ£Œ μ—¬λΆ€ 확인 κ°€λŠ₯

```java
admin.deleteRecords(recordsToDelete).all().get();
```


### **νŠΉμ§•**

- μ‚­μ œλœ λ ˆμ½”λ“œλŠ” μ¦‰μ‹œ μ ‘κ·Ό λΆˆκ°€ μƒνƒœλ‘œ μ „ν™˜
- μ‹€μ œ λ””μŠ€ν¬ μ‚­μ œλŠ” λΉ„λ™κΈ°λ‘œ 처리



## **6.3. 리더 μ„ μΆœ πŸ‘‘**

### **μ„ ν˜Έ 리더 μ„ μΆœ (Preferred Leader Election)**

- 각 νŒŒν‹°μ…˜μ€ 기본적으둜 **μ„ ν˜Έ 리더 λ ˆν”Œλ¦¬μΉ΄**λ₯Ό 가짐
- μΉ΄ν”„μΉ΄λŠ” μ„ ν˜Έ 리더가 리더 역할을 μˆ˜ν–‰ν•˜λŠ”μ§€ 주기적으둜 확인
- `electLeader()` λ©”μ„œλ“œλ‘œ μ„ ν˜Έ 리더λ₯Ό λ‹€μ‹œ λ¦¬λ”λ‘œ 지정 κ°€λŠ₯


### **언클린 리더 μ„ μΆœ (Unclean Leader Election)**

- 리더 λ ˆν”Œλ¦¬μΉ΄κ°€ λͺ¨λ‘ μ‚¬μš© λΆˆκ°€ν•  경우, 리더가 μ—†λŠ” μƒνƒœ λ°œμƒ κ°€λŠ₯
- 데이터 μœ μ‹€μ„ κ°μˆ˜ν•˜κ³  **비정상 λ ˆν”Œλ¦¬μΉ΄**λ₯Ό λ¦¬λ”λ‘œ 지정
- 이 과정은 λΉ„λ™κΈ°λ‘œ μ‹€ν–‰λ˜λ©°, μ‹œκ°„μ΄ μ†Œμš”λ  수 있음



## **6.4. λ ˆν”Œλ¦¬μΉ΄ μž¬ν• λ‹Ή πŸ“¦**

### **ν•„μš”μ„±**

- νŠΉμ • 브둜컀 κ³ΌλΆ€ν•˜ μ™„ν™”
- μž₯λΉ„ ꡐ체λ₯Ό μœ„ν•΄ λ ˆν”Œλ¦¬μΉ΄ 이동 λ˜λŠ” μΆ”κ°€
- 데이터 κ· ν˜•μ„ λ§žμΆ”κΈ° μœ„ν•œ 재배치


### **μ‚¬μš© 방법**

```java
admin.alterPartitionReassignments(partitionReassignments).all().get();
```

### **μ£Όμ˜μ‚¬ν•­**
- λ ˆν”Œλ¦¬μΉ΄ 이동은 **λŒ€λŸ‰μ˜ 데이터 볡제**λ₯Ό 초래
- 볡제 μž‘μ—…μœΌλ‘œ 인해 브둜컀 μ„±λŠ₯에 영ν–₯을 쀄 수 μžˆμœΌλ―€λ‘œ μ‹ μ€‘νžˆ 진행



## **7. μΉ΄ν”„μΉ΄ ν…ŒμŠ€νŠΈ πŸ§ͺ**

### **MockAdminClient**
- μ‹€μ œ 브둜컀 없이 `AdminClient`의 λ™μž‘μ„ ν…ŒμŠ€νŠΈν•  수 μžˆλŠ” 도ꡬ
- μΉ΄ν”„μΉ΄κ°€ μ œκ³΅ν•˜λŠ” λͺ©μ—… 클래슀(`MockAdminClient`)λ₯Ό ν™œμš©

0 comments on commit ed17074

Please sign in to comment.