使用MySQL的Binlog来同步数据到ES当中

一、技术选型与核心原理

  1. 核心组件

    MySQL Binlog :ROW模式记录数据变更事件(INSERT/UPDATE/DELETE),提供原子性变更流

    Canal/OpenReplicator :伪装MySQL Slave订阅Binlog(本文以Canal 1.1.6为例)

    Kafka :作为消息中间件解耦数据管道,提供削峰填谷能力

    Elasticsearch High Level REST Client:官方推荐写入接口,支持批量提交和重试策略

  2. 同步原理

    复制代码
    MySQL Server → Binlog → Canal Server → Kafka → Consumer → ES Bulk API

    伪装从库 :Canal通过MySQL Slave协议订阅Binlog

    数据路由 :通过Kafka Topic实现分表分索引路由

    最终一致性:通过ACK机制和死信队列保障数据可靠性


二、环境准备与配置

1. MySQL配置(关键步骤)
ini 复制代码
# my.cnf 配置(需重启MySQL)
[mysqld]
server_id = 1
log_bin = /var/lib/mysql/mysql-bin.log
binlog_format = ROW        # 必须为ROW模式
expire_logs_days = 7       # 避免日志膨胀
binlog_row_image = FULL    # 记录完整行数据
gtid_mode = ON             # 启用GTID(高可用场景)
2. Canal Server部署
bash 复制代码
# 下载Canal 1.1.6并解压
wget https://github.com/alibaba/canal/releases/download/canal-1.1.6/canal.deployer-1.1.6.tar.gz

# 配置conf/canal.properties
canal.serverMode = kafka     # 输出到Kafka
kafka.bootstrap.servers = 192.168.1.100:9092
canal.mq.topic=canal_topic   # 按表名动态路由

# 配置conf/example/instance.properties
canal.instance.master.address=192.168.1.101:3306
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.filter.regex=.*\\..*  # 监控所有库表

三、数据管道搭建

1. Kafka Topic规划
Topic名称 分区数 副本数 用途
canal_raw 12 3 原始Binlog事件
es_sync 12 3 已处理的ES文档事件
2. 消费者程序设计(Java示例)
java 复制代码
// 使用Spring Kafka消费并转换数据
@KafkaListener(topics = "canal_raw")
public void syncToES(ConsumerRecord<String, String> record) {
    CanalMessage message = JSON.parseObject(record.value(), CanalMessage.class);
    
    // 转换逻辑
    List<IndexRequest> requests = message.getData().stream()
        .map(row -> {
            IndexRequest request = new IndexRequest("index_name");
            request.id(row.get("id")); // 基于主键幂等
            request.source(row);
            return request;
        }).collect(Collectors.toList());
    
    // 批量写入ES(Bulk API)
    BulkRequest bulkRequest = new BulkRequest();
    requests.forEach(bulkRequest::add);
    esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
}

关键优化点

• 批量提交:每500条或1秒间隔触发Bulk操作

• 重试策略:指数退避重试 + 死信队列记录失败数据


四、数据建模与映射

1. 关系型到文档型转换
json 复制代码
// MySQL表结构
CREATE TABLE user (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  tags JSON  # 需要展平为ES嵌套对象
);

// ES Mapping定义
PUT /user
{
  "mappings": {
    "properties": {
      "id": {"type": "keyword"},
      "name": {"type": "text", "fields": {"keyword": {"type": "keyword"}}},
      "tags": {
        "type": "nested",  # 处理嵌套结构
        "properties": {
          "tag_name": {"type": "keyword"},
          "create_time": {"type": "date"}
        }
      }
    }
  }
}
2. 同步策略
操作类型 处理逻辑
INSERT 直接生成IndexRequest
UPDATE 根据_id生成UpdateRequest
DELETE 生成DeleteRequest(软删除需特殊处理)

五、高可用与监控

  1. 容灾设计

    Canal集群 :通过ZooKeeper选举Leader

    Kafka消费者 :Consumer Group自动Rebalance

    ES写入:采用跨AZ副本 + 自动故障转移

  2. 监控指标

    bash 复制代码
    # Prometheus监控项
    canal_binlog_lag_seconds  # 同步延迟
    kafka_consumer_lag_total  # 消费堆积
    es_indexing_rate          # 写入吞吐
  3. 报警策略

    • Binlog延迟 > 60s

    • 消费堆积 > 10,000条

    • ES Bulk失败率 > 1%


六、扩展性设计

  1. 分库分表同步

    • 通过Canal的canal.instance.filter.regex按正则匹配库表

    • 在Kafka中使用Dynamic Topic Routing(按库表名生成Topic)

  2. 数据清洗中间件

    python 复制代码
    # 使用Flink处理复杂ETL
    env.addSource(KafkaSource())
      .map(parseCanalMessage)
      .filter(lambda x: x['status'] == 'VALID')  # 数据清洗
      .keyBy(lambda x: x['user_id'])
      .window(TumblingProcessingTimeWindows.of(Time.seconds(10)))
      .reduce(mergeDuplicateEvents)  # 去重
      .sinkTo(ElasticsearchSink())

七、故障恢复与数据校验

  1. 断点续传

    • Canal Server持久化Binlog Position到ZooKeeper

    • Kafka Consumer手动提交Offset

  2. 全量+增量初始化

    bash 复制代码
    # 全量同步流程
    mysqldump --single-transaction > dump.sql
    python transform_to_es_bulk.py dump.sql | es_loader
  3. 数据一致性校验

    • 使用Elasticsearch _stats API对比MySQL COUNT

    • 通过checksum比对抽样数据


八、性能压测建议

  1. 基准测试场景

    • 单线程写入 vs 多线程Bulk

    • 不同Bulk Size对吞吐影响(建议256-2048条/批次)

    • ES Refresh Interval调优(从1s调整到30s)

  2. 硬件规格参考

    组件 QPS 1万 QPS 10万
    Canal Server 4C8G 8C16G + 独立部署
    Kafka 3节点 4C8G 6节点 8C32G
    ES集群 3节点 8C32G 6节点 16C64G

通过该方案可实现毫秒级延迟的数据同步,在日均亿级数据量的生产环境中验证过稳定性。建议在预发布环境进行全链路压测,根据实际业务特征调整参数。

相关推荐
身如柳絮随风扬1 小时前
MySQL核心知识
数据库·mysql
551只玄猫2 小时前
【数据库原理 实验报告1】创建和管理数据库
数据库·sql·学习·mysql·课程设计·实验报告·数据库原理
q5431470872 小时前
MySQL SQL100道基础练习题
数据库·mysql
zhoupenghui1683 小时前
mysql 中如果条件where中有or,则要求or两边的字段都必须有索引,否则不能用到索引, 为什么?
数据库·mysql·索引
eggwyw4 小时前
完美解决phpstudy安装后mysql无法启动
数据库·mysql
java修仙传4 小时前
MySQL 事务隔离级别详解
数据库·mysql·oracle
Irissgwe4 小时前
MySQL存储过程和触发器专题
数据库·mysql·oracle
skiy7 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
创世宇图7 小时前
Alibaba Cloud Linux 安装生产环境-mysql
linux·mysql
重庆小透明8 小时前
【搞定面试之mysql】第一篇:mysql的优化和索引
mysql·面试·职场和发展