Idempotent Producer

Kafka์˜ ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ(Idempotent Producer)๋Š” ๋ฉ”์‹œ์ง€ ์ค‘๋ณต ์ „์†ก ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ๊ธฐ๋Šฅ์œผ๋กœ, ํ”„๋กœ๋“€์„œ๊ฐ€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ณด๋‚ด๋”๋ผ๋„ Kafka๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋‚˜ ์žฌ์‹œ๋„ ๋“ฑ์œผ๋กœ ์ธํ•ด ์ค‘๋ณต๋œ ๋ฉ”์‹œ์ง€๊ฐ€ ๋ธŒ๋กœ์ปค์— ์ „์†ก๋˜๋Š” ๊ฒฝ์šฐ์—๋„, Kafka๊ฐ€ ์ด๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด ์ค‘๋ณต ์—†์ด ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์ „์†ก(Exactly Once Delivery)์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Kafka ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋ž€?

๋ฉฑ๋“ฑ์„ฑ(idempotency)์€ ๋™์ผํ•œ ์š”์ฒญ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์ˆ˜ํ–‰ํ•ด๋„ ๊ฒฐ๊ณผ๊ฐ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ํŠน์„ฑ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Kafka์—์„œ ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ํ”„๋กœ๋“€์„œ์˜ ์ค‘๋ณต ๋ฉ”์‹œ์ง€ ์ „์†ก์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๋“€์„œ๊ฐ€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ „์†กํ•  ๋•Œ, Kafka๋Š” ์ด๋ฅผ ์ค‘๋ณต ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ  ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

Kafka์—์„œ ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ๋ฉ”์‹œ์ง€ ์ „์†ก์ด ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ๋„คํŠธ์›Œํฌ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ด ์žฌ์‹œ๋„๊ฐ€ ํ•„์š”ํ•  ๋•Œ, ์ค‘๋ณต๋œ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ์˜ ์ฃผ์š” ํŠน์ง•

  1. ๋ฉ”์‹œ์ง€ ์ค‘๋ณต ์ „์†ก ๋ฐฉ์ง€: ํ”„๋กœ๋“€์„œ๊ฐ€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ „์†กํ•˜๋”๋ผ๋„ Kafka๋Š” ์ค‘๋ณต๋œ ๋ฉ”์‹œ์ง€๋ฅผ ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์žฌ์‹œ๋„ ์‹œ ์ค‘๋ณต ๋ฉ”์‹œ์ง€๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

  2. ํ”„๋กœ๋“€์„œ์˜ ์•ˆ์ •์„ฑ ํ–ฅ์ƒ: Kafka๋Š” ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ ์‚ฌ์šฉ ์‹œ ํ”„๋กœ๋“€์„œ ID(Producer ID, PID)์™€ ์‹œํ€€์Šค ๋„˜๋ฒ„๋ฅผ ํ†ตํ•ด ๊ฐ ๋ฉ”์‹œ์ง€๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€ ์ค‘๋ณต๊ณผ ์ˆœ์„œ ๋ณด์žฅ์„ ์ง€์›ํ•˜๋ฉฐ, ๋„คํŠธ์›Œํฌ ์žฅ์•  ๋˜๋Š” ๋ธŒ๋กœ์ปค ์žฅ์•  ์‹œ์—๋„ ๋ฉ”์‹œ์ง€๋ฅผ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  3. ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์ „์†ก(Exactly Once Delivery): ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์ „์†กํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ํŠนํžˆ ์žฅ์•  ๋ณต๊ตฌ ํ›„์—๋„ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ณ ์ž ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


๋™์ž‘ ์›๋ฆฌ

Kafka์˜ ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ๊ฐ ํ”„๋กœ๋“€์„œ ์ธ์Šคํ„ด์Šค์— ๊ณ ์œ ํ•œ Producer ID (PID)๋ฅผ ํ• ๋‹นํ•˜์—ฌ, ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•  ๋•Œ๋งˆ๋‹ค ์‹œํ€€์Šค ๋„˜๋ฒ„์™€ ํ•จ๊ป˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ธŒ๋กœ์ปค์— ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

  1. Producer ID: Kafka๋Š” ๊ฐ ํ”„๋กœ๋“€์„œ์— ๊ณ ์œ ํ•œ ID๋ฅผ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ID๋Š” ํ”„๋กœ๋“€์„œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ „์†กํ•˜๋Š” ๋ชจ๋“  ๋ฉ”์‹œ์ง€์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  2. ์‹œํ€€์Šค ๋„˜๋ฒ„: ํ”„๋กœ๋“€์„œ๋Š” ๊ฐ ๋ฉ”์‹œ์ง€์— ์‹œํ€€์Šค ๋„˜๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. Kafka ๋ธŒ๋กœ์ปค๋Š” ํ•ด๋‹น ์‹œํ€€์Šค ๋„˜๋ฒ„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฉ”์‹œ์ง€์˜ ์ˆœ์„œ๋ฅผ ์ถ”์ ํ•˜๊ณ , ์ค‘๋ณต๋œ ์‹œํ€€์Šค ๋„˜๋ฒ„๊ฐ€ ์ „์†ก๋  ๊ฒฝ์šฐ ์ด๋ฅผ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค.

  3. ์žฌ์ „์†ก ์‹œ ์ค‘๋ณต ์ฒ˜๋ฆฌ ๋ฐฉ์ง€:

    • ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋‚˜ ์žฌ์‹œ๋„ ์ƒํ™ฉ์—์„œ, ํ”„๋กœ๋“€์„œ๊ฐ€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Kafka๋Š” PID์™€ ์‹œํ€€์Šค ๋„˜๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ด ์ค‘๋ณต๋œ ๋ฉ”์‹œ์ง€๋ฅผ ์ž๋™์œผ๋กœ ํ•„ํ„ฐ๋งํ•˜๊ณ , ํ•œ ๋ฒˆ๋งŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

    • ์ค‘๋ณต ์ „์†ก๋œ ๋ฉ”์‹œ์ง€๋ฅผ Kafka๊ฐ€ ์ž๋™์œผ๋กœ ๋ฌด์‹œํ•˜๋ฏ€๋กœ, ์ค‘๋ณต ๋ฉ”์‹œ์ง€๋กœ ์ธํ•œ ๋ถ€์ž‘์šฉ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ ์„ค์ •

Kafka์—์„œ ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด enable.idempotence ์„ค์ •์„ true๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ค์ •์„ ํ†ตํ•ด Kafka๋Š” ํ”„๋กœ๋“€์„œ์—๊ฒŒ ๊ณ ์œ ํ•œ Producer ID๋ฅผ ํ• ๋‹นํ•˜๊ณ , ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹œ ์ค‘๋ณต ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

val props = Properties()
props[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = "localhost:9092"
props[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java.name
props[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java.name
props[ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG] = "true"  // ๋ฉฑ๋“ฑ์„ฑ ํ™œ์„ฑํ™”

val producer = KafkaProducer<String, String>(props)
val record = ProducerRecord("my-topic", "key", "value")

producer.send(record) { metadata, exception ->
    if (exception != null) {
        println("Error sending message: ${exception.message}")
    } else {
        println("Message sent successfully to partition ${metadata.partition()}, offset ${metadata.offset()}")
    }
}

producer.close()

์œ„ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด enable.idempotence๊ฐ€ true๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด Kafka ํ”„๋กœ๋“€์„œ๋Š” ๋ฉฑ๋“ฑ์„ฑ ๋ชจ๋“œ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€ ์ค‘๋ณต ๋ฐฉ์ง€์™€ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์ „์†ก(Exactly Once Delivery)์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค.


๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ์™€ ํŠธ๋žœ์žญ์…˜

Kafka์˜ ํŠธ๋žœ์žญ์…˜ ๊ธฐ๋Šฅ๊ณผ ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ์ž์ฃผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. Kafka์—์„œ ํŠธ๋žœ์žญ์…˜์€ ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋ฅผ ์‚ฌ์šฉํ•ด ์ค‘๋ณต ์ „์†ก์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์ •ํ™•ํ•œ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋ฅผ ํŠธ๋žœ์žญ์…˜ ๋ชจ๋“œ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ํŒŒํ‹ฐ์…˜์— ์ „์†ก๋˜๋Š” ๋ฉ”์‹œ์ง€๋“ค์ด ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜ ๋ชจ๋‘ ์‹คํŒจํ•˜๋„๋ก ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Exactly Once Semantics (EOS)๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ์˜ ์žฅ์ 

  1. ๋ฉ”์‹œ์ง€ ์ค‘๋ณต ๋ฐฉ์ง€: ๋„คํŠธ์›Œํฌ ์žฅ์• ๋‚˜ ์žฌ์‹œ๋„ ์ƒํ™ฉ์—์„œ ์ค‘๋ณต ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ๋ฉ”์‹œ์ง€๋ฅผ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  2. ์•ˆ์ •์„ฑ ํ–ฅ์ƒ: PID์™€ ์‹œํ€€์Šค ๋„˜๋ฒ„๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์‹œ์ง€์˜ ์ค‘๋ณต ์ „์†ก์„ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์žฅ์•  ์ƒํ™ฉ์—์„œ๋„ ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  3. ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์ „์†ก(Exactly Once Delivery): ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ๋งŒ ์ „์†กํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ Kafka์—์„œ ๋ฐ์ดํ„ฐ ์†์‹ค์ด๋‚˜ ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•  ๊ฒฝ์šฐ์— ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

  4. ํŠธ๋žœ์žญ์…˜๊ณผ ์—ฐ๊ณ„: ๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” Kafka์˜ ํŠธ๋žœ์žญ์…˜ ๊ธฐ๋Šฅ๊ณผ ๊ฒฐํ•ฉํ•ด ์—ฌ๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋˜๋Š” ํŒŒํ‹ฐ์…˜ ๊ฐ„์˜ ์›์ž์  ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ์˜ ํ•œ๊ณ„

๋ฉฑ๋“ฑ์„ฑ ํ”„๋กœ๋“€์„œ๋Š” ๋‹จ์ผ ํŒŒํ‹ฐ์…˜ ๋‚ด์—์„œ์˜ ์ค‘๋ณต ์ „์†ก์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋™์ผํ•œ ํŒŒํ‹ฐ์…˜์— ๋ฉ”์‹œ์ง€๋ฅผ ์ค‘๋ณต ์ „์†กํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐ๋Š” ๋งค์šฐ ํšจ๊ณผ์ ์ด์ง€๋งŒ, ๋‹ค๋ฅธ ํŒŒํ‹ฐ์…˜์— ๋ฉ”์‹œ์ง€๋ฅผ ์ค‘๋ณต ์ „์†กํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ณ„๋„์˜ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Last updated