Kafka를 사용하면서 Topic의 이름을 짓는 것에 고통을 느끼고 있다. 그래서 해당 주제에 대해서 생각을 정리하고 넘어가면 좋을 것 같아 해당 게시글을 작성하게 되었다. 기본적인 Naming에 대한 기술들은 코딩을 하면서 자연스럽게 터득하게 되므로 해당 내용에서는 연결자에 대한 고찰을 중점적으로 다룰 생각이다.
Kafka Topic Naming에 대해서 공부하던 중 좋은 게시글을 만나게 되었다. 해당 게시글을 아래에 추천하겠다.
https://devfoxstar.github.io/middleware/kafka-topic-naming/#google_vignette
Kafka Topic Naming에 대해서 공부하며 여러가지 연결자를 이용하여 Topic들을 생성해 보았는데, 해당 과정을 수행하는 도중 Topic의 연결자에 대한 버그들을 기술하고 넘어가려고 한다.
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''ecommerce-users'' at line 1
- 발생이유: MariaDB 같은 SQL 데이터베이스에서는 하이픈('-')이 특수 문자로 해석될 수 있으므로, Topic 이름에 이를 포함시킬 경우 SQL 구문 분석 과정에서 오류가 발생한다. 이는 Kafka Connect를 사용하여 데이터를 SQL 데이터베이스에 저장할 때 명시적으로 나타난다.
- 해결방법: Kafka Connect를 사용하여 Topic 이름으로부터 생성되는 테이블 이름을 직접 지정하는 것으로 해결할 수 있다. 이를 통해 SQL 데이터베이스에서 인식할 수 있는 이름으로 매핑하면 된다.
"org.apache.kafka.connect.errors.ConnectException: Exiting WorkerSinkTask due to unrecoverable exception.\r\n\tat org.apache.kafka.connect.runtime.WorkerSinkTask.deliverMessages(WorkerSinkTask.java:611)\r\n\tat org.apache.kafka.connect.runtime.WorkerSinkTask.poll(WorkerSinkTask.java:333)\r\n\tat org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:234)\r\n\tat org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:203)\r\n\tat org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:188)\r\n\tat org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:243)\r\n\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)\r\n\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)\r\n\tat java.base/java.lang.Thread.run(Thread.java:842)\r\nCaused by: org.apache.kafka.connect.errors.ConnectException: java.sql.SQLException: Exception chain:\r\njava.sql.BatchUpdateException: (conn=88) Table 'test.users' doesn't exist\r\njava.sql.BatchUpdateException: (conn=88) Table 'test.users' doesn't exist\r\njava.sql.SQLSyntaxErrorException: (conn=88) Table 'test.users' doesn't exist\r\n\r\n\tat io.confluent.connect.jdbc.sink.JdbcSinkTask.put(JdbcSinkTask.java:132)\r\n\tat org.apache.kafka.connect.runtime.WorkerSinkTask.deliverMessages(WorkerSinkTask.java:581)\r\n\t... 10 more\r\nCaused by: java.sql.SQLException: Exception chain:\r\njava.sql.BatchUpdateException: (conn=88) Table 'test.users' doesn't exist\r\njava.sql.BatchUpdateException: (conn=88) Table 'test.users' doesn't exist\r\njava.sql.SQLSyntaxErrorException: (conn=88) Table 'test.users' doesn't exist\r\n\r\n\tat io.confluent.connect.jdbc.sink.JdbcSinkTask.getAllMessagesException(JdbcSinkTask.java:165)\r\n\tat io.confluent.connect.jdbc.sink.JdbcSinkTask.put(JdbcSinkTask.java:111)\r\n\t... 11 more\r\n"
발생 이유: 점('.')을 사용할 경우, Kafka Connect가 이를 테이블 이름과 컬럼 이름을 구분하는 구분자로 해석할 수 있으며, 이로 인해 실제 데이터베이스에 존재하지 않는 테이블 이름으로 인식되어 오류가 발생할 수 있다.
해결 방안: 점('.') 대신에 Kafka Topic 이름에 다른 연결자를 사용하거나, Kafka Connect의 설정을 조정하여 올바른 테이블 이름을 인식하도록 할 수 있다.
"org.apache.kafka.connect.errors.ConnectException: Error while attempting to create/find topic(s) 'ecommerce.users'\r\n\tat org.apache.kafka.connect.util.TopicAdmin.createOrFindTopics(TopicAdmin.java:427)\r\n\tat org.apache.kafka.connect.runtime.WorkerSourceTask.maybeCreateTopic(WorkerSourceTask.java:431)\r\n\tat org.apache.kafka.connect.runtime.WorkerSourceTask.sendRecords(WorkerSourceTask.java:365)\r\n\tat org.apache.kafka.connect.runtime.WorkerSourceTask.execute(WorkerSourceTask.java:257)\r\n\tat org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:188)\r\n\tat org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:243)\r\n\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)\r\n\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)\r\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)\r\n\tat java.base/java.lang.Thread.run(Thread.java:842)\r\nCaused by: java.util.concurrent.ExecutionException: org.apache.kafka.common.errors.InvalidTopicException: Topic 'ecommerce.users' collides with existing topics: ecommerce_users\r\n\tat java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)\r\n\tat java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)\r\n\tat org.apache.kafka.common.internals.KafkaFutureImpl.get(KafkaFutureImpl.java:165)\r\n\tat org.apache.kafka.connect.util.TopicAdmin.createOrFindTopics(TopicAdmin.java:387)\r\n\t... 10 more\r\nCaused by: org.apache.kafka.common.errors.InvalidTopicException: Topic 'ecommerce.users' collides with existing topics: ecommerce_users\r\n"
발생 이유: Kafka에서는 Topic 이름에 밑줄('')과 점('.')을 혼용하는 것이 허용되지 않을 뿐만 아니라, 이 두 기호는 서로 대체될 수 있어 이름 충돌을 일으킬 수 있다. 예를 들어, 'ecommerce.users'와 'ecommerce_users'는 서로 다른 Topic으로 의도될 수 있지만, Kafka 내부에서는 이를 동일한 Topic으로 간주하여 충돌 오류가 발생다.
해결 방안: Topic 이름을 명명할 때는 밑줄('')과 점('.') 중 하나만 선택하여 일관성 있게 사용하는 것이 중요하다.
전체적으로 데이터 베이스와 관련해서 오류가 발생하는 모습이다. 해당 규칙을 정하기 위해서 데이터 베이스 네이밍 규칙에 대해서도 다시 공부해보았고, 좋은 게시글을 찾아 아래 링크를 통해 공유하겠다.
오류에 대해서 해결 방안들을 정리하기는 했으나. 가장 좋은 방법은 해당 연결자들을 사용하지 않는 것이라고 생각한다. 그래서 현재의 지식으로는 '__' 을 연결자로 고정적으로 지정하여 사용하려고 한다. 또한 데이터베이스 Table Name 규칙에서도 단어와 단어 사이는 해당 연결자를 이용하여 구성한다고 되어있다.