BackEnd🌱/Kafka

[Kafka] ν”„λ‘œλ“€μ„œ λ©±λ“±μ„± 보μž₯ν•˜κΈ°

dkswnkk 2024. 2. 1. 22:19

κ°œμš”

멱등성은 λ™μΌν•œ μž‘μ—…μ„ μ—¬λŸ¬ 번 μˆ˜ν–‰ν•˜λ”λΌλ„ λ™μΌν•œ κ²°κ³Όκ°€ λ‚˜νƒ€λ‚˜λŠ” νŠΉμ„±μ„ μ˜λ―Έν•©λ‹ˆλ‹€. λ”°λΌμ„œ 멱등성을 μ§€λ‹Œ ν”„λ‘œλ“€μ„œλŠ” 같은 데이터λ₯Ό μ—¬λŸ¬ 번 μ „μ†‘ν•˜λ”λΌλ„ ν•΄λ‹Ή 데이터가 μΉ΄ν”„μΉ΄ ν΄λŸ¬μŠ€ν„°μ— 단 ν•œ 번만 μ €μž₯λ˜λ„λ‘ 보μž₯ν•©λ‹ˆλ‹€.

κ·Έλ ‡λ‹€λ©΄ ν”„λ‘œλ“€μ„œμ— μ–΄λ–»κ²Œ 멱등성을 μ μš©ν•˜κ³ , 이λ₯Ό 톡해 λ°μ΄ν„°μ˜ 쀑볡 μ €μž₯ 없이 μ •ν™•νžˆ ν•œ 번만 μ €μž₯λ˜λ„λ‘ 보μž₯ν•  수 μžˆμ„κΉŒμš”? 이번 κΈ€μ—μ„œλŠ” ν”„λ‘œλ“€μ„œμ— 멱등성을 보μž₯ν•˜λ„λ‘ μ μš©ν•˜λŠ” 방법에 λŒ€ν•΄ μƒμ„Έν•˜κ²Œ μ•Œμ•„λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

 

 

λ©”μ‹œμ§€ 전솑 방식

Producer와 Broker의 μ„€μ • 및 ꡬ성에 따라 Kafkaμ—μ„œλŠ” λ©”μ‹œμ§€ 전달 보μž₯ μˆ˜μ€€μ„ μ•„λž˜μ™€ 같이 μ„Έ 가지 λ°©μ‹μœΌλ‘œ κ΅¬λΆ„ν•©λ‹ˆλ‹€.

https://medium.com/@andy.bryant/processing-guarantees-in-kafka-12dd2e30be0e

  • μ΅œλŒ€ ν•œ 번 (At most once): λ©”μ‹œμ§€κ°€ ν•œ 번만 μ „μ†‘λ˜λ©°, μž¬μ „μ†‘μ€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. κ·ΈλŸ¬λ‚˜ 이둜 인해 λ©”μ‹œμ§€κ°€ μœ μ‹€λ  수 μžˆλŠ” κ°€λŠ₯성이 μžˆλ‹€.
  • μ΅œμ†Œ ν•œ 번 (At least once): λ©”μ‹œμ§€κ°€ λ°˜λ“œμ‹œ μ „μ†‘λ˜λ©°, μ΅œμ†Œν•œ ν•œ 번 이상은 전솑이 보μž₯λœλ‹€. κ·ΈλŸ¬λ‚˜ 이 κ³Όμ •μ—μ„œ λ©”μ‹œμ§€κ°€ μ€‘λ³΅μœΌλ‘œ 전솑될 수 μžˆλ‹€.
  • μ •ν™•νžˆ ν•œ 번 (Exactly once): λ©”μ‹œμ§€κ°€ μ •ν™•νžˆ ν•œ 번만 μ „μ†‘λ˜λ©°, μž¬μ „μ†‘μ€ μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€. λ”°λΌμ„œ, λ©”μ‹œμ§€κ°€ μœ μ‹€λ˜μ§€ μ•ŠλŠ” 것이 보μž₯λœλ‹€.

각각의 처리 방식에 λŒ€ν•΄ ν”„λ‘œλ“€μ„œμ˜ κ΄€μ μ—μ„œ 쑰금 더 μžμ„Ένžˆ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

 

At most once(μ΅œλŒ€ ν•œλ²ˆ)

https://www.nasa1515.com/apache-kafka-pruducer-processing-method-ack-idempotence/#at-most-once

'μ΅œλŒ€ ν•œ 번' μ „λž΅μ—μ„œλŠ” λ©”μ‹œμ§€κ°€ 단 ν•œ 번만 μ „μ†‘λ©λ‹ˆλ‹€. μ΄λŠ” λ©”μ‹œμ§€μ— λŒ€ν•œ 응닡 확인(Ack)을 받지 λͺ»ν•˜λ”라도 μž¬μ „μ†‘μ„ ν•˜μ§€ μ•ŠμŒμ„ μ˜λ―Έν•˜λ©°, 이λ₯Ό 톡해 쀑볡 전솑을 λ°©μ§€ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이 μ „λž΅μ˜ ν•œκ³„μ μœΌλ‘œλŠ” λ„€νŠΈμ›Œν¬ 문제 λ“±μœΌλ‘œ 인해 λ©”μ‹œμ§€λ₯Ό μ œλŒ€λ‘œ 받지 λͺ»ν•˜λŠ” 경우, ν•΄λ‹Ή λ©”μ‹œμ§€κ°€ μœ μ‹€λ  수 μžˆλ‹€λŠ” 점이 μžˆμŠ΅λ‹ˆλ‹€.

이 μ „λž΅μ€ λ©”μ‹œμ§€μ˜ 손싀 κ°€λŠ₯성을 κ°μˆ˜ν•˜λ©΄μ„œλ„ 쀑볡 전솑을 λ°©μ§€ν•˜λŠ” μ ‘κ·Ό 방식이며, 높은 μ²˜λ¦¬λŸ‰κ³Ό 짧은 λŒ€κΈ° μ‹œκ°„μ„ μ‰½κ²Œ 달성할 수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ λŒ€λŸ‰μ˜ 둜그 μˆ˜μ§‘μ΄λ‚˜ IoT λ“±μ˜ ν™˜κ²½μ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©λ˜λŠ” μ „λž΅μž…λ‹ˆλ‹€.

 

At least once(μ΅œμ†Œ ν•œ 번)

https://www.nasa1515.com/apache-kafka-pruducer-processing-method-ack-idempotence/#at-least-once

'μ΅œμ†Œ ν•œ 번' λ°©μ‹μ—μ„œλŠ” λ©”μ‹œμ§€μ˜ 쀑볡을 ν—ˆμš©ν•˜μ§€λ§Œ, λ©”μ‹œμ§€μ˜ 손싀은 ν—ˆμš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이 λ°©μ‹μ—μ„œ ν”„λ‘œλ“€μ„œλŠ” λΈŒλ‘œμ»€λ‘œλΆ€ν„° 응닡 확인(Ack)을 받지 λͺ»ν–ˆμ„ λ•Œ λΈŒλ‘œμ»€κ°€ λ©”μ‹œμ§€λ₯Ό μ €μž₯은 ν–ˆμ§€λ§Œ μ‘λ‹΅λ§Œ μ „μ†‘ν•˜μ§€ λͺ»ν–ˆλŠ”지, μ•„λ‹ˆλ©΄ λ©”μ‹œμ§€ μ €μž₯κ³Ό 응닡 전솑 λͺ¨λ‘ μ‹€νŒ¨ν–ˆλŠ”μ§€λ₯Ό νŒλ‹¨ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ, λΈŒλ‘œμ»€κ°€ λ©”μ‹œμ§€λ₯Ό μ €μž₯ν–ˆμœΌλ‚˜ μ‘λ‹΅λ§Œ μ „μ†‘ν•˜μ§€ λͺ»ν•œ 경우, ν”„λ‘œλ“€μ„œλŠ” 응닡을 받지 λͺ»ν–ˆκΈ° λ•Œλ¬Έμ— 같은 λ©”μ‹œμ§€λ₯Ό μž¬μ „μ†‘ν•˜κ²Œ λ©λ‹ˆλ‹€. 이둜 인해 μ€‘λ³΅λœ λ©”μ‹œμ§€κ°€ λΈŒλ‘œμ»€μ— μ €μž₯될 수 μžˆμŠ΅λ‹ˆλ‹€. 즉, 이 μ „λž΅μ€ λ©”μ‹œμ§€μ˜ 손싀을 λ°©μ§€ν•˜κΈ° μœ„ν•΄ 쀑볡 μ €μž₯을 ν—ˆμš©ν•˜λŠ” μ ‘κ·Ό λ°©μ‹μœΌλ‘œ λ°μ΄ν„°μ˜ 완전성을 μ΅œμš°μ„ μœΌλ‘œ λ‘λŠ” κ²½μš°μ— 맀우 μœ μš©ν•©λ‹ˆλ‹€.

 

Exactly once(μ •ν™•νžˆ ν•œ 번)

https://www.nasa1515.com/apache-kafka-pruducer-processing-method-ack-idempotence/#exactly-once

'μ •ν™•νžˆ ν•œ 번' 방식은 λ©±λ“±μ„±(idempotence) 원칙을 κ°€μž₯ 잘 λ”°λ₯΄λŠ” λ°©μ‹μž…λ‹ˆλ‹€. 이 λ°©μ‹μ—μ„œλŠ” λ©”μ‹œμ§€κ°€ λ”± ν•œ 번만 μ „λ‹¬λ˜λ©°, μ–΄λ– ν•œ λ©”μ‹œμ§€λ„ μ†μ‹€λ˜μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€. ν”„λ‘œλ“€μ„œ ID와 μ‹œν€€μŠ€ 번호λ₯Ό ν™œμš©ν•΄ 응닡 확인(Ack)을 λ°›κ³  λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•˜λŠ” 과정이 ν•„μˆ˜μ μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ 이런 νŠΉμ„± λ•Œλ¬Έμ— λ‹€λ₯Έ 방식에 λΉ„ν•΄ 응닡 λŒ€κΈ° μ‹œκ°„μ΄ 길어지고, μ²˜λ¦¬λŸ‰μ΄ μƒλŒ€μ μœΌλ‘œ λ–¨μ–΄μ§‘λ‹ˆλ‹€.

이 방식은 λ©”μ‹œμ§€κ°€ μœ μ‹€ 없이 μ •ν™•νžˆ ν•œ 번만 μ „μ†‘λ˜λŠ” 것을 보μž₯ν•΄μ•Ό ν•˜λŠ” μƒν™©μ—μ„œ μ‚¬μš©λ©λ‹ˆλ‹€. 

 

 

Producer Acknowledgements(acks)

Apache Kafka의 Producer Acknowledgements (acks) 섀정은 ν”„λ‘œλ“€μ„œκ°€ λΈŒλ‘œμ»€μ—κ²Œ λ©”μ‹œμ§€λ₯Ό 보낸 ν›„ λ°›λŠ” μ‘λ‹΅μ˜ μˆ˜μ€€μ„ κ²°μ •ν•©λ‹ˆλ‹€. 

ν”„λ‘œλ“€μ„œμ˜ 확인 응닡(acks) μ„€μ •μ—λŠ” 3κ°€μ§€μ˜ μ˜΅μ…˜μ΄ μ‘΄μž¬ν•©λ‹ˆλ‹€.

  • acks=0: 이 μ„€μ •μ—μ„œλŠ” ν”„λ‘œλ“€μ„œκ°€ λΈŒλ‘œμ»€μ—κ²Œ λ©”μ‹œμ§€λ₯Ό 보내고, μ–΄λ– ν•œ 응닡도 기닀리지 μ•ŠμŠ΅λ‹ˆλ‹€. μ΄λŠ” κ°€μž₯ λΉ λ₯Έ 전솑 속도λ₯Ό μ œκ³΅ν•˜μ§€λ§Œ, λ©”μ‹œμ§€κ°€ μ‹€μ œλ‘œ λΈŒλ‘œμ»€μ— λ„λ‹¬ν–ˆλŠ”μ§€ 확인할 수 μ—†μ–΄ 데이터 μ†μ‹€μ˜ μœ„ν—˜μ΄ κ°€μž₯ λ†’μŠ΅λ‹ˆλ‹€.
  • acks=1: ν”„λ‘œλ“€μ„œλŠ” 리더 λΈŒλ‘œμ»€κ°€ λ©”μ‹œμ§€λ₯Ό λ°›μ•˜μ„ λ•Œλ§Œ 응닡을 λ°›μŠ΅λ‹ˆλ‹€. 이 섀정은 λ©”μ‹œμ§€κ°€ μ΅œμ†Œ ν•œ 곳의 λΈŒλ‘œμ»€μ— μ €μž₯λ˜μ—ˆμŒμ„ 보μž₯ν•˜μ§€λ§Œ, 이 λΈŒλ‘œμ»€κ°€ μž₯μ• κ°€ λ°œμƒν•˜λ©΄ λ©”μ‹œμ§€κ°€ 손싀될 수 μžˆμŠ΅λ‹ˆλ‹€. 이 μ˜΅μ…˜μ€ 전솑 속도와 μ‹ λ’°μ„± μ‚¬μ΄μ—μ„œ κ· ν˜•μ„ μ œκ³΅ν•©λ‹ˆλ‹€.
  • acks=all λ˜λŠ” acks=-1: 이 섀정은 ν”„λ‘œλ“€μ„œκ°€ 리더 브둜컀 뿐만 μ•„λ‹ˆλΌ λͺ¨λ“  ISR(In-Sync Replicas)에 μ˜ν•΄ λ©”μ‹œμ§€κ°€ μ²˜λ¦¬λ˜μ—ˆλ‹€λŠ” 확인을 받을 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦½λ‹ˆλ‹€. μ΄λŠ” 데이터 신뒰성을 μ΅œλŒ€ν™”ν•˜μ§€λ§Œ, 전솑 속도가 느렀질 수 μžˆμŠ΅λ‹ˆλ‹€. 이 μ˜΅μ…˜μ€ λͺ¨λ“  λ ˆν”Œλ¦¬μΉ΄κ°€ λ™κΈ°ν™”λ˜μ–΄ λ°μ΄ν„°μ˜ 내ꡬ성이 κ°€μž₯ μ€‘μš”ν•œ κ²½μš°μ— μ‚¬μš©λ©λ‹ˆλ‹€.

쑰금 더 μžμ„Ένžˆ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

acks=0

https://magpienote.tistory.com/251

acks=0 섀정은 'μ΅œλŒ€ ν•œλ²ˆ(At most once)' 전솑 μ „λž΅μ— ν•΄λ‹Ήν•©λ‹ˆλ‹€.

이 섀정을 μ‚¬μš©ν•˜λŠ” 경우, ν”„λ‘œλ“€μ„œλŠ” λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•œ μˆœκ°„μ— λ©”μ‹œμ§€κ°€ μ„±κ³΅μ μœΌλ‘œ μž‘μ„±λœ κ²ƒμœΌλ‘œ κ°„μ£Όν•©λ‹ˆλ‹€. 즉, λΈŒλ‘œμ»€λ‘œλΆ€ν„°μ˜ 응닡을 기닀리지 μ•ŠμŠ΅λ‹ˆλ‹€.

이런 μƒν™©μ—μ„œ, λ§Œμ•½ λΈŒλ‘œμ»€κ°€ μ˜€ν”„λΌμΈ μƒνƒœκ°€ λ˜κ±°λ‚˜ μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ—¬ 데이터 μ“°κΈ° μž‘μ—…μ΄ μ€‘λ‹¨λ˜λ”λΌλ„ ν”„λ‘œλ“€μ„œλŠ” 이λ₯Ό μ•Œ 수 μ—†μŠ΅λ‹ˆλ‹€. 결과적으둜 이런 κ²½μš°μ—λŠ” 데이터가 손싀될 수 μžˆκΈ°μ—, acks=0 섀정은 λ©”μ‹œμ§€μ˜ μœ μ‹€μ΄ ν—ˆμš©λ˜λŠ” μƒν™©μ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©λ©λ‹ˆλ‹€.

 

acks=1

https://magpienote.tistory.com/251

acks=1 섀정은 'μ΅œμ†Œ ν•œλ²ˆ(At least once)' 전솑 μ „λž΅μ— ν•΄λ‹Ήλ˜λ©°, 이 섀정을 μ‚¬μš©ν•˜λ©΄ ν”„λ‘œλ“€μ„œλŠ” 리더 λΈŒλ‘œμ»€λ‘œλΆ€ν„° 확인 응닡을 λ°›λŠ” μ‹œμ μ— λ©”μ‹œμ§€ μ“°κΈ°κ°€ μ„±κ³΅ν–ˆλ‹€κ³  νŒλ‹¨ν•©λ‹ˆλ‹€.(μΉ΄ν”„μΉ΄ v1.0λΆ€ν„° v2.8κΉŒμ§€ default μ„€μ •μž…λ‹ˆλ‹€.)

μ£Όμ˜ν•  점은 acks=1 μ„€μ •μ—μ„œλŠ” ν”„λ‘œλ“€μ„œκ°€ 였직 리더가 데이터λ₯Ό μ €μž₯ν•œ μ‹œμ μ—λ§Œ 응닡을 λ°›κΈ° λ•Œλ¬Έμ—, 리더 μ΄μ™Έμ˜ λ ˆν”Œλ¦¬μΉ΄λ“€μ΄ 데이터λ₯Ό μ„±κ³΅μ μœΌλ‘œ λ³΅μ œν–ˆλŠ”μ§€λŠ” ν™•μΈν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 리더 λΈŒλ‘œμ»€κ°€ κ°‘μžκΈ° μ˜€ν”„λΌμΈ μƒνƒœκ°€ 되고, λ ˆν”Œλ¦¬μΉ΄λ“€μ΄ 아직 데이터λ₯Ό λ³΅μ œν•˜μ§€ λͺ»ν•œ κ²½μš°μ—λŠ” 데이터 손싀이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ§Œμ•½ λΈŒλ‘œμ»€κ°€ 확인 μš”μ²­μ„ 받지 λͺ»ν–ˆλ‹€λ©΄ ν”„λ‘œλ“€μ„œλŠ” 데이터 μ“°κΈ°λ₯Ό μ„±κ³΅μ μœΌλ‘œ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ μš”μ²­μ„ μž¬μ‹œλ„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ²°κ΅­ acks=1 섀정을 μ‚¬μš©ν•˜λ©΄ μž¬μ‹œλ„λ₯Ό 톡해 쀑볡 전솑을 ν—ˆμš©ν•˜μ§€λ§Œ, ν”„λ‘œλ“€μ„œκ°€ 리더λ₯Ό 톡해 데이터 μ“°κΈ°κ°€ μ„±κ³΅ν–ˆλŠ”μ§€ 확인할 수 있기 λ•Œλ¬Έμ— λ°μ΄ν„°μ˜ μ•ˆμ •μ„±μ€ acks=0에 λΉ„ν•΄ λ†’μ•„μ§€κ²Œ λ©λ‹ˆλ‹€.

 

acks=all or -1

https://magpienote.tistory.com/251

acks=all λ˜λŠ” acks=-1 섀정은 'μ •ν™•νžˆ ν•œ 번(Exactly once)' 전솑 μ „λž΅μ— ν•΄λ‹Ήν•©λ‹ˆλ‹€. 이 섀정을 μ‚¬μš©ν•˜λ©΄, ν”„λ‘œλ“€μ„œλŠ” 리더 브둜컀λ₯Ό ν¬ν•¨ν•œ λͺ¨λ“  λ ˆν”Œλ¦¬μΉ΄ λΈŒλ‘œμ»€λ“€λ‘œλΆ€ν„° 확인 응닡을 받은 μ‹œμ μ— λ©”μ‹œμ§€ μ“°κΈ°κ°€ μ„±κ³΅ν–ˆλ‹€κ³  νŒλ‹¨ν•©λ‹ˆλ‹€.(μΉ΄ν”„μΉ΄ v3.0λΆ€ν„° default μ„€μ •μž…λ‹ˆλ‹€.)

이 방식은 acks=1 섀정에 λΉ„ν•΄ 더 높은 데이터 μ•ˆμ •μ„±μ„ μ œκ³΅ν•˜λŠ”λ°, ν”„λ‘œλ“€μ„œλŠ” λͺ¨λ“  λ ˆν”Œλ¦¬μΉ΄ λΈŒλ‘œμ»€λ“€μ΄ 데이터λ₯Ό μ„±κ³΅μ μœΌλ‘œ μ €μž₯ν–ˆλ‹€λŠ” 확인을 λ°›κΈ° λ•Œλ¬Έμ— μ–΄λ– ν•œ λΈŒλ‘œμ»€μ— λ¬Έμ œκ°€ λ°œμƒν•˜λ”λΌλ„ 데이터 손싀 μœ„ν—˜μ΄ 크게 μ€„μ–΄λ“­λ‹ˆλ‹€. ν•˜μ§€λ§Œ λͺ¨λ“  λ ˆν”Œλ¦¬μΉ΄ λΈŒλ‘œμ»€λ“€λ‘œλΆ€ν„° 응닡을 λ°›μ•„μ•Ό ν•˜λ―€λ‘œ, λ„€νŠΈμ›Œν¬ μ§€μ—°μ΄λ‚˜ 브둜컀의 λΆ€ν•˜ λ“±μœΌλ‘œ 인해 전체 λ©”μ‹œμ§€ 전솑 μ‹œκ°„μ΄ λŠ˜μ–΄λ‚  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ•„μ§κΉŒμ§€λ„ 쀑볡 전솑이 κ°€λŠ₯ν•˜λ‹€λŠ” λ¬Έμ œκ°€ μ‘΄μž¬ν•˜λŠ”λ°, λ‹€μŒκ³Ό 같은 μƒν™©μž…λ‹ˆλ‹€.

https://medium.com/@shesh.soft/kafka-idempotent-producer-and-consumer-25c52402ceb9

μœ„ μ΄λ―Έμ§€λŠ” ν”„λ‘œλ“€μ„œκ°€ λΈŒλ‘œμ»€μ—κ²Œ λ©”μ‹œμ§€λ₯Ό 보내고, λΈŒλ‘œμ»€κ°€ ν”„λ‘œλ“€μ„œμ—κ²Œ ackλ₯Ό λ³΄λ‚΄λŠ” κ³Όμ •μž…λ‹ˆλ‹€. ν˜„μž¬κΉŒμ§€λŠ” λͺ¨λ‘ μ •μƒμ μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ ν”„λ‘œλ“€μ„œκ°€ λΈŒλ‘œμ»€μ—κ²Œ 보낸 λ©”μ‹œμ§€μ— λŒ€ν•œ 응닡이 λ„€νŠΈμ›Œν¬ 지연 λ“±μ˜ 이유둜 ν”„λ‘œλ“€μ„œμ—κ²Œ λŒμ•„μ˜€μ§€ μ•ŠλŠ” 상황을 κ°€μ •ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€. 

https://medium.com/@shesh.soft/kafka-idempotent-producer-and-consumer-25c52402ceb9

μœ„ μƒν™©μ—μ„œλŠ” 'y'λΌλŠ” λ©”μ‹œμ§€λ₯Ό  ν”„λ‘œλ“€μ„œκ°€ λΈŒλ‘œμ»€μ—κ²Œ λ³΄λƒˆλŠ”λ°, 이 λ©”μ‹œμ§€λŠ” λΈŒλ‘œμ»€μ— μ˜ν•΄ μ •μƒμ μœΌλ‘œ νŒŒν‹°μ…˜μ— μ €μž₯λ˜μ—ˆμ§€λ§Œ ackκ°€ ν”„λ‘œλ“€μ„œμ—κ²Œ λ„μ°©ν•˜μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 경우 ν”„λ‘œλ“€μ„œλŠ” 였λ₯˜λ‘œ νŒλ‹¨ν•˜κ³  λ™μΌν•œ λ©”μ‹œμ§€μΈ 'y'λ₯Ό λ‹€μ‹œ λ³΄λ‚΄κ²Œ λ©λ‹ˆλ‹€. κ·Έ κ²°κ³Ό λΈŒλ‘œμ»€μ—λŠ” 'y'λ©”μ‹œμ§€κ°€ μ€‘λ³΅μœΌλ‘œ μ €μž₯λ©λ‹ˆλ‹€.

λ”°λΌμ„œ λ©±λ“±μ„± μžˆλŠ” 'μ •ν™•νžˆ ν•œ 번(Exactly once)'을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄μ„œλŠ” acks μ„€μ •λΏλ§Œ μ•„λ‹ˆλΌ idempotent μ„€μ • 그리고 Brocker의 max.in.flight.requests.per.connection μ„€μ •, min.insync.replicas μ„€μ •, retries도 같이 λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. 이 뢀뢄은 μ•„λž˜μ—μ„œ μ’€ 더 μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

 

λ©±λ“±μ„± 보μž₯ μ„€μ •

λ©±λ“±μ„±(idempotence)μ΄λž€ ν”„λ‘œλ“€μ„œκ°€ λ ˆμ½”λ“œλ₯Ό μ „μ†‘ν–ˆμ§€λ§Œ, λ„€νŠΈμ›Œν¬ 이슈 λ“±μœΌλ‘œ 인해 ackλ₯Ό 받지 λͺ»ν•œ κ²½μš°μ—λ„ 쀑볡 λ©”μ‹œμ§€μ˜ 전달 및 μ €μž₯을 λ°©μ§€ν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ μΉ΄ν”„μΉ΄λŠ” ν”„λ‘œλ“€μ„œ ID(PID)와 μ‹œν€€μŠ€ 번호λ₯Ό 기반으둜 λ©”μ‹œμ§€λ₯Ό μΆ”μ ν•˜κ³ , λ™μΌν•œ 컀밋에 λŒ€ν•΄ 쀑볡 처리λ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€.

멱등성을 보μž₯ν•˜κΈ° μœ„ν•œ 섀정은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • acks: ν”„λ‘œλ“€μ„œκ°€ μš”μ²­μ„ 보내고 리더가 λ ˆν”Œλ¦¬μΉ΄μ˜ μˆ˜μ‹ μ„ 확인해야 ν•˜λŠ” 개수λ₯Ό κ²°μ •. 'all' λ˜λŠ” '-1'둜 μ„€μ •ν•œλ‹€.
  • enable.idempotence: ν”„λ‘œλ“€μ„œκ°€ λ ˆμ½”λ“œ μ“°κΈ° μž‘μ—…μ„ 단 ν•œ 번만 ν—ˆμš©ν•  것인지λ₯Ό κ²°μ •. 'true'둜 μ„€μ •ν•΄μ•Ό 멱등성을 보μž₯ν•œλ‹€.
  • max.in.flight.requests.per.connection: ν•œ λ²ˆμ— λͺ‡ 개의 μš”μ²­μ„ 전솑할 것인지λ₯Ό κ²°μ •. 이 값은 1 이상 5 μ΄ν•˜λ‘œ μ„€μ •ν•΄μ•Ό ν•œλ‹€.
  • retries: λ©”μ‹œμ§€λ₯Ό μ „μ†‘ν•˜κΈ° μœ„ν•΄ μž¬μ‹œλ„λ˜λŠ” 횟수λ₯Ό κ²°μ •. 이 값은 0 μ΄μƒμœΌλ‘œ μ„€μ •ν•΄μ•Ό ν•œλ‹€.
  • min.insync.replicas: λ™κΈ°ν™”ν•˜λŠ” λ ˆν”Œλ¦¬μΉ΄μ˜ 수λ₯Ό κ²°μ •. acks=all일 경우 보톡 2둜 μ„€μ •ν•œλ‹€(브둜컀 섀정이닀).

μœ„μ˜ λͺ¨λ“  섀정값을 μ μš©ν•˜μ§€ μ•ŠμœΌλ©΄ ConfigException이 λ°œμƒν•˜λ―€λ‘œ μ£Όμ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€.(섀정값을 ν™•μΈν•˜λŠ” λΆ€λΆ„)

 

enable.idempotence

μΉ΄ν”„μΉ΄ v3.0 λΆ€ν„°λŠ” acks=all(-1)κ³Ό enable.idempotence=trueκ°€ default둜 μ μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€ κ·ΈλŸ¬λ‚˜ v2.8 μ΄ν•˜ λ²„μ „μ—μ„œλŠ” acks=-1κ³Ό enable.idempotence=falseκ°€ default μ„€μ •μ΄λ―€λ‘œ, μ΄λŸ¬ν•œ λ²„μ „μ—μ„œλŠ” λ³„λ„λ‘œ 섀정을 λ³€κ²½ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€.

https://medium.com/@shesh.soft/kafka-idempotent-producer-and-consumer-25c52402ceb9

enable.idempotence=true둜 μ„€μ •ν•˜λ©΄, μœ„ μ΄λ―Έμ§€μ²˜λŸΌ 각 ν”„λ‘œλ“€μ„œμ—λŠ” κ³ μœ ν•œ ν”„λ‘œλ“€μ„œ ID(PID)κ°€ ν• λ‹Ήλ©λ‹ˆλ‹€. ν”„λ‘œλ“€μ„œλŠ” λ©”μ‹œμ§€λ₯Ό λΈŒλ‘œμ»€μ—κ²Œ 보낼 λ•Œλ§ˆλ‹€ 이 PIDλ₯Ό ν¬ν•¨ν•˜λ©°, 각 λ©”μ‹œμ§€λŠ” 순차적으둜 μ¦κ°€ν•˜λŠ” μ‹œν€€μŠ€ 번호λ₯Ό λ°›μŠ΅λ‹ˆλ‹€. ν”„λ‘œλ“€μ„œκ°€ λ©”μ‹œμ§€λ₯Ό λ³΄λ‚΄λŠ” 각 ν† ν”½ νŒŒν‹°μ…˜λ§ˆλ‹€ λ³„λ„μ˜ μ‹œν€€μŠ€κ°€ μœ μ§€λ˜κ³ , λΈŒλ‘œμ»€λŠ” νŒŒν‹°μ…˜λ³„λ‘œ μ„±κ³΅μ μœΌλ‘œ 처리된 PID-μ‹œν€€μŠ€ 번호 μ‘°ν•© 쀑 κ°€μž₯ 큰 값을 μΆ”μ ν•©λ‹ˆλ‹€.

https://medium.com/@shesh.soft/kafka-idempotent-producer-and-consumer-25c52402ceb9

μœ„ 이미지λ₯Ό 보면 λΈŒλ‘œμ»€λŠ” ν”„λ‘œλ“€μ„œμ˜ μš”μ²­μ΄ PID/ν† ν”½νŒŒν‹°μ…˜ μŒμ—μ„œ λ§ˆμ§€λ§‰μœΌλ‘œ μ»€λ°‹λœ λ©”μ‹œμ§€λ³΄λ‹€ μ‹œν€€μŠ€ λ²ˆν˜Έκ°€ μ •ν™•νžˆ 1만큼 크지 μ•Šμ€ 경우, ν”„λ‘œλ“€μ„œμ˜ μš”μ²­μ„ κ±°λΆ€ν•˜λŠ” 것을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 ν”„λ‘œλ“€μ„œλŠ” μ‹€νŒ¨μ— λ”°λ₯Έ μš”μ²­ μž¬μ‹œλ„λ₯Ό ν•  수 μžˆμ§€λ§Œ, λͺ¨λ“  λ©”μ‹œμ§€λŠ” λ‘œκ·Έμ— μ •ν™•νžˆ ν•œ 번만 κΈ°λ‘λ©λ‹ˆλ‹€. ν•˜μ§€λ§Œ μƒˆλ‘œμš΄ ν”„λ‘œλ“€μ„œ μΈμŠ€ν„΄μŠ€μ—λŠ” μƒˆλ‘œμš΄ 고유 PIDκ°€ ν• λ‹Ήλ˜λ―€λ‘œ, 단일 ν”„λ‘œλ“€μ„œ μ„Έμ…˜ λ‚΄μ—μ„œλ§Œ 멱등성을 보μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

max.in.flight.requests.per.connection

μΉ΄ν”„μΉ΄μ—μ„œ max.in.flight.requests.per.connection 섀정은 λ©±λ“±μ„±(idempotence)을 보μž₯ν•˜λŠ” 데 μ€‘μš”ν•œ 역할을 ν•©λ‹ˆλ‹€. 이 섀정은 ν•œ 번의 μ—°κ²°μ—μ„œ λ™μ‹œμ— μ²˜λ¦¬ν•  수 μžˆλŠ” μ΅œλŒ€ μš”μ²­ 수λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. μΉ΄ν”„μΉ΄ v0.11 버전 μ΄μƒμ—μ„œλŠ” 멱등성이 ν™œμ„±ν™”λœ ν”„λ‘œλ“€μ„œμ˜ 경우, 이 값을 5 μ΄ν•˜λ‘œ μ„€μ •ν•˜λŠ” 것이 ꢌμž₯λ˜λŠ”λ° κ·Έ μ΄μœ λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • λ©”μ‹œμ§€ μˆœμ„œ 보μž₯: μΉ΄ν”„μΉ΄μ˜ λ©±λ“± ν”„λ‘œλ“€μ„œλŠ” 같은 νŒŒν‹°μ…˜μ— λŒ€ν•΄ λ©”μ‹œμ§€μ˜ μˆœμ„œλ₯Ό 보μž₯ν•΄μ•Ό ν•©λ‹ˆλ‹€. max.in.flight.requests.per.connection 값이 5 μ΄ν•˜μΌ λ•Œ, ν”„λ‘œλ“€μ„œλŠ” ν•œ λ©”μ‹œμ§€κ°€ μ‹€νŒ¨ν•˜λ©΄ κ·Έ ν›„μ˜ λ©”μ‹œμ§€λ“€μ€ μ„œλ²„μ— μ „μ†‘λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ™μž‘μ€ λ©”μ‹œμ§€μ˜ μˆœμ„œκ°€ λ³€κ²½λ˜μ§€ μ•Šλ„λ‘ 보μž₯ν•˜λŠ” 데 μ€‘μš”ν•©λ‹ˆλ‹€. λ§Œμ•½ 이 값이 5보닀 크닀면, ν”„λ‘œλ“€μ„œλŠ” μž¬μ‹œλ„ν•˜λŠ” λ™μ•ˆ λ‹€λ₯Έ λ©”μ‹œμ§€λ“€μ„ 전솑할 수 μžˆμ–΄, λ©”μ‹œμ§€ μˆœμ„œκ°€ λ’€λ°”λ€” μœ„ν—˜μ΄ μžˆμŠ΅λ‹ˆλ‹€.
  • 쀑볡 λ©”μ‹œμ§€ 방지: λ©±λ“±μ„± ν”„λ‘œλ“€μ„œλŠ” λ©”μ‹œμ§€μ˜ 쀑볡 전솑을 λ°©μ§€ν•©λ‹ˆλ‹€. max.in.flight.requests.per.connection 값이 λ„ˆλ¬΄ 크면 λ„€νŠΈμ›Œν¬ 지연 λ“±μ˜ 문제둜 인해 쀑볡 λ©”μ‹œμ§€κ°€ λ°œμƒν•  κ°€λŠ₯성이 μ¦κ°€ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 이 값을 5 μ΄ν•˜λ‘œ μ„€μ •ν•˜μ—¬ μ΄λŸ¬ν•œ 문제λ₯Ό 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

https://magpienote.tistory.com/251

 

 

μ½”λ“œ

μ‹€μ œ μ½”λ“œμ—μ„œλŠ” λ‹€μŒκ³Ό 같이 ν”„λ‘œλ“€μ„œμ˜ 속성을 μ„€μ •ν•˜μ—¬ λ©±λ“±μ„± κΈ°λŠ₯을 ν™œμ„±ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Properties properties = new Properties();

// λ©±λ“±μ„± ν™œμ„±ν™” μ„€μ •
properties.setProperty(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");

enable.idempotenceλ₯Ό true둜 μ„€μ •ν•˜λ©΄ 데이터가 μ •ν™•νžˆ ν•œ 번만 μ μž¬λ˜λ„λ‘ ν•˜κΈ° μœ„ν•΄ ν”„λ‘œλ“€μ„œμ˜ λͺ‡ 가지 μ˜΅μ…˜μ΄ μžλ™μœΌλ‘œ μ„€μ •λ©λ‹ˆλ‹€. λŒ€ν‘œμ μœΌλ‘œ 데이터 μž¬μ „μ†‘ 횟수λ₯Ό κ²°μ •ν•˜λŠ” retriesλŠ” 기본값인 Integer.MAX_VALUE둜 μ„€μ •λ˜κ³ , acks μ˜΅μ…˜μ€ all둜 μ„€μ •λ©λ‹ˆλ‹€.

 

 

λ©±λ“±μ„± ν”„λ‘œλ“€μ„œμ˜ ν•œκ³„

λ©±λ“±μ„± ν”„λ‘œλ“€μ„œλŠ” λ™μΌν•œ μ„Έμ…˜ λ‚΄μ—μ„œλ§Œ μ •ν™•νžˆ ν•œ 번의 전달을 보μž₯ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œ 'λ™μΌν•œ μ„Έμ…˜'μ΄λž€, PID(Producer ID)의 생λͺ…μ£ΌκΈ°λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. λ§Œμ•½ λ©±λ“±μ„± ν”„λ‘œλ“€μ„œλ‘œ μž‘λ™ν•˜λŠ” ν”„λ‘œλ“€μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— λ¬Έμ œκ°€ λ°œμƒν•΄ μ’…λ£Œλ˜κ³  λ‹€μ‹œ μ‹œμž‘ν•˜λ©΄ PIDκ°€ λ³€κ²½λ©λ‹ˆλ‹€.

λ™μΌν•œ 데이터λ₯Ό μ „μ†‘ν•˜λ”λΌλ„, PIDκ°€ λ°”λ€Œλ©΄ λΈŒλ‘œμ»€λŠ” λ‹€λ₯Έ ν”„λ‘œλ“€μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ λ‹€λ₯Έ 데이터λ₯Ό λ³΄λƒˆλ‹€κ³  νŒλ‹¨ν•©λ‹ˆλ‹€. λ”°λΌμ„œ λ©±λ“±μ„± ν”„λ‘œλ“€μ„œλŠ” μž₯μ• κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ” μƒν™©μ—μ„œλ§Œ 데이터λ₯Ό μ •ν™•νžˆ ν•œ 번 μ μž¬ν•˜λŠ” 것을 보μž₯ν•œλ‹€λŠ” 점을 λͺ…심해야 ν•©λ‹ˆλ‹€. 

 

 

λ©±λ“±μ„± ν”„λ‘œλ“€μ„œ μ‚¬μš© μ‹œ 였λ₯˜ 확인

λ©±λ“±μ„± ν”„λ‘œλ“€μ„œλŠ” μ‹œν€€μŠ€ 번호λ₯Ό 0λΆ€ν„° μ‹œμž‘ν•˜μ—¬, 데이터λ₯Ό 전솑할 λ•Œλ§ˆλ‹€ 이 번호λ₯Ό 1μ”© μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€. λΈŒλ‘œμ»€λŠ” λ©±λ“±μ„± ν”„λ‘œλ“€μ„œκ°€ μ „μ†‘ν•œ λ°μ΄ν„°μ˜ PID와 μ‹œν€€μŠ€ 번호λ₯Ό ν™•μΈν•˜λŠ” κ³Όμ •μ—μ„œ, μ‹œν€€μŠ€ λ²ˆν˜Έκ°€ 일관성을 μœ μ§€ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λŠ” OutOfOrderSequenceException을 λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

이 μ˜ˆμ™ΈλŠ” λΈŒλ‘œμ»€κ°€ μ˜ˆμƒν–ˆλ˜ μ‹œν€€μŠ€ λ²ˆν˜Έμ™€ μ‹€μ œλ‘œ 받은 λ°μ΄ν„°μ˜ μ‹œν€€μŠ€ λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•Šμ„ λ•Œ λ°œμƒν•©λ‹ˆλ‹€. OutOfOrderSequenceException이 λ°œμƒν•˜λ©΄, μ‹œν€€μŠ€ 번호의 μˆœμ„œκ°€ λ’€λ°”λ€” 수 μžˆμœΌλ―€λ‘œ, μˆœμ„œκ°€ μ€‘μš”ν•œ 데이터λ₯Ό μ „μ†‘ν•˜λŠ” ν”„λ‘œλ“€μ„œλŠ” 이 μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ 적절히 λŒ€μ‘ν•  수 μžˆλŠ” λ°©μ•ˆμ„ κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€.

 

 

μ°Έκ³