🎬 HoRain云小助手:个人主页
🔥 个人专栏: 《Linux 系列教程》《c语言教程》
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
专栏介绍
专栏名称 | 专栏介绍 |
本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。 | |
本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制! | |
全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。 | |
本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。 | |
本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。 | |
本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等) |
以下是使用 Canal 同步 MySQL 增量数据到 Elasticsearch(ES)的详细流程及注意事项:
1. Canal 工作原理
Canal 通过模拟 MySQL Slave 协议,从 MySQL Master 读取 binlog 日志并解析,将增量数据(INSERT/UPDATE/DELETE)转换为结构化事件,最终将数据同步到下游存储(如 ES)。
2. 前置条件
2.1 MySQL 配置
- 开启 binlog:确保 MySQL 的
binlog
已开启且为 ROW 模式。# my.cnf [mysqld] log-bin=mysql-bin binlog-format=ROW server-id=1
- 创建 Canal 账户:
CREATE USER 'canal'@'%' IDENTIFIED BY 'canal'; GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%'; FLUSH PRIVILEGES;
2.2 安装 Canal
- 下载 Canal Deployer 包。
- 解压并修改配置:
# conf/canal.properties canal.serverMode = tcp # 使用 TCP 模式 canal.port = 11111 # Canal 服务端口 # conf/example/instance.properties canal.instance.mysql.slaveId=1234 # 唯一 Slave ID canal.instance.master.address=127.0.0.1:3306 canal.instance.dbUsername=canal canal.instance.dbPassword=canal canal.instance.filter.regex=.*\\..* # 监控所有库表
3. 同步到 Elasticsearch
3.1 方案选择
- 自定义开发:编写 Canal 客户端解析数据并写入 ES。
- Canal Adapter:使用官方工具 Canal Adapter 直接配置 ES 映射。
3.2 方案一:自定义客户端开发
步骤 1:引入依赖
<!-- Canal 客户端 -->
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.client</artifactId>
<version>1.1.6</version>
</dependency>
<!-- ES Java Client -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.12.0</version>
</dependency>
步骤 2:Canal 客户端代码
public class CanalToESClient {
public static void main(String[] args) {
// 1. 连接 Canal
CanalConnector connector = CanalConnectors.newSingleConnector(
new InetSocketAddress("127.0.0.1", 11111), "example", "", "");
connector.connect();
connector.subscribe(".*\\..*"); // 订阅所有表
// 2. 监听事件
while (true) {
Message message = connector.getWithoutAck(100); // 批量获取
List<CanalEntry.Entry> entries = message.getEntries();
if (entries.isEmpty()) {
Thread.sleep(1000);
continue;
}
for (CanalEntry.Entry entry : entries) {
if (entry.getEntryType() == CanalEntry.EntryType.ROWDATA) {
CanalEntry.RowChange rowChange = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) {
// 3. 解析事件类型(INSERT/UPDATE/DELETE)
CanalEntry.EventType eventType = rowChange.getEventType();
String tableName = entry.getHeader().getTableName();
List<CanalEntry.Column> columns = eventType == CanalEntry.EventType.DELETE ?
rowData.getBeforeColumnsList() : rowData.getAfterColumnsList();
// 4. 构建 ES 文档
Map<String, Object> doc = new HashMap<>();
for (CanalEntry.Column column : columns) {
doc.put(column.getName(), column.getValue());
}
// 5. 写入 ES
IndexRequest request = new IndexRequest("your_index")
.id(doc.get("id").toString())
.source(doc);
// 使用 ElasticsearchClient 发送请求
elasticsearchClient.index(request);
}
}
}
connector.ack(message.getId()); // 确认消费
}
}
}
步骤 3:处理数据映射
- 字段类型转换:如 MySQL 的
DATETIME
转为 ES 的date
类型。 - 关联数据合并:如多表关联写入同一 ES 文档。
3.3 方案二:使用 Canal Adapter
步骤 1:配置 Adapter
# conf/es7/mytest_user.yml
dataSourceKey: defaultDS # 数据源(对应 application.yml)
destination: example # Canal 实例名
groupId: # 消费组(空表示单机)
esMapping:
_index: "user_index" # ES 索引名
_id: "id" # 文档 ID(对应 MySQL 字段)
sql: "SELECT id, name, age FROM user"
commitBatch: 3000 # 批量提交大小
步骤 2:启动 Adapter
bin/startup.sh
4. 注意事项
- 幂等性:ES 写入需保证幂等(如使用
_id
避免重复插入)。 - 性能优化:
- 批量写入 ES(
bulk
API)。 - 调整 Canal 客户端的
batchSize
和 ES 的刷新间隔。
- 批量写入 ES(
- 数据一致性:
- 监控 Canal 位点(
canal.meta
)确保断点续传。 - 使用事务或消息队列(如 Kafka)解耦 Canal 与 ES。
- 监控 Canal 位点(
- DDL 同步:Canal 默认不处理 DDL,需手动更新 ES 索引映射。
5. 常见问题
Q1:Canal 无法连接 MySQL
- 检查 MySQL 用户权限(需
REPLICATION SLAVE, REPLICATION CLIENT
)。 - 确认
binlog
已开启且为ROW
模式。
Q2:ES 写入延迟高
- 增加 Canal 客户端的批量处理大小(
batchSize
)。 - 优化 ES 索引配置(如分片数、副本数)。
Q3:数据字段类型不匹配
- 在 ES 中预定义索引映射(
mappings
),确保与 MySQL 字段类型兼容。
6. 扩展工具
- Debezium:另一款流行的 CDC 工具,支持多数据库同步到 ES。
- Logstash JDBC Input:通过定时轮询同步增量数据(非实时)。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙