
ํค์ด ํ๋ธ๋ฅด!
์ ๋ Tinkoff ํ์์ ์ผํ๊ณ ์๋๋ฐ, ์ด ํ์ ์์ฒด ์๋ฆผ ์ผํฐ๋ฅผ ๊ฐ๋ฐํ๊ณ ์์ต๋๋ค. ์ ๋ ์ฃผ๋ก Spring boot๋ฅผ ์ฌ์ฉํ์ฌ Java๋ก ๊ฐ๋ฐํ๊ณ ํ๋ก์ ํธ์์ ๋ฐ์ํ๋ ๋ค์ํ ๊ธฐ์ ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
๋๋ถ๋ถ์ ๋ง์ดํฌ๋ก์๋น์ค๋ ๋ฉ์์ง ๋ธ๋ก์ปค๋ฅผ ํตํด ๋น๋๊ธฐ์ ์ผ๋ก ์๋ก ํต์ ํฉ๋๋ค. ์ด์ ์๋ IBM MQ๋ฅผ ๋ธ๋ก์ปค๋ก ์ฌ์ฉํ๋๋ฐ, ์ด๋ ๋ ์ด์ ๋ถํ๋ฅผ ๊ฐ๋นํ ์ ์์์ง๋ง ๋์์ ๋์ ์ ๋ฌ ๋ณด์ฅ์ ์ ๊ณตํ์ต๋๋ค.
๋์ฒด ์๋ฃจ์ ์ผ๋ก Apache Kafka๊ฐ ์ ์๋์๋๋ฐ, ์ด๋ ํ์ฅ์ฑ์ด ๋ฐ์ด๋ ์ ์ฌ๋ ฅ์ ๊ฐ์ง๊ณ ์์ง๋ง, ์ํ๊น๊ฒ๋ ๋ค์ํ ์๋๋ฆฌ์ค์ ๋ง๊ฒ ๊ตฌ์ฑ์ ๋ํ ์ฌ์ค์ ๊ฐ๋ณ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ด ํ์ํฉ๋๋ค. ๊ฒ๋ค๊ฐ, ์นดํ์นด์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์๋ํ๋ ์ต์ ํ ๋ฒ ์ ๋ฌ ๋ฉ์ปค๋์ฆ์ ์ฒ์๋ถํฐ ํ์ํ ์์ค์ ์ผ๊ด์ฑ์ ์ ์งํ๋ ๊ฒ์ ํ์ฉํ์ง ์์์ต๋๋ค. ๋ค์์ผ๋ก, Kafka ๊ตฌ์ฑ์ ๋ํ ๊ฒฝํ์ ๊ณต์ ํ๊ฒ ์ต๋๋ค. ํนํ, ์ ํํ ํ ๋ฒ๋ง ์ ๋ฌ๋๋๋ก ์ค์ ํ๊ณ ์คํํ๋ ๋ฐฉ๋ฒ์ ์๋ ค๋๋ฆฌ๊ฒ ์ต๋๋ค.
๋ณด์ฅ๋ ๋ฐฐ์ก ๋ฐ ๊ธฐํ
์๋์ ์ค๋ช ๋ ์ค์ ์ ๊ธฐ๋ณธ ์ฐ๊ฒฐ ์ค์ ์ผ๋ก ์ธํด ๋ฐ์ํ ์ ์๋ ์ฌ๋ฌ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ํ์ง๋ง ๋จผ์ ๋๋ฒ๊น ์ ์ฉ์ดํ๊ฒ ํ ์ ์๋ ํ ๊ฐ์ง ๋งค๊ฐ๋ณ์์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด๊ณ ์ถ์ต๋๋ค.
์ด๊ฒ์ด ๋์์ด ๋ ๊ฒ์ ๋๋ค ํด๋ผ์ด์ธํธ.์์ด๋ ์์ฐ์์ ์๋น์๋ฅผ ์ํด. ์ฒ์์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ์ ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ฉฐ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ ๋๋ก ์๋ํฉ๋๋ค. ํ์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ๋ฌ Consumer๋ฅผ ์ฌ์ฉํ๊ณ ์ด๋ฅผ ๋์ผํ client.id๋ก ์ค์ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํฉ๋๋ค.
org.apache.kafka.common.utils.AppInfoParser โ Error registering AppInfo mbean javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=kafka.test-0Kafka๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ JMX๋ฅผ ์ฌ์ฉํ๋ ค๋ ๊ฒฝ์ฐ ๋ฌธ์ ๊ฐ ๋ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ๊ณผ ์ฃผ์ ์ด๋ฆ ๋ฑ์ ์กฐํฉํ์ฌ client.id ๊ฐ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ๊ตฌ์ฑ ๊ฒฐ๊ณผ๋ ๋ช ๋ น ์ถ๋ ฅ์์ โโํ์ธํ ์ ์์ต๋๋ค. ์นดํ์นด-์๋น์-๊ทธ๋ฃน Confluent ์ ํธ๋ฆฌํฐ์์:

์ด์ ๋ณด์ฅ๋ ๋ฉ์์ง ์ ๋ฌ ์๋๋ฆฌ์ค๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. Kafka Producer์๋ ๋งค๊ฐ๋ณ์๊ฐ ์์ต๋๋ค. Acks์ด๋ฅผ ํตํด ํด๋ฌ์คํฐ ๋ฆฌ๋๊ฐ ๋ฉ์์ง๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋์๋ค๊ณ ๊ฐ์ฃผํด์ผ ํ๋ ํ์ธ ํ์๋ฅผ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ด ๋งค๊ฐ๋ณ์๋ ๋ค์ ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค.
- 0 - ํ์ธ์ด ๊ณ ๋ ค๋์ง ์์ต๋๋ค.
- 1์ ๊ธฐ๋ณธ ๋งค๊ฐ๋ณ์์ด๊ณ , 1๊ฐ์ ๋ณต์ ๋ณธ๋ง ํ์ธํ๋ฉด ๋ฉ๋๋ค.
- -1 โ ๋ชจ๋ ๋๊ธฐํ๋ ๋ณต์ ๋ณธ์ ํ์ธ์ด ํ์ํฉ๋๋ค(ํด๋ฌ์คํฐ ์ค์ ) min.insync.replicas).
๋์ด๋ ๊ฐ์ ๋ณด๋ฉด acks๊ฐ -1์ผ ๋ ๋ฉ์์ง๊ฐ ์์ค๋์ง ์์ ๊ฒ์ด๋ผ๋ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๋ณด์ฅ์ด ์ ๊ณต๋๋ค๋ ๊ฒ์ด ๋ถ๋ช ํฉ๋๋ค.
์ฐ๋ฆฌ ๋ชจ๋ ์๋ค์ํผ, ๋ถ์ฐ ์์คํ ์ ์ ๋ขฐํ ์ ์์ต๋๋ค. ์ผ์์ ์ธ ์คํจ๋ก๋ถํฐ ๋ณดํธํ๊ธฐ ์ํด Kafka Producer๋ ๋ค์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ฌ์๋์ด๋ฅผ ํตํด ์ฌ์๋ ํ์๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ๋ฐฐ๋ฌ.์๊ฐ ์ด๊ณผ.ms. retries ๋งค๊ฐ๋ณ์์ ๊ธฐ๋ณธ๊ฐ์ Integer.MAX_VALUE(2147483647)์ด๋ฏ๋ก delivery.timeout.ms๋ง ๋ณ๊ฒฝํ๋ฉด ๋ฉ์์ง ์ฌ์ ์ก ํ์๋ฅผ ์กฐ์ ํ ์ ์์ต๋๋ค.
์ ํํ ํ ๋ฒ ๋ฐฐ๋ฌ๋ก ์ ํ
๋์ด๋ ์ค์ ์ ์ฌ์ฉํ๋ฉด ์ ์์๊ฐ ๋์ ๋ณด์ฅ์ฑ์ ๊ฐ์ถ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค. ์ด์ Kafka ํ ํฝ์ ๋จ ํ๋์ ๋ฉ์์ง ์ฌ๋ณธ๋ง ๊ธฐ๋ก๋๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ๊ฒฝ์ฐ์๋ Producer์ ๋งค๊ฐ๋ณ์๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. enable.idempotence ์ฌ์ค์ ๋๋ค. ๋ฉฑ๋ฑ์ฑ์ ๋จ์ผ ์ฃผ์ ์ ํน์ ํํฐ์ ์ ๋จ ํ๋์ ๋ฉ์์ง๋ง ๊ธฐ๋ก๋จ์ ๋ณด์ฅํฉ๋๋ค. ๋ฉฑ๋ฑ์ฑ์ ํ์ฑํํ๊ธฐ ์ํ ์ ์ ์กฐ๊ฑด์ ๊ฐ์ ๋๋ค. acks = all, ์ฌ์๋ > 0, ์ฐ๊ฒฐ๋น ์ต๋ ๋นํ ์ค ์์ฒญ ์ โค 5. ๊ฐ๋ฐ์๊ฐ ์ด๋ฌํ ๋งค๊ฐ๋ณ์๋ฅผ ์ค์ ํ์ง ์์ผ๋ฉด ์์ ์ง์ ๋ ๊ฐ์ด ์๋์ผ๋ก ์ค์ ๋ฉ๋๋ค.
๋ฉฑ๋ฑ์ฑ์ด ๊ตฌ์ฑ๋๋ฉด ํญ์ ๋์ผํ ๋ฉ์์ง๊ฐ ๋์ผํ ํํฐ์ ์ ์ ์ฅ๋๋๋ก ํด์ผ ํฉ๋๋ค. ์ด ์์ ์ Producer์์ partitioner.class ํค์ ๋งค๊ฐ๋ณ์๋ฅผ ๊ตฌ์ฑํ์ฌ ์ํํ ์ ์์ต๋๋ค. ์ด์ ๋ถํฐ ์์ํด ๋ณด๊ฒ ์ต๋๋ค. ๊ฐ ๋ฐฐ์ก๋ง๋ค ๋์ผํด์ผ ํฉ๋๋ค. ์ด๋ ์๋ณธ ๋ฉ์์ง์ ๋น์ฆ๋์ค ์๋ณ์๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ๋ฌ์ฑํ ์ ์์ต๋๋ค. partitioner.class ๋งค๊ฐ๋ณ์์ ๊ธฐ๋ณธ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. . ์ด ๊ธฐ๋ณธ ๋ถํ ์ ๋ต์ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์งํ๋ฉ๋๋ค.
- ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ๋ ํํฐ์ ์ด ๋ช ์์ ์ผ๋ก ์ง์ ๋๋ฉด ํด๋น ํํฐ์ ์ ์ฌ์ฉํฉ๋๋ค.
- ํํฐ์ ์ด ์ง์ ๋์ง ์์์ง๋ง ํค๊ฐ ์ง์ ๋ ๊ฒฝ์ฐ ํค์ ํด์๋ก ํํฐ์ ์ ์ ํํฉ๋๋ค.
- ํํฐ์ ๊ณผ ํค๊ฐ ์ง์ ๋์ง ์์ผ๋ฉด ํํฐ์ ์ ํ๋์ฉ ์ ํํฉ๋๋ค(๋ผ์ด๋ ๋ก๋น).
๋ํ ํค์ ๋ฉฑ๋ฑ์ฑ์ ์ฌ์ฉํ์ฌ ๋งค๊ฐ๋ณ์๋ฅผ ๋ณด๋ ๋๋ค. ์ฐ๊ฒฐ๋น ์ต๋ ๋นํ ์ค ์์ฒญ ์ = 1 ์๋น์์๊ฒ ๋ฉ์์ง๋ฅผ ์์๋๋ก ์ฒ๋ฆฌํด ์ค๋๋ค. ํด๋ฌ์คํฐ์ ์ก์ธ์ค ์ ์ด๊ฐ ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ ํด๋น ์ฃผ์ ์ ๋ํ ๋ฉฑ๋ฑ ์ฐ๊ธฐ ๊ถํ์ด ํ์ํ๋ค๋ ์ ๋ ๊ธฐ์ตํด ๋๋ ๊ฒ์ด ์ข์ต๋๋ค.
๊ฐ์๊ธฐ ํค์ ์ํ ๋ฉฑ๋ฑ ์ ์ก ๊ธฐ๋ฅ์ด ๋ถ์กฑํด์ง๊ฑฐ๋ ์์ฐ์ ์ธก์ ๋ก์ง์ด ์๋ก ๋ค๋ฅธ ํํฐ์ ๊ฐ์ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ์ ์งํด์ผ ํ๋ ๊ฒฝ์ฐ, ํธ๋์ญ์ ์ด ํด๊ฒฐ์ฑ ์ด ๋ ์ ์์ต๋๋ค. ๋ํ ์ฒด์ธ ํธ๋์ญ์ ์ ์ฌ์ฉํ๋ฉด Kafka์ ๋ ์ฝ๋๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ ์ฝ๋์ ์กฐ๊ฑด๋ถ๋ก ๋๊ธฐํํ ์ ์์ต๋๋ค. ์์ฐ์์๊ฒ ํธ๋์ญ์ ์ ์ก์ ํ์ฑํํ๋ ค๋ฉด ๋ฉฑ๋ฑ์ฑ์ ๊ฐ์ ธ์ผ ํ๋ฉฐ ์ถ๊ฐ๋ก ๋ค์์ ์ง์ ํด์ผ ํฉ๋๋ค. transactional.id. Kafka ํด๋ฌ์คํฐ์ ์ก์ธ์ค ์ ์ด๊ฐ ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ ๋ฉฑ๋ฑ ์ฐ๊ธฐ์ ๊ฐ์ ํธ๋์ญ์ ์ฐ๊ธฐ์๋ ์ฐ๊ธฐ ๊ถํ์ด ํ์ํ๋ฉฐ, ์ด ๊ถํ์ transactional.id์ ์ ์ฅ๋ ๊ฐ์ ์ฌ์ฉํ์ฌ ๋ง์คํฌ๋ฅผ ํตํด ๋ถ์ฌํ ์ ์์ต๋๋ค.
๊ณต์์ ์ผ๋ก๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ๊ณผ ๊ฐ์ ๋ชจ๋ ๋ฌธ์์ด์ ํธ๋์ญ์ ์๋ณ์๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ํ์ง๋ง ๋์ผํ transactional.id๋ก ๋์ผํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ์ธ์คํด์ค๋ฅผ ์์ํ๋ฉด Kafka๊ฐ ์ฒ์ ์คํํ ์ธ์คํด์ค๋ฅผ ์ข๋น ํ๋ก์ธ์ค๋ก ๊ฐ์ฃผํ์ฌ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด์ ์ค์ง๋ฉ๋๋ค.
org.apache.kafka.common.errors.ProducerFencedException: Producer attempted an operation with an old epoch. Either there is a newer producer with the same transactionalId, or the producer's transaction has been expired by the broker.์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ํ๊ฒฝ ๋ณ์์์ ์ป์ ํธ์คํธ ์ด๋ฆ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ์ ์ ๋ฏธ์ฌ๋ก ๋ถ์ ๋๋ค.
ํ๋ก๋์๋ ๊ตฌ์ฑ๋์์ง๋ง, Kafka์ ํธ๋์ญ์ ์ ๋ฉ์์ง ๋ฒ์๋ง ๊ด๋ฆฌํฉ๋๋ค. ๊ฑฐ๋ ์ํ์ ๊ด๊ณ์์ด ๋ฉ์์ง๋ ์ฆ์ ์ฃผ์ ๋ก ์ ์ก๋์ง๋ง ์ถ๊ฐ์ ์ธ ์์คํ ์์ฑ์ด ์์ต๋๋ค.
์ด๋ฌํ ๋ฉ์์ง๊ฐ ์๋น์์๊ฒ ๋ฏธ๋ฆฌ ์ฝํ์ง ์๋๋ก ํ๋ ค๋ฉด ๋งค๊ฐ๋ณ์๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. ๊ฒฉ๋ฆฌ ์์ค read_committed ๊ฐ์ผ๋ก. ์ด๋ฌํ ์๋น์๋ ์ด์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋นํธ๋์ญ์
๋ฉ์์ง๋ฅผ ์ฝ์ ์ ์์ผ๋ฉฐ, ์ปค๋ฐ ์ดํ์๋ง ํธ๋์ญ์
๋ฉ์์ง๋ฅผ ์ฝ์ ์ ์์ต๋๋ค.
์์ ๋์ด๋ ๋ชจ๋ ์ค์ ์ ์๋ฃํ๋ค๋ฉด, ์ ํํ ํ ๋ฒ ๋ฐฐ์ก์ด ์ค์ ๋ ๊ฒ์
๋๋ค. ์ถํํด์!
ํ์ง๋ง ํ ๊ฐ์ง ๋ ์ค์ํ ์ ์ด ์์ต๋๋ค. ์์์ ๊ตฌ์ฑํ Transactional.id๋ ์ค์ ๋ก๋ ํธ๋์ญ์ ์ ๋์ฌ์ ๋๋ค. ๊ฑฐ๋ ๊ด๋ฆฌ์์ ์ผ๋ จ๋ฒํธ๊ฐ ์ถ๊ฐ๋ฉ๋๋ค. ์์ ๋ ์๋ณ์๋ ๋ค์์ ๋ฐ๊ธ๋ฉ๋๋ค. transactional.id.expiration.msKafka ํด๋ฌ์คํฐ์ ๊ตฌ์ฑ๋๊ณ ๊ธฐ๋ณธ๊ฐ์ "7์ผ"์ ๋๋ค. ์ด ์๊ฐ ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฉ์์ง๋ฅผ ์์ ํ์ง ๋ชปํ ๊ฒฝ์ฐ ๋ค์ ๊ฑฐ๋๋ฅผ ๋ณด๋ด๋ ค๊ณ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค. InvalidPidMappingException. ์ดํ, ๊ฑฐ๋ ์กฐ์ ์๋ ๋ค์ ๊ฑฐ๋์ ๋ํ ์๋ก์ด ์ผ๋ จ๋ฒํธ๋ฅผ ๋ฐ๊ธํฉ๋๋ค. ๊ทธ๋ฌ๋ InvalidPidMappingException์ด ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌ๋์ง ์์ผ๋ฉด ๋ฉ์์ง๊ฐ ์์ค๋ ์ ์์ต๋๋ค.
ํฉ๊ณ ๋์
๋ณด์๋ค์ํผ, ๋จ์ํ ์นดํ์นด์ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ์ฌ๋ฌ ๋งค๊ฐ๋ณ์๋ฅผ ์กฐํฉํ์ฌ ์ ํํด์ผ ํ๋ฉฐ, ๋น ๋ฅธ ๋ณ๊ฒฝ์ ๋๋นํด์ผ ํฉ๋๋ค. ์ด ๊ธ์์๋ ์ ํํ ํ ๋ฒ ์ ๋ฌ ์ค์ ์ ์์ธํ ๋ณด์ฌ๋๋ฆฌ๊ณ , ์ฐ๋ฆฌ๊ฐ ๊ฒช์ ๋ช ๊ฐ์ง client.id์ transactional.id ๊ตฌ์ฑ ๋ฌธ์ ์ ๋ํด ์ค๋ช ํ๊ณ ์ ํ์ต๋๋ค. ์๋๋ ์์ฐ์ ๋ฐ ์๋น์ ์ค์ ์ ๋ํ ์์ฝ์ ๋๋ค.
ํ๋ก๋์ :
- acks = ๋ชจ๋
- ์ฌ์๋ > 0
- enable.idempotence = true
- ์ฐ๊ฒฐ๋น ์ต๋ ๋นํ ์ค ์์ฒญ ์ โค 5(1 - ์ฃผ๋ฌธ๋ ์ ์ก์ ๊ฒฝ์ฐ)
- transactional.id = ${application-name}-${hostname}
์๋น์:
- ๊ฒฉ๋ฆฌ ์์ค = ์ฝ๊ธฐ ์ปค๋ฐ๋จ
ํฅํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ค๋ฅ๋ฅผ ์ต์ํํ๊ธฐ ์ํด, ์ฐ๋ฆฌ๋ ์คํ๋ง ๊ตฌ์ฑ์ ์์ฒด ๋ํผ๋ฅผ ๋ง๋ค์์ผ๋ฉฐ, ์ฌ๊ธฐ์ ๋์ด๋ ์ผ๋ถ ๋งค๊ฐ๋ณ์์ ๊ฐ์ด ์ด๋ฏธ ์ค์ ๋์ด ์์ต๋๋ค.
๋ค์์ ์์จ ํ์ต์ ์ํ ๋ช ๊ฐ์ง ์๋ฃ์ ๋๋ค.
์ถ์ฒ : habr.com
