canal 监听mysql 、java实现

1: mysql  开启 binglog 
 配置文件路径: vim /etc/mysql/mysql.conf.d/mysqld.cnf
 内容:canal 监听mysql 、java实现_第1张图片

 2:canal  配置

     canal  的相关配置和初始化在github上面有很详细的文档和配置说明,不过我按照配置一直显示bind失败;

因为自己错误的修改了 canal.properties 的  tcp bind  ip为本机(无脑参考个人博客的配合导致)结果就是浪费了一整天时间找各种原因,
参考了无数的相关博客还是失败。 最后还是看官方文档做了参数的配置;
只需要 修改 

canal 监听mysql 、java实现_第2张图片

 启动, ok

查看日志  logs目录下有 canal、example,很好理解,一个是canal 服务的日志,一个是我们定义的实例的日志;

canal:

canal 监听mysql 、java实现_第3张图片

看到红框内容说明启动成功

example:

 canal 监听mysql 、java实现_第4张图片

 看到数据即代表监听到了日志;

java:

 public static void main(String args[]) {
    // 创建链接
    CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("IP",
            11111), "example", "canal", "canal");
    int batchSize = 1000;
    int emptyCount = 0;
    try {
        connector.connect();
        connector.subscribe(".*\\..*");
        connector.rollback();
        int totalEmptyCount = 120;
        while (emptyCount < totalEmptyCount) {
            Message message = connector.getWithoutAck(batchSize); // 获取指定数量的数据
            long batchId = message.getId();
            int size = message.getEntries().size();
            if (batchId == -1 || size == 0) {
                emptyCount++;
                System.out.println("empty count : " + emptyCount);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            } else {
                emptyCount = 0;
                // System.out.printf("message[batchId=%s,size=%s] \n", batchId, size);
                printEntry(message.getEntries());
            }

            connector.ack(batchId); // 提交确认
            // connector.rollback(batchId); // 处理失败, 回滚数据
        }

        System.out.println("empty too many times, exit");
    } finally {
        connector.disconnect();
    }
}

private static void printEntry(List entrys) {
    for (CanalEntry.Entry entry : entrys) {
        if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) {
            continue;
        }

        CanalEntry.RowChange rowChage = null;
        try {
            rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
        } catch (Exception e) {
            throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),
                    e);
        }

        CanalEntry.EventType eventType = rowChage.getEventType();
        System.out.println(String.format("================> binlog[%s:%s] , name[%s,%s] , eventType : %s",
                entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
                entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
                eventType));

        for (CanalEntry.RowData rowData : rowChage.getRowDatasList()) {
            if (eventType == CanalEntry.EventType.DELETE) {
                printColumn(rowData.getBeforeColumnsList());
            } else if (eventType == CanalEntry.EventType.INSERT) {
                printColumn(rowData.getAfterColumnsList());
            } else {
                System.out.println("-------> before");
                printColumn(rowData.getBeforeColumnsList());
                System.out.println("-------> after");
                printColumn(rowData.getAfterColumnsList());
            }
        }
    }
}

private static void printColumn(List columns) {
    for (CanalEntry.Column column : columns) {
        System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());
    }
}

完全copy的github上源码就可以使用。此前我一直在纠结这个11111到底是canal的端口还是mysql的端口,

最后成功后回头想这是在连接canal 服务当然是canal的默认端口 11111,canal相关的mysql数据库帐号地址 密码 端口 我们已经在instance.properties 文件里配置过了,所以。。哎 自己是个猪脑子,总是用结果推过程,还是不够细心;

然后在监听的数据库操作增删改就会实时打印到控制台

canal 监听mysql 、java实现_第5张图片

这就是我删除掉了字段名为 c1 、c2的一行数据;

更多的关于配置redis、mq的使用因为没有实际的场景需要使用canal暂时我也没去查,不过应该不会难;

总之整个配置超级良心,自己配置坎坷还是因为自己粗心。
人生建议:多看官方文档。

你可能感兴趣的:(canal,mysql,java)