Source Connector 配置:MySQL → Kafka 数据同步
1 ) 动态添加 Connector
-
通过 API 创建
JDBC Source Connector,从 MySQL 表users实时捕获数据变更。 -
关键配置参数:
json{ "name": "mysql-source-users", // Connector 唯一标识 "config": { "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", "connection.url": "jdbc:mysql://192.168.0.140:3306/kafka_study", "connection.user": "root", "connection.password": "123456", "table.whitelist": "users", // 监听的表 "mode": "incrementing", // 增量模式 "incrementing.column.name": "id", // 自增列(用于识别新数据) "topic.prefix": "imc-mysql-", // 生成 Topic 的格式(如 imc-mysql-users) "tasks.max": "1" } } -
执行命令:
bash
curl -X POST http://localhost:8083/connectors \
-H "Content-Type: application/json" \
-d @jdbc-source-config.json
✅ 响应状态码 201 表示创建成功
2 ) 验证数据同步
-
向 MySQL 表
users插入数据:sqlINSERT INTO users (name, age) VALUES ('Allen', 18);- 消费 Kafka Topic 验证数据:
bashkafka-console-consumer --bootstrap-server localhost:9092 \ --topic imc-mysql-users \ --from-beginning -
输出示例:
json{ "schema": { /* Avro Schema */ }, "payload": { "id": 1, "name": "Allen", "age": 18 } }
Sink Connector 配置:Kafka → MySQL 数据回写
1 ) 创建 Sink Connector
-
将 Kafka Topic
imc-mysql-users的数据写入 MySQL 表users_back:json{ "name": "mysql-sink-users-back", "config": { "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", "connection.url": "jdbc:mysql://192.168.0.140:3306/kafka_study", "connection.user": "root", "connection.password": "123456", "topics": "imc-mysql-users", // 监听的 Topic "table.name.format": "users_back", // 目标表 "insert.mode": "upsert", // 写入模式(插入/更新) "pk.mode": "record_key", // 主键模式 "pk.fields": "id" // 主键字段 } } -
执行命令:
bashcurl -X POST http://localhost:8083/connectors \ -H "Content-Type: application/json" \ -d @jdbc-sink-config.json
2 ) 验证回写结果
-
查询 MySQL 表
users_back:sqlSELECT * FROM users_back; -- 应包含与 `users` 相同的数据 -
若更新
users表数据,users_back将自动同步(upsert模式生效)。
Kafka Connect 核心概念解析
1 ) Connector 与 Task
-
Connector:管理数据同步任务的逻辑单元(如
mysql-source-users)。 -
Task:实际执行数据搬运的物理线程,一个 Connector 可启动多个 Task 并行处理。
-
Rebalance 机制:当 Task 故障时,自动将分区分配给健康 Task(如下图所示):
tree[Task1, Task2, Task3] → Task2 故障 → Rebalance → [Task1, Task3]
2 ) Converter 的作用
-
数据格式转换:Source Connector 从 MySQL 读取数据后,需通过 Converter(如
JsonConverter)序列化为 Kafka 兼容格式(如 JSON/Avro)。 -
Sink Connector 的逆过程:将 Kafka 数据反序列化后写入目标库。
-
配置示例:
propertieskey.converter=org.apache.kafka.connect.json.JsonConverter value.converter=org.apache.kafka.connect.json.JsonConverter
3 ) 部署模式对比
| 模式 | Standalone | Distributed |
|---|---|---|
| 适用场景 | 开发/测试 | 生产环境 |
| 高可用 | 不支持 | 支持(多节点故障转移) |
| 扩展性 | 单节点 | 水平扩展 |
生产环境注意事项
1 ) 局限性
- Schema 管理复杂:需配套 Schema Registry 确保数据兼容性。
- 删除数据同步:默认不处理源表删除操作(需自定义逻辑)。
2 ) 替代方案建议
- 复杂场景推荐 Elasticsearch Logstash 或 Debezium,其在 CDC(Change Data Capture)领域更成熟。
工程示例:基于 NestJS 的 Kafka 集成方案
目标:替代 Java 技术栈,提供全链路 NestJS 实现
1 ) 方案 1:NestJS 作为 Kafka 生产者/消费者
typescript
// 安装依赖
npm install @nestjs/microservices kafkajs
// src/kafka/kafka.module.ts
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
@Module({
imports: [
ClientsModule.register([
{
name: 'KAFKA_SERVICE',
transport: Transport.KAFKA,
options: {
client: {
brokers: ['localhost:9092'],
},
consumer: {
groupId: 'nestjs-consumer-group',
},
},
},
]),
],
exports: [ClientsModule],
})
export class KafkaModule {}
// src/user/user.service.ts(生产者示例)
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
import { ClientKafka } from '@nestjs/microservices';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User) private userRepository: Repository<User>,
@Inject('KAFKA_SERVICE') private kafkaClient: ClientKafka,
) {}
async createUser(userData: Omit<User, 'id'>) {
const user = this.userRepository.create(userData);
await this.userRepository.save(user);
// 发送消息到 Kafka
this.kafkaClient.emit('imc-mysql-users', {
key: user.id.toString(),
value: JSON.stringify(user),
});
return user;
}
}
// src/user/user.consumer.ts(消费者示例)
import { Controller } from '@nestjs/common';
import { EventPattern, Payload } from '@nestjs/microservices';
@Controller()
export class UserConsumer {
@EventPattern('imc-mysql-users')
async handleUserEvent(@Payload() message: { value: string }) {
const user = JSON.parse(message.value);
console.log('Received user data:', user);
// 可在此写入 users_back 表
}
}
2 ) 方案 2:NestJS 监控 Kafka Connect API
typescript
// src/connect/connect.service.ts
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
@Injectable()
export class ConnectService {
constructor(private httpService: HttpService) {}
async createConnector(config: object) {
const response = await this.httpService.
post('http://localhost:8083/connectors', config)
.toPromise();
return response.data;
}
async listConnectors() {
const response = await this.httpService.
get('http://localhost:8083/connectors')
.toPromise();
return response.data;
}
}
3 ) 方案 3:自定义 Connector 替代方案(简化版)
适用场景:需灵活控制数据流转逻辑
typescript
// src/task/task-scheduler.service.ts
import { Injectable } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { UserService } from '../user/user.service';
@Injectable()
export class TaskSchedulerService {
constructor(private userService: UserService) {}
@Cron('*/30 * * * * *') // 每 30 秒执行
async syncUsersToBackup() {
const users = await this.userService.findAll();
// 批量写入 users_back 表(省略 ORM 操作)
console.log(`Synced ${users.length} users to backup table`);
}
}
配置优化与周边工具
1 ) Kafka 命令补充
-
查看 Connector 状态:
bashcurl http://localhost:8083/connectors/mysql-source-users/status -
重启 Task:
bashcurl -X POST http://localhost:8083/connectors/mysql-source-users/tasks/0/restart
2 )Schema Registry 集成(确保数据一致性)
yaml
# docker-compose.yml 片段
schema-registry:
image: confluentinc/cp-schema-registry:7.0.1
depends_on: [kafka]
ports: ["8081:8081"]
environment:
SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092
SCHEMA_REGISTRY_HOST_NAME: schema-registry
总结
核心结论:
- Kafka Connect 定位:适用于标准化数据管道(如 MySQL → Kafka → Elasticsearch),但对复杂业务逻辑支持有限。
- NestJS 集成建议:
- 轻量级同步:直接使用
@nestjs/microservices(方案 1) - 大规模迁移:组合 Kafka Connect + NestJS 监控(方案 2)
- 轻量级同步:直接使用
- 生产避坑指南:
- 优先选择 Distributed 模式保障高可用。
- 增量同步时严格验证
incrementing.column.name避免数据丢失。