Debezium ์†Œ๊ฐœ - Apache Kafka์šฉ CDC

Debezium ์†Œ๊ฐœ - Apache Kafka์šฉ CDC

์ €๋Š” ์—…๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด์„œ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ  ์†”๋ฃจ์…˜/์†Œํ”„ํŠธ์›จ์–ด ์ œํ’ˆ์„ ์ž์ฃผ ์ ‘ํ•˜๋Š”๋ฐ, ์ด์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ๋Ÿฌ์‹œ์•„์–ด ์ธํ„ฐ๋„ท์—์„œ๋Š” ๋‹ค์†Œ ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” Debezium์„ ์‚ฌ์šฉํ•˜์—ฌ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋‘ DBMS(PostgreSQL ๋ฐ MongoDB)์—์„œ Kafka ํด๋Ÿฌ์Šคํ„ฐ๋กœ CDC ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•˜๋„๋ก ๊ตฌ์„ฑํ•ด์•ผ ํ–ˆ๋˜ ์ตœ๊ทผ ์‹ค์Šต์˜ ์˜ˆ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ๋Ÿฌํ•œ ๊ณต๋ฐฑ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฉ”์šฐ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜ํ–‰๋œ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ์ด ๋ฆฌ๋ทฐ ๊ธฐ์‚ฌ๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ Debezium๊ณผ CDC๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

๋ฐ๋ฒ  ์ง€์›€ โ€” CDC ์†Œํ”„ํŠธ์›จ์–ด ์นดํ…Œ๊ณ ๋ฆฌ ๋Œ€ํ‘œ(๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์บก์ฒ˜), ๋” ์ •ํ™•ํ•˜๊ฒŒ๋Š” Apache Kafka Connect ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ˜ธํ™˜๋˜๋Š” ๋‹ค์–‘ํ•œ DBMS๋ฅผ ์œ„ํ•œ ์ปค๋„ฅํ„ฐ ์„ธํŠธ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ, Apache License v2.0์— ๋”ฐ๋ผ ๋ผ์ด์„ผ์Šค๊ฐ€ ๋ถ€์—ฌ๋˜๊ณ  Red Hat์˜ ํ›„์›์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. 2016๋…„๋ถ€ํ„ฐ ๊ฐœ๋ฐœ์ด ์ง„ํ–‰ ์ค‘์ด๋ฉฐ ํ˜„์žฌ MySQL, PostgreSQL, MongoDB, SQL Server์™€ ๊ฐ™์€ DBMS์— ๋Œ€ํ•œ ๊ณต์‹ ์ง€์›์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. Cassandra ๋ฐ Oracle์šฉ ์ปค๋„ฅํ„ฐ๋„ ์žˆ์ง€๋งŒ ํ˜„์žฌ๋Š” "์ดˆ๊ธฐ ์•ก์„ธ์Šค" ์ƒํƒœ์— ์žˆ์œผ๋ฉฐ ์ƒˆ ๋ฆด๋ฆฌ์Šค๋Š” ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

CDC๋ฅผ ๊ธฐ์กด ์ ‘๊ทผ ๋ฐฉ์‹(์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด DBMS์—์„œ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ๊ฒฝ์šฐ)๊ณผ ๋น„๊ตํ•˜๋ฉด ์ฃผ์š” ์ด์ ์€ ๋‚ฎ์€ ๋Œ€๊ธฐ ์‹œ๊ฐ„, ๋†’์€ ์•ˆ์ •์„ฑ ๋ฐ ๊ฐ€์šฉ์„ฑ์œผ๋กœ ํ–‰ ์ˆ˜์ค€์—์„œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์ŠคํŠธ๋ฆฌ๋ฐ์„ ๊ตฌํ˜„ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ๋‘ ๊ฐ€์ง€ ์‚ฌํ•ญ์€ Kafka ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ CDC ์ด๋ฒคํŠธ์šฉ ์ €์žฅ์†Œ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋˜ ๋‹ค๋ฅธ ์žฅ์ ์€ ๋‹จ์ผ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฒคํŠธ๋ฅผ ์ €์žฅํ•˜๋ฏ€๋กœ ์ตœ์ข… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์„œ๋กœ ๋‹ค๋ฅธ DBMS๋ฅผ ์šด์˜ํ•˜๋Š” ๋ฐ ๋”ฐ๋ฅธ ๋ฏธ๋ฌ˜ํ•œ ์ฐจ์ด์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ˆ˜ํ‰์œผ๋กœ ํ™•์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์‹œ์— ๋ฐ์ดํ„ฐ๋ฅผ DBMS์—์„œ ์ง์ ‘ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ณ  Kafka ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ ๋ฐ์ดํ„ฐ ์†Œ์Šค์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์ด ์ตœ์†Œํ™”๋ฉ๋‹ˆ๋‹ค.

Debezium ์•„ํ‚คํ…์ฒ˜ ์ •๋ณด

Debezium์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ ๊ณ„ํš์œผ๋กœ ๊ท€๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

DBMS(๋ฐ์ดํ„ฐ ์†Œ์Šค) โ†’ Kafka Connect์˜ ์ปค๋„ฅํ„ฐ โ†’ Apache Kafka โ†’ ์†Œ๋น„์ž

์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ์€ ํ”„๋กœ์ ํŠธ ์›น์‚ฌ์ดํŠธ์˜ ๋‹ค์ด์–ด๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.

Debezium ์†Œ๊ฐœ - Apache Kafka์šฉ CDC

ํ•˜์ง€๋งŒ ์ €๋Š” ์ด ๋ฐฉ์‹์ด ๋ณ„๋กœ ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์‹ฑํฌ ์ปค๋„ฅํ„ฐ๋งŒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ๋Š” ์ƒํ™ฉ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ๋ ˆ์ดํฌ๋ฅผ ์ฑ„์šฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์˜ ๋งˆ์ง€๋ง‰ ๋งํฌ) ์ด๊ฒƒ์ด Debezium์„ ์‚ฌ์šฉํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค. Apache Kafka๋กœ ์ „์†ก๋œ ์ด๋ฒคํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

  • ์บ์‹œ์—์„œ ๊ด€๋ จ ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  • ์•Œ๋ฆผ ๋ณด๋‚ด๊ธฐ;
  • ๊ฒ€์ƒ‰ ์ƒ‰์ธ ์—…๋ฐ์ดํŠธ;
  • ์ผ์ข…์˜ ๊ฐ์‚ฌ ๋กœ๊ทธ;
  • ...

Java ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์žˆ๊ณ  Kafka ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”/๊ฐ€๋Šฅ์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ์„ ํ†ตํ•ด ์ž‘์—…ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์žฅ ์ปค๋„ฅํ„ฐ. ๋ถ„๋ช…ํ•œ ์ด์ ์€ ์ถ”๊ฐ€ ์ธํ”„๋ผ(์ปค๋„ฅํ„ฐ ๋ฐ Kafka ํ˜•ํƒœ)๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์†”๋ฃจ์…˜์€ ๋ฒ„์ „ 1.1๋ถ€ํ„ฐ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ๋” ์ด์ƒ ์‚ฌ์šฉ์ด ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ด์— ๋Œ€ํ•œ ์ง€์›์€ ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์—์„œ ์ œ๊ฑฐ๋  ์ˆ˜ ์žˆ์Œ).

์ด ๋ฌธ์„œ์—์„œ๋Š” ๋‚ด๊ฒฐํ•จ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ์ œ๊ณตํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ปค๋„ฅํ„ฐ ๊ตฌ์„ฑ

๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฐ€์น˜์ธ ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”์ ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  1. ๋ฒ„์ „ 5.7๋ถ€ํ„ฐ MySQL, PostgreSQL 9.6+, MongoDB 3.2+(์ „์ฒด ๋ชฉ๋ก);
  2. ์•„ํŒŒ์น˜ ์นดํ”„์นด ํด๋Ÿฌ์Šคํ„ฐ;
  3. Kafka Connect ์ธ์Šคํ„ด์Šค(๋ฒ„์ „ 1.x, 2.x)
  4. Debezium ์ปค๋„ฅํ„ฐ๋ฅผ ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ ๋‘ ์ ์— ๋Œ€ํ•ด ์ž‘์—…ํ•˜์‹ญ์‹œ์˜ค. DBMS ๋ฐ Apache Kafka์˜ ์„ค์น˜ ํ”„๋กœ์„ธ์Šค๋Š” ์ด ๊ธฐ์‚ฌ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒŒ๋“œ๋ฐ•์Šค์— ๋ชจ๋“  ๊ฒƒ์„ ๋ฐฐํฌํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ์˜ˆ์ œ๊ฐ€ ํฌํ•จ๋œ ๊ณต์‹ ์ €์žฅ์†Œ์— ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ๋„์ปค ์ž‘์„ฑ.yaml.

๋งˆ์ง€๋ง‰ ๋‘ ๊ฐ€์ง€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

0. ์นดํ”„์นด ์ปค๋„ฅํŠธ

์ด ๋ฌธ์„œ์™€ ์ถ”๊ฐ€ ๋ฌธ์„œ์—์„œ๋Š” ๋ชจ๋“  ๊ตฌ์„ฑ ์˜ˆ์ œ๊ฐ€ Debezium ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐฐํฌํ•œ Docker ์ด๋ฏธ์ง€์˜ ๋งฅ๋ฝ์—์„œ ๋…ผ์˜๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ ํŒŒ์ผ(์ปค๋„ฅํ„ฐ)์ด ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Kafka Connect ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Confluent์—์„œ Kafka Connect๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ํ•„์š”ํ•œ ์ปค๋„ฅํ„ฐ์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋‹ค์Œ์— ์ง€์ •๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋…๋ฆฝ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. plugin.path ๋˜๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ์„ค์ • CLASSPATH. Kafka Connect ์ž‘์—…์ž ๋ฐ ์ปค๋„ฅํ„ฐ์— ๋Œ€ํ•œ ์„ค์ •์€ ์ž‘์—…์ž ์‹œ์ž‘ ๋ช…๋ น์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ตฌ์„ฑ ํŒŒ์ผ์„ ํ†ตํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”. ์„ ์  ์„œ๋ฅ˜ ๋น„์น˜.

์ปค๋„ฅํ„ฐ ๋ฒ„์ „์—์„œ Debeizum์„ ์„ค์ •ํ•˜๋Š” ์ „์ฒด ํ”„๋กœ์„ธ์Šค๋Š” ๋‘ ๋‹จ๊ณ„๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๊ฐ๊ฐ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. Kafka Connect ํ”„๋ ˆ์ž„์›Œํฌ ์„ค์ •

๋ฐ์ดํ„ฐ๋ฅผ Apache Kafka ํด๋Ÿฌ์Šคํ„ฐ๋กœ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์ • ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ Kafka Connect ํ”„๋ ˆ์ž„์›Œํฌ์— ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

  • ํด๋Ÿฌ์Šคํ„ฐ ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜
  • ์ปค๋„ฅํ„ฐ ์ž์ฒด์˜ ๊ตฌ์„ฑ์ด ์ง์ ‘ ์ €์žฅ๋  ์ฃผ์ œ์˜ ์ด๋ฆ„,
  • ์ปค๋„ฅํ„ฐ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ๊ทธ๋ฃน์˜ ์ด๋ฆ„(๋ถ„์‚ฐ ๋ชจ๋“œ๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ)

ํ”„๋กœ์ ํŠธ์˜ ๊ณต์‹ Docker ์ด๋ฏธ์ง€๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์„ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์‹ญ์‹œ์˜ค.

docker pull debezium/connect

์ปค๋„ฅํ„ฐ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ธํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • BOOTSTRAP_SERVERS=kafka-1:9092,kafka-2:9092,kafka-3:9092 โ€” ์ „์ฒด ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์„ฑ์› ๋ชฉ๋ก์„ ์–ป๊ธฐ ์œ„ํ•œ Kafka ํด๋Ÿฌ์Šคํ„ฐ ์„œ๋ฒ„์˜ ์ดˆ๊ธฐ ๋ชฉ๋ก
  • OFFSET_STORAGE_TOPIC=connector-offsets - ์ปค๋„ฅํ„ฐ๊ฐ€ ํ˜„์žฌ ์œ„์น˜ํ•œ ์œ„์น˜๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์ œ;
  • CONNECT_STATUS_STORAGE_TOPIC=connector-status โ€” ์ปค๋„ฅํ„ฐ ๋ฐ ํ•ด๋‹น ์ž‘์—…์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.
  • CONFIG_STORAGE_TOPIC=connector-config โ€” ์ปค๋„ฅํ„ฐ ๊ตฌ์„ฑ ๋ฐ์ดํ„ฐ ๋ฐ ํ•ด๋‹น ์ž‘์—…์„ ์ €์žฅํ•˜๋Š” ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.
  • GROUP_ID=1 โ€” ์ปค๋„ฅํ„ฐ ์ž‘์—…์ด ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์ž ๊ทธ๋ฃน์˜ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค. ๋ถ„์‚ฐ ์‚ฌ์šฉ์‹œ ํ•„์š”ํ•œ (๋ถ„์‚ฐ) ๋ชจ๋“œ.

๋‹ค์Œ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

docker run 
  -e BOOTSTRAP_SERVERS='kafka-1:9092,kafka-2:9092,kafka-3:9092' 
  -e GROUP_ID=1 
  -e CONFIG_STORAGE_TOPIC=my_connect_configs 
  -e OFFSET_STORAGE_TOPIC=my_connect_offsets 
  -e STATUS_STORAGE_TOPIC=my_connect_statuses  debezium/connect:1.2

Avro์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์‚ฌํ•ญ

๊ธฐ๋ณธ์ ์œผ๋กœ Debezium์€ JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ƒŒ๋“œ๋ฐ•์Šค ๋ฐ ์†Œ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ์—๋Š” ํ—ˆ์šฉ๋˜์ง€๋งŒ ๋กœ๋“œ๊ฐ€ ๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. JSON ๋ณ€ํ™˜๊ธฐ์˜ ๋Œ€์•ˆ์€ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ง๋ ฌํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„ ๋ธŒ๋กœ Apache Kafka์˜ I/O ํ•˜์œ„ ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ๋กœ๋“œ๋ฅผ ์ค„์ด๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

Avro๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ณ„๋„์˜ ๋ฐฐํฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ‚ค๋งˆ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ (๋‹ค์ด์–ด๊ทธ๋žจ ์ €์žฅ์šฉ). ๋ณ€ํ™˜๊ธฐ์˜ ๋ณ€์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

name: CONNECT_VALUE_CONVERTER_SCHEMA_REGISTRY_URL
value: http://kafka-registry-01:8081/
name: CONNECT_KEY_CONVERTER_SCHEMA_REGISTRY_URL
value: http://kafka-registry-01:8081/
name: VALUE_CONVERTER   
value: io.confluent.connect.avro.AvroConverter

Avro ์‚ฌ์šฉ ๋ฐ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ์„ค์ •์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ๋ฌธ์„œ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚ฉ๋‹ˆ๋‹ค. ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด JSON์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

2. ์ปค๋„ฅํ„ฐ ์ž์ฒด ๊ตฌ์„ฑ

์ด์ œ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์ปค๋„ฅํ„ฐ ์ž์ฒด์˜ ๊ตฌ์„ฑ์œผ๋กœ ์ง์ ‘ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‘ DBMS์ธ PostgreSQL๊ณผ MongoDB์— ๋Œ€ํ•œ ์ปค๋„ฅํ„ฐ์˜ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ์ œ๊ฐ€ ๊ฒฝํ—˜์ด ์žˆ๊ณ  ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค(์ž‘์ง€๋งŒ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!).

๊ตฌ์„ฑ์€ JSON ํ‘œ๊ธฐ๋ฒ•์œผ๋กœ ์„ค๋ช…๋˜๋ฉฐ POST ์š”์ฒญ์„ ์‚ฌ์šฉํ•˜์—ฌ Kafka Connect์— ์—…๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.

2.1. ํฌ์ŠคํŠธ๊ทธ๋ ˆSQL

PostgreSQL์šฉ ์ปค๋„ฅํ„ฐ ๊ตฌ์„ฑ ์˜ˆ:

{
  "name": "pg-connector",
  "config": {
    "connector.class": "io.debezium.connector.postgresql.PostgresConnector",
    "plugin.name": "pgoutput",
    "database.hostname": "127.0.0.1",
    "database.port": "5432",
    "database.user": "debezium",
    "database.password": "definitelynotpassword",
    "database.dbname" : "dbname",
    "database.server.name": "pg-dev",
    "table.include.list": "public.(.*)",
    "heartbeat.interval.ms": "5000",
    "slot.name": "dbname_debezium",
    "publication.name": "dbname_publication",
    "transforms": "AddPrefix",
    "transforms.AddPrefix.type": "org.apache.kafka.connect.transforms.RegexRouter",
    "transforms.AddPrefix.regex": "pg-dev.public.(.*)",
    "transforms.AddPrefix.replacement": "data.cdc.dbname"
  }
}

์ด ์„ค์ • ํ›„ ์ปค๋„ฅํ„ฐ ์ž‘๋™ ์›๋ฆฌ๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

  • ์ฒ˜์Œ ์‹คํ–‰ ์‹œ ๊ตฌ์„ฑ์— ์ง€์ •๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•˜์—ฌ ๋ชจ๋“œ๋กœ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐ ์Šค๋ƒ…์ƒท, ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜์—ฌ ์–ป์€ ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ Kafka๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. SELECT * FROM table_name.
  • ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ปค๋„ฅํ„ฐ๋Š” PostgreSQL WAL ํŒŒ์ผ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฝ๋Š” ๋ชจ๋“œ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ๋œ ์˜ต์…˜ ์ •๋ณด:

  • name โ€” ์•„๋ž˜ ์„ค๋ช…๋œ ๊ตฌ์„ฑ์ด ์‚ฌ์šฉ๋˜๋Š” ์ปค๋„ฅํ„ฐ์˜ ์ด๋ฆ„ ์•ž์œผ๋กœ ์ด ์ด๋ฆ„์€ Kafka Connect REST API๋ฅผ ํ†ตํ•ด ์ปค๋„ฅํ„ฐ ์ž‘์—…(์ฆ‰, ์ƒํƒœ ๋ณด๊ธฐ/๋‹ค์‹œ ์‹œ์ž‘/๊ตฌ์„ฑ ์—…๋ฐ์ดํŠธ)์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • connector.class โ€” ๊ตฌ์„ฑ๋œ ์ปค๋„ฅํ„ฐ์—์„œ ์‚ฌ์šฉํ•  DBMS ์ปค๋„ฅํ„ฐ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
  • plugin.name โ€” WAL ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋…ผ๋ฆฌ์ ์œผ๋กœ ๋””์ฝ”๋”ฉํ•˜๊ธฐ ์œ„ํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ์„ ํƒ ๊ฐ€๋Šฅ wal2json, decoderbuffs ะธ pgoutput. ์ฒ˜์Œ ๋‘ ๊ฐœ๋Š” DBMS์— ์ ์ ˆํ•œ ํ™•์žฅ์„ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. pgoutput PostgreSQL ๋ฒ„์ „ 10 ์ด์ƒ์˜ ๊ฒฝ์šฐ ์ถ”๊ฐ€ ์กฐ์ž‘์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • database.* โ€” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์˜ต์…˜. ์—ฌ๊ธฐ์„œ database.server.name โ€” Kafka ํด๋Ÿฌ์Šคํ„ฐ์—์„œ ์ฃผ์ œ ์ด๋ฆ„์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” PostgreSQL ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
  • table.include.list โ€” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”์ ํ•˜๋ ค๋Š” ํ…Œ์ด๋ธ” ๋ชฉ๋ก ํ˜•์‹์œผ๋กœ ์ง€์ • schema.table_name; ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. table.exclude.list;
  • heartbeat.interval.ms โ€” ์ปค๋„ฅํ„ฐ๊ฐ€ ํ•˜ํŠธ๋น„ํŠธ ๋ฉ”์‹œ์ง€๋ฅผ ํŠน์ˆ˜ ์ฃผ์ œ๋กœ ๋ณด๋‚ด๋Š” ๊ฐ„๊ฒฉ(๋ฐ€๋ฆฌ์ดˆ)์ž…๋‹ˆ๋‹ค.
  • heartbeat.action.query โ€” ๊ฐ ํ•˜ํŠธ๋น„ํŠธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ๋•Œ ์‹คํ–‰๋  ์š”์ฒญ(์˜ต์…˜์€ ๋ฒ„์ „ 1.1์— ๋‚˜ํƒ€๋‚จ)
  • slot.name โ€” ์ปค๋„ฅํ„ฐ์—์„œ ์‚ฌ์šฉํ•  ๋ณต์ œ ์Šฌ๋กฏ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
  • publication.name - ์ด๋ฆ„ ์ถœํŒ ์ปค๋„ฅํ„ฐ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” PostgreSQL์—์„œ. ๋งŒ์•ฝ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, Debezium์€ ๊ทธ๊ฒƒ์„ ์ƒ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ๋œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ด ์ž‘์—…์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ๊ถŒํ•œ์ด ์—†์œผ๋ฉด ์ปค๋„ฅํ„ฐ๊ฐ€ ์˜ค๋ฅ˜์™€ ํ•จ๊ป˜ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.
  • transforms ๋Œ€์ƒ ์ฃผ์ œ์˜ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •ํ™•ํ•˜๊ฒŒ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
    • transforms.AddPrefix.type ์ •๊ทœ์‹์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
    • transforms.AddPrefix.regex โ€” ๋Œ€์ƒ ์ฃผ์ œ์˜ ์ด๋ฆ„์„ ์žฌ์ •์˜ํ•˜๋Š” ๋งˆ์Šคํฌ
    • transforms.AddPrefix.replacement - ์šฐ๋ฆฌ๊ฐ€ ์žฌ์ •์˜ํ•˜๋Š” ๊ฒƒ์„ ์ง์ ‘์ ์œผ๋กœ.

ํ•˜ํŠธ๋น„ํŠธ ๋ฐ ๋ณ€ํ™˜์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ

๊ธฐ๋ณธ์ ์œผ๋กœ ์ปค๋„ฅํ„ฐ๋Š” ์ปค๋ฐ‹๋œ ๊ฐ ํŠธ๋žœ์žญ์…˜์— ๋Œ€ํ•ด Kafka์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ณ  ํ•ด๋‹น LSN(๋กœ๊ทธ ์‹œํ€€์Šค ๋ฒˆํ˜ธ)์ด ์„œ๋น„์Šค ํ•ญ๋ชฉ์— ๊ธฐ๋ก๋ฉ๋‹ˆ๋‹ค. offset. ๊ทธ๋Ÿฌ๋‚˜ ์ปค๋„ฅํ„ฐ๊ฐ€ ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ํ•ด๋‹น ํ…Œ์ด๋ธ”์˜ ์ผ๋ถ€(๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ž์ฃผ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ)๋งŒ ์ฝ๋„๋ก ๊ตฌ์„ฑ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

  • ์ปค๋„ฅํ„ฐ๋Š” WAL ํŒŒ์ผ์„ ์ฝ๊ณ  ๋ชจ๋‹ˆํ„ฐ๋ง ์ค‘์ธ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹์„ ๊ฐ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ฃผ์ œ๋‚˜ ๋ณต์ œ ์Šฌ๋กฏ์—์„œ ํ˜„์žฌ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฉด WAL ํŒŒ์ผ์ด ๋””์Šคํฌ์— ๋ณด๊ด€๋˜์–ด ๋””์Šคํฌ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์˜ต์…˜์ด ๊ตฌ์ถœ๋˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค. heartbeat.interval.ms ะธ heartbeat.action.query. ์ด๋Ÿฌํ•œ ์˜ต์…˜์„ ์Œ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ํ•˜ํŠธ๋น„ํŠธ ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์†ก๋  ๋•Œ๋งˆ๋‹ค ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์—์„œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปค๋„ฅํ„ฐ๊ฐ€ ํ˜„์žฌ ์œ„์น˜ํ•œ(๋ณต์ œ ์Šฌ๋กฏ์— ์žˆ๋Š”) LSN์€ ์ง€์†์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด DBMS๋Š” ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ WAL ํŒŒ์ผ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ต์…˜์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ์  ์„œ๋ฅ˜ ๋น„์น˜.

์ฃผ์˜ ๊นŠ๊ฒŒ ์ฃผ๋ชฉํ•  ๋งŒํ•œ ๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. transforms. ํŽธ๋ฆฌํ•จ๊ณผ ์•„๋ฆ„๋‹ค์›€์ด ๋” ์ค‘์š”ํ•˜์ง€๋งŒ...

๊ธฐ๋ณธ์ ์œผ๋กœ Debezium์€ ๋‹ค์Œ ๋ช…๋ช… ์ •์ฑ…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฃผ์ œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. serverName.schemaName.tableName. ์ด๋Š” ํ•ญ์ƒ ํŽธ๋ฆฌํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ต์…˜ transforms ์ •๊ทœ์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ • ์ด๋ฆ„์„ ๊ฐ€์ง„ ์ฃผ์ œ๋กœ ๋ผ์šฐํŒ…ํ•ด์•ผ ํ•˜๋Š” ์ด๋ฒคํŠธ์ธ ํ…Œ์ด๋ธ” ๋ชฉ๋ก์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ๊ตฌ์„ฑ์—์„œ๋Š” ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. transforms ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ผ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋‹ˆํ„ฐ๋ง๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ชจ๋“  CDC ์ด๋ฒคํŠธ๋Š” ๋‹ค์Œ ์ด๋ฆ„์˜ ์ฃผ์ œ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. data.cdc.dbname. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด (์ด ์„ค์ • ์—†์ด) Debezium์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ ํ…Œ์ด๋ธ”์— ๋Œ€ํ•œ ์ฃผ์ œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. pg-dev.public.<table_name>.

์ปค๋„ฅํ„ฐ ์ œํ•œ

PostgreSQL์šฉ ์ปค๋„ฅํ„ฐ ๊ตฌ์„ฑ์— ๋Œ€ํ•œ ์„ค๋ช…์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋ ค๋ฉด ํ•ด๋‹น ์ž‘์—…์˜ ๋‹ค์Œ ๊ธฐ๋Šฅ/์ œํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

  1. PostgreSQL์šฉ ์ปค๋„ฅํ„ฐ์˜ ๊ธฐ๋Šฅ์€ ๋…ผ๋ฆฌ์  ๋””์ฝ”๋”ฉ ๊ฐœ๋…์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๊ทธ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์กฐ ๋ณ€๊ฒฝ ์š”์ฒญ์„ ์ถ”์ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (DDL) - ๋”ฐ๋ผ์„œ ์ด ๋ฐ์ดํ„ฐ๋Š” ์ฃผ์ œ์— ํฌํ•จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  2. ๋ณต์ œ ์Šฌ๋กฏ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ปค๋„ฅํ„ฐ ์—ฐ๊ฒฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋งŒ ์ฃผ์š” DBMS ์ธ์Šคํ„ด์Šค์—.
  3. ์ปค๋„ฅํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐ๋˜๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฝ๊ธฐ ์ „์šฉ ๊ถŒํ•œ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ฒ˜์Œ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋ณต์ œ ์Šฌ๋กฏ์„ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๊ฒŒ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ ์ ์šฉ

์ด์ œ ๊ตฌ์„ฑ์„ ์ปค๋„ฅํ„ฐ์— ๋กœ๋“œํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

curl -i -X POST -H "Accept:application/json" 
  -H  "Content-Type:application/json"  http://localhost:8083/connectors/ 
  -d @pg-con.json

๋‹ค์šด๋กœ๋“œ๊ฐ€ ์„ฑ๊ณตํ–ˆ๊ณ  ์ปค๋„ฅํ„ฐ๊ฐ€ ์‹œ์ž‘๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

$ curl -i http://localhost:8083/connectors/pg-connector/status 
HTTP/1.1 200 OK
Date: Thu, 17 Sep 2020 20:19:40 GMT
Content-Type: application/json
Content-Length: 175
Server: Jetty(9.4.20.v20190813)

{"name":"pg-connector","connector":{"state":"RUNNING","worker_id":"172.24.0.5:8083"},"tasks":[{"id":0,"state":"RUNNING","worker_id":"172.24.0.5:8083"}],"type":"source"}

์ข‹์Šต๋‹ˆ๋‹ค. ์„ค์ •์ด ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉฐ ์‚ฌ์šฉํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์†Œ๋น„์ž์ธ ์ฒ™ํ•˜๊ณ  Kafka์— ์—ฐ๊ฒฐํ•œ ํ›„ ํ…Œ์ด๋ธ”์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ณ€๊ฒฝํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

$ kafka/bin/kafka-console-consumer.sh 
  --bootstrap-server kafka:9092 
  --from-beginning 
  --property print.key=true 
  --topic data.cdc.dbname

postgres=# insert into customers (id, first_name, last_name, email) values (1005, 'foo', 'bar', '[email protected]');
INSERT 0 1
postgres=# update customers set first_name = 'egg' where id = 1005;
UPDATE 1

์šฐ๋ฆฌ ์ฃผ์ œ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ํฌํ•จ๋œ ๋งค์šฐ ๊ธด JSON

{
"schema":{
"type":"struct",
"fields":[
{
"type":"int32",
"optional":false,
"field":"id"
}
],
"optional":false,
"name":"data.cdc.dbname.Key"
},
"payload":{
"id":1005
}
}{
"schema":{
"type":"struct",
"fields":[
{
"type":"struct",
"fields":[
{
"type":"int32",
"optional":false,
"field":"id"
},
{
"type":"string",
"optional":false,
"field":"first_name"
},
{
"type":"string",
"optional":false,
"field":"last_name"
},
{
"type":"string",
"optional":false,
"field":"email"
}
],
"optional":true,
"name":"data.cdc.dbname.Value",
"field":"before"
},
{
"type":"struct",
"fields":[
{
"type":"int32",
"optional":false,
"field":"id"
},
{
"type":"string",
"optional":false,
"field":"first_name"
},
{
"type":"string",
"optional":false,
"field":"last_name"
},
{
"type":"string",
"optional":false,
"field":"email"
}
],
"optional":true,
"name":"data.cdc.dbname.Value",
"field":"after"
},
{
"type":"struct",
"fields":[
{
"type":"string",
"optional":false,
"field":"version"
},
{
"type":"string",
"optional":false,
"field":"connector"
},
{
"type":"string",
"optional":false,
"field":"name"
},
{
"type":"int64",
"optional":false,
"field":"ts_ms"
},
{
"type":"string",
"optional":true,
"name":"io.debezium.data.Enum",
"version":1,
"parameters":{
"allowed":"true,last,false"
},
"default":"false",
"field":"snapshot"
},
{
"type":"string",
"optional":false,
"field":"db"
},
{
"type":"string",
"optional":false,
"field":"schema"
},
{
"type":"string",
"optional":false,
"field":"table"
},
{
"type":"int64",
"optional":true,
"field":"txId"
},
{
"type":"int64",
"optional":true,
"field":"lsn"
},
{
"type":"int64",
"optional":true,
"field":"xmin"
}
],
"optional":false,
"name":"io.debezium.connector.postgresql.Source",
"field":"source"
},
{
"type":"string",
"optional":false,
"field":"op"
},
{
"type":"int64",
"optional":true,
"field":"ts_ms"
},
{
"type":"struct",
"fields":[
{
"type":"string",
"optional":false,
"field":"id"
},
{
"type":"int64",
"optional":false,
"field":"total_order"
},
{
"type":"int64",
"optional":false,
"field":"data_collection_order"
}
],
"optional":true,
"field":"transaction"
}
],
"optional":false,
"name":"data.cdc.dbname.Envelope"
},
"payload":{
"before":null,
"after":{
"id":1005,
"first_name":"foo",
"last_name":"bar",
"email":"[email protected]"
},
"source":{
"version":"1.2.3.Final",
"connector":"postgresql",
"name":"dbserver1",
"ts_ms":1600374991648,
"snapshot":"false",
"db":"postgres",
"schema":"public",
"table":"customers",
"txId":602,
"lsn":34088472,
"xmin":null
},
"op":"c",
"ts_ms":1600374991762,
"transaction":null
}
}{
"schema":{
"type":"struct",
"fields":[
{
"type":"int32",
"optional":false,
"field":"id"
}
],
"optional":false,
"name":"data.cdc.dbname.Key"
},
"payload":{
"id":1005
}
}{
"schema":{
"type":"struct",
"fields":[
{
"type":"struct",
"fields":[
{
"type":"int32",
"optional":false,
"field":"id"
},
{
"type":"string",
"optional":false,
"field":"first_name"
},
{
"type":"string",
"optional":false,
"field":"last_name"
},
{
"type":"string",
"optional":false,
"field":"email"
}
],
"optional":true,
"name":"data.cdc.dbname.Value",
"field":"before"
},
{
"type":"struct",
"fields":[
{
"type":"int32",
"optional":false,
"field":"id"
},
{
"type":"string",
"optional":false,
"field":"first_name"
},
{
"type":"string",
"optional":false,
"field":"last_name"
},
{
"type":"string",
"optional":false,
"field":"email"
}
],
"optional":true,
"name":"data.cdc.dbname.Value",
"field":"after"
},
{
"type":"struct",
"fields":[
{
"type":"string",
"optional":false,
"field":"version"
},
{
"type":"string",
"optional":false,
"field":"connector"
},
{
"type":"string",
"optional":false,
"field":"name"
},
{
"type":"int64",
"optional":false,
"field":"ts_ms"
},
{
"type":"string",
"optional":true,
"name":"io.debezium.data.Enum",
"version":1,
"parameters":{
"allowed":"true,last,false"
},
"default":"false",
"field":"snapshot"
},
{
"type":"string",
"optional":false,
"field":"db"
},
{
"type":"string",
"optional":false,
"field":"schema"
},
{
"type":"string",
"optional":false,
"field":"table"
},
{
"type":"int64",
"optional":true,
"field":"txId"
},
{
"type":"int64",
"optional":true,
"field":"lsn"
},
{
"type":"int64",
"optional":true,
"field":"xmin"
}
],
"optional":false,
"name":"io.debezium.connector.postgresql.Source",
"field":"source"
},
{
"type":"string",
"optional":false,
"field":"op"
},
{
"type":"int64",
"optional":true,
"field":"ts_ms"
},
{
"type":"struct",
"fields":[
{
"type":"string",
"optional":false,
"field":"id"
},
{
"type":"int64",
"optional":false,
"field":"total_order"
},
{
"type":"int64",
"optional":false,
"field":"data_collection_order"
}
],
"optional":true,
"field":"transaction"
}
],
"optional":false,
"name":"data.cdc.dbname.Envelope"
},
"payload":{
"before":{
"id":1005,
"first_name":"foo",
"last_name":"bar",
"email":"[email protected]"
},
"after":{
"id":1005,
"first_name":"egg",
"last_name":"bar",
"email":"[email protected]"
},
"source":{
"version":"1.2.3.Final",
"connector":"postgresql",
"name":"dbserver1",
"ts_ms":1600375609365,
"snapshot":"false",
"db":"postgres",
"schema":"public",
"table":"customers",
"txId":603,
"lsn":34089688,
"xmin":null
},
"op":"u",
"ts_ms":1600375609778,
"transaction":null
}
}

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ๋ ˆ์ฝ”๋“œ๋Š” ๋ณ€๊ฒฝ๋œ ๋ ˆ์ฝ”๋“œ์˜ ํ‚ค(PK)์™€ ๋ณ€๊ฒฝ์˜ ๋ณธ์งˆ, ์ฆ‰ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ด์ „์— ๋ฌด์—‡์ด์—ˆ๋Š”์ง€, ์ดํ›„์— ๋ฌด์—‡์ด ๋˜์—ˆ๋Š”์ง€๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

  • ์˜ ๊ฒฝ์šฐ INSERT: ์ด์ „ ๊ฐ’(before) ๊ฐ™์Œ null, ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ดํ›„ - ์‚ฝ์ž…๋œ ๋ผ์ธ.
  • ์˜ ๊ฒฝ์šฐ UPDATE:์—์„œ payload.before ๋ผ์ธ์˜ ์ด์ „ ์ƒํƒœ๊ฐ€ ํ‘œ์‹œ๋˜๊ณ , payload.after โ€” ๋ณ€ํ™”์˜ ๋ณธ์งˆ์„ ์ง€๋‹Œ ์ƒˆ๋กœ์šด ๊ฒƒ.

2.2 ๋ชฝ๊ณ DB

์ด ์ปค๋„ฅํ„ฐ๋Š” ํ‘œ์ค€ MongoDB ๋ณต์ œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ DBMS ๋…ธ๋“œ์˜ oplog์—์„œ ์ •๋ณด๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ ์„ค๋ช…ํ•œ PgSQL์šฉ ์ปค๋„ฅํ„ฐ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์—ฌ๊ธฐ์—์„œ๋„ ์ฒ˜์Œ ์‹œ์ž‘ํ•  ๋•Œ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์Šค๋ƒ…์ƒท์ด ์ƒ์„ฑ๋˜๊ณ  ๊ทธ ํ›„ ์ปค๋„ฅํ„ฐ๊ฐ€ oplog ์ฝ๊ธฐ ๋ชจ๋“œ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ ์˜ˆ :

{
"name": "mp-k8s-mongo-connector",
"config": {
"connector.class": "io.debezium.connector.mongodb.MongoDbConnector",
"tasks.max": "1",
"mongodb.hosts": "MainRepSet/mongo:27017",
"mongodb.name": "mongo",
"mongodb.user": "debezium",
"mongodb.password": "dbname",
"database.whitelist": "db_1,db_2",
"transforms": "AddPrefix",
"transforms.AddPrefix.type": "org.apache.kafka.connect.transforms.RegexRouter",
"transforms.AddPrefix.regex": "mongo.([a-zA-Z_0-9]*).([a-zA-Z_0-9]*)",
"transforms.AddPrefix.replacement": "data.cdc.mongo_$1"
}
}

๋ณด์‹œ๋‹ค์‹œํ”ผ ์ด์ „ ์˜ˆ์™€ ๋น„๊ตํ•˜์—ฌ ์—ฌ๊ธฐ์—๋Š” ์ƒˆ๋กœ์šด ์˜ต์…˜์ด ์—†์ง€๋งŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ๋‹ด๋‹นํ•˜๋Š” ์˜ต์…˜ ์ˆ˜์™€ ์ ‘๋‘์‚ฌ๋งŒ ์ค„์—ˆ์Šต๋‹ˆ๋‹ค.

์„ค์ • transforms ์ด๋ฒˆ์—๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ‚ค๋งˆ์—์„œ ๋Œ€์ƒ ์ฃผ์ œ์˜ ์ด๋ฆ„์„ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. <server_name>.<db_name>.<collection_name> ะฒ data.cdc.mongo_<db_name>.

๊ฒฐํ•จ ํ—ˆ์šฉ

์šฐ๋ฆฌ ์‹œ๋Œ€์˜ ๋‚ด๊ฒฐํ•จ์„ฑ ๋ฐ ๊ณ ๊ฐ€์šฉ์„ฑ ๋ฌธ์ œ๋Š” ๊ทธ ์–ด๋Š ๋•Œ๋ณด๋‹ค ์‹ฌ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๋ฐ์ดํ„ฐ์™€ ํŠธ๋žœ์žญ์…˜์— ๊ด€ํ•ด ์ด์•ผ๊ธฐํ•  ๋•Œ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ถ”์ ํ•˜๋Š” ๊ฒƒ์ด ์ด ๋ฌธ์ œ์—์„œ ์ œ์™ธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์›์น™์ ์œผ๋กœ ๋ฌด์—‡์ด ์ž˜๋ชป๋  ์ˆ˜ ์žˆ๋Š”์ง€, ๊ฐ ๊ฒฝ์šฐ์— Debezium์— ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚ ์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜ตํŠธ์•„์›ƒ ์˜ต์…˜์—๋Š” ์„ธ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์นดํ”„์นด ์—ฐ๊ฒฐ ์‹คํŒจ. Connect๊ฐ€ ๋ถ„์‚ฐ ๋ชจ๋“œ์—์„œ ์ž‘๋™ํ•˜๋„๋ก ๊ตฌ์„ฑ๋œ ๊ฒฝ์šฐ ๋™์ผํ•œ group.id๋ฅผ ์„ค์ •ํ•˜๋ ค๋ฉด ์—ฌ๋Ÿฌ ์ž‘์—…์ž๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์‹คํŒจํ•˜๋ฉด ์ปค๋„ฅํ„ฐ๊ฐ€ ๋‹ค๋ฅธ ์ž‘์—…์ž์—์„œ ๋‹ค์‹œ ์‹œ์ž‘๋˜๊ณ  Kafka ์ฃผ์ œ์—์„œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ปค๋ฐ‹๋œ ์œ„์น˜๋ถ€ํ„ฐ ๊ณ„์† ์ฝ์Šต๋‹ˆ๋‹ค.
  2. Kafka ํด๋Ÿฌ์Šคํ„ฐ์™€์˜ ์—ฐ๊ฒฐ ๋Š๊น€. ์ปค๋„ฅํ„ฐ๋Š” ๋‹จ์ˆœํžˆ Kafka๋กœ ์ „์†ก์— ์‹คํŒจํ•œ ์œ„์น˜์—์„œ ์ฝ๊ธฐ๋ฅผ ์ค‘์ง€ํ•˜๊ณ  ์‹œ๋„๊ฐ€ ์„ฑ๊ณตํ•  ๋•Œ๊นŒ์ง€ ์ฃผ๊ธฐ์ ์œผ๋กœ ์žฌ์ „์†ก์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.
  3. ๋ฐ์ดํ„ฐ ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ. ์ปค๋„ฅํ„ฐ๋Š” ๊ตฌ์„ฑ๋œ ๋Œ€๋กœ ์†Œ์Šค์— ๋‹ค์‹œ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ 16๋ฒˆ ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€์ˆ˜ ๋ฐฑ์˜คํ”„. 16๋ฒˆ์งธ ์‹œ๋„์— ์‹คํŒจํ•˜๋ฉด ํ•ด๋‹น ์ž‘์—…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์‹คํŒจํ•œ Kafka Connect REST ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ˆ˜๋™์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์˜ ๊ฒฝ์šฐ PostgreSQL ๋ฐ์ดํ„ฐ๋Š” ์†์‹ค๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๋ณต์ œ ์Šฌ๋กฏ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปค๋„ฅํ„ฐ๊ฐ€ ์ฝ์ง€ ์•Š๋Š” WAL ํŒŒ์ผ์„ ์‚ญ์ œํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์ฝ”์ธ์˜ ๋‹จ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋„ฅํ„ฐ์™€ DBMS ์‚ฌ์ด์˜ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์ด ์žฅ๊ธฐ๊ฐ„ ์ค‘๋‹จ๋˜๋ฉด ๋””์Šคํฌ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•ด์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๊ณ  ์ด๋กœ ์ธํ•ด ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด DBMS.
    • ์˜ ๊ฒฝ์šฐ MySQL์˜ binlog ํŒŒ์ผ์€ ์—ฐ๊ฒฐ์ด ๋ณต์›๋˜๊ธฐ ์ „์— DBMS ์ž์ฒด์— ์˜ํ•ด ํšŒ์ „๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์ปค๋„ฅํ„ฐ๊ฐ€ ์‹คํŒจ ์ƒํƒœ๋กœ ์ „ํ™˜๋˜๊ณ , ์ •์ƒ ์ž‘๋™์„ ๋ณต์›ํ•˜๋ ค๋ฉด ์ดˆ๊ธฐ ์Šค๋ƒ…์ƒท ๋ชจ๋“œ์—์„œ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜์—ฌ binlog์—์„œ ๊ณ„์† ์ฝ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • ์•ฝ MongoDB์˜. ์„ค๋ช…์„œ์— ๋”ฐ๋ฅด๋ฉด ๋กœ๊ทธ/oplog ํŒŒ์ผ์ด ์‚ญ์ œ๋˜๊ณ  ์ปค๋„ฅํ„ฐ๊ฐ€ ์ค‘๋‹จ๋œ ์œ„์น˜์—์„œ ๊ณ„์† ์ฝ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์ปค๋„ฅํ„ฐ์˜ ๋™์ž‘์€ ๋ชจ๋“  DBMS์— ๋Œ€ํ•ด ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ปค๋„ฅํ„ฐ๊ฐ€ ์ƒํƒœ๋กœ ์ „ํ™˜๋จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์‹คํŒจํ•œ ๋ชจ๋“œ์—์„œ ๋‹ค์‹œ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐ ์Šค๋ƒ…์ƒท.

      ๊ทธ๋Ÿฌ๋‚˜ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋„ฅํ„ฐ ์—ฐ๊ฒฐ์ด ์˜ค๋žซ๋™์•ˆ ๋Š์–ด์ง€๊ณ (๋˜๋Š” MongoDB ์ธ์Šคํ„ด์Šค์— ๋„๋‹ฌํ•  ์ˆ˜ ์—†์Œ) ์ด ์‹œ๊ฐ„ ๋™์•ˆ oplog๊ฐ€ ํšŒ์ „ํ•œ ๊ฒฝ์šฐ ์—ฐ๊ฒฐ์ด ๋ณต์›๋˜๋ฉด ์ปค๋„ฅํ„ฐ๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฒซ ๋ฒˆ์งธ ์œ„์น˜์—์„œ ์นจ์ฐฉํ•˜๊ฒŒ ๊ณ„์† ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ”๋กœ Kafka์˜ ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹ˆ ์น  ๊ฒƒ์ด๋‹ค.

๊ฒฐ๋ก 

Debezium์€ CDC ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ๋‚˜์˜ ์ฒซ ๊ฒฝํ—˜์ด๋ฉฐ ์ „๋ฐ˜์ ์œผ๋กœ ๋งค์šฐ ๊ธ์ •์ ์ž…๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” ์ฃผ์š” DBMS ์ง€์›, ๊ตฌ์„ฑ ์šฉ์ด์„ฑ, ํด๋Ÿฌ์Šคํ„ฐ๋ง ์ง€์› ๋ฐ ํ™œ๋ฐœํ•œ ์ปค๋ฎค๋‹ˆํ‹ฐ๋กœ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹ค๋ฌด์— ๊ด€์‹ฌ์ด ์žˆ๋Š” ๋ถ„๋“ค์€ ๊ฐ€์ด๋“œ๋ฅผ ์ฝ์–ด๋ณด์‹œ๊ธธ ๊ถŒํ•ฉ๋‹ˆ๋‹ค. ์นดํ”„์นด ์ปค๋„ฅํŠธ ะธ ๋ฐ๋ฒ  ์ง€์›€.

Kafka Connect์šฉ JDBC ์ปค๋„ฅํ„ฐ์™€ ๋น„๊ตํ•  ๋•Œ Debezium์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์€ DBMS ๋กœ๊ทธ์—์„œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฝ์–ด ์ตœ์†Œํ•œ์˜ ๋Œ€๊ธฐ ์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Kafka Connect์˜ JDBC ์ปค๋„ฅํ„ฐ๋Š” ๊ณ ์ •๋œ ๊ฐ„๊ฒฉ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋ง๋˜๋Š” ํ…Œ์ด๋ธ”์„ ์ฟผ๋ฆฌํ•˜๊ณ  (๊ฐ™์€ ์ด์œ ๋กœ) ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ญ์ œ๋  ๋•Œ ๋ฉ”์‹œ์ง€๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?).

์œ ์‚ฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด Debezium ์™ธ์— ๋‹ค์Œ ์†”๋ฃจ์…˜์— ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PS

๋ธ”๋กœ๊ทธ์—์„œ๋„ ์ฝ์–ด๋ณด์„ธ์š”.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€