canal数据库binlog监听-核心实现和event事件

binlog监听核心实现

在AbstractEventParser中启动1个parseThread线程做定时(thread线程sleep间隔时间为10-20s, 10000 + RandomUtils.nextInt(10000))从mysql服务器端拉取 binlog日志做处理。

启动监听拉取线程
  1. 配置transaction buffer初始化缓冲队列CanalEntry.Entry[]数组(队列大小默认为1024 byte)

  2. 构造并启动bin log parser的binlogParser
    实例(AbstractMysqlEventParser子类有MysqlEventParser、RdsBinlogEventParserProxy、LocalBinlogEventParser、RdsLocalBinlogEventParser等实现), 核心为构建类 LogEventConvert,做slaver模拟和binlog dump。

  3. 启动parseThread定时sink的线程(while循环,空闲则sleep)

    1. buildErosaConnection构造Erosa连接,即调用socket或netty做数据库tcp连接。
    2. 启动一个心跳线程,保持tcp连接keepAlive不断开,避免重复创建新的socket对mysql服务端带来的压力。
    3. 执行dump前的准备工作
    4. 获取最后的位置信息位点信息EntryPosition position = findStartPosition(erosaConnection)
    5. 定义SinkFunction
    6. 开始dump数据
      1. 支持并发的话,创建multiStageCoprocessor进行多阶段处理
      2. 根据位点信息(GTID模式的话获取gtid;非gtid模式下,有journalName则使用journalName作为位点标识,否则使用时间戳timestamp作为开始位点)dump数据erosaConnection.dump(startPosition.getTimestamp(), multiStageCoprocessor);
      3. 设置请求binlog的命令参数 -> 打开socket网络连接 -> 通过inputStream获取binlog数据二进制量 -> 按binlog格式解析二进制流提取数据库event -> 更新位点(到redis等介质中)

AbstractEventParser#start()启动源码如下

public void start() {
    super.start();
    MDC.put("destination", destination);
    // 配置transaction buffer
    // 初始化缓冲队列
    transactionBuffer.setBufferSize(transactionSize);// 设置buffer大小
    transactionBuffer.start();
    // 构造bin log parser, 构建的类 LogEventConvert
    binlogParser = buildParser();// 初始化一下BinLogParser
    binlogParser.start();
    // 启动工作线程
    parseThread = new Thread(new Runnable() {

      public void run() {
        MDC.put("destination", String.valueOf(destination));
        ErosaConnection erosaConnection = null;
        boolean isMariaDB = false;
        while (running) {
          try {
            // 开始执行replication
            // 1. 构造Erosa连接
            erosaConnection = buildErosaConnection();

            // 2. 启动一个心跳线程
            startHeartBeat(erosaConnection);

            // 3. 执行dump前的准备工作
            preDump(erosaConnection);

            erosaConnection.connect();// 链接

            long queryServerId = erosaConnection.queryServerId();
            if (queryServerId != 0) {
              serverId = queryServerId;
            }

            if (erosaConnection instanceof MysqlConnection) {
              isMariaDB = ((MysqlConnection) erosaConnection).isMariaDB();
            }
            // 4. 获取最后的位置信息
            long start = System.currentTimeMillis();
            logger.warn(
                "---> begin to find start position, it will be long time for reset or first position");
            EntryPosition position = findStartPosition(erosaConnection);
            final EntryPosition startPosition = position;
            if (startPo
  • 35
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值