canal快速搭建(我已为你近乎避掉所有坑)

按照我的步骤来:
首先我们不使用Linux自带的Mysql5.1,需要自己去安装5.7版本(要先卸载5.1),这个版本不需要自己去设置UTF-8了自带(所以不会出现乱码问题)!但5.7版本的密码设置需要自己去谷歌修改方法以及怎样设置简单的密码(也可去看我的其他博文)。
我选择的是canal.deployer-1.1.1.tar.gz(之前的版本配置文件似乎有的地方不一样)
jdk1.8
centOS6.9

1.开启mysql的binlog功能:
vim /etc/my.cnf
尾部添加

#binlog数据中包含server_id,标识该数据是由那个server同步过来的
server-id = 1
#mysql向文件名前缀添加数字后缀来按顺序创建二进制日志文件如mysql-binlog.000006 
log-bin = /var/lib/mysql/mysql-bin
#选择基于行的日志记录方式
binlog_format = ROW

用show variables like ‘bin_log%’;
log_bin为ON即可

2.MySQL 里配置Canal Server权限:
#一定要加SHOW VIEW这个东西,不然后面报错

CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';
GRANT SHOW VIEW, SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;

3.下载canal的压缩包并解压:
官网https://github.com/alibaba/canal/releases
下载 canal.deployer-1.1.1.tar.gz
mkdir /usr/local/canal
下载好的压缩包在上面的目录中解压
tar –zxvf canal.deployer-1.1.1.tar.gz

4.配置修改
在解压好的目录下
vim conf/example/instance.properties

修改这三个地方即可

# mysql serverId,随便设置
canal.instance.mysql.slaveId = 1234

#position info,需要改成自己的数据库信息
canal.instance.master.address = 127.0.0.1:3306

#一定要注释掉下面这个参数,这样就会扫描全库
#canal.instance.defaultDatabaseName = test

5.启动:
sh bin/startup.sh
查看日志:
vim logs/canal/canal.log
有下面的这三句话即表示成功

[main] INFO  com.alibaba.otter.canal.deployer.CanalLauncher - ## start the canal server.
[main] INFO  com.alibaba.otter.canal.deployer.CanalController - ## start the canal server[10.1.29.120:11111]
[main] INFO  com.alibaba.otter.canal.deployer.CanalLauncher - ## the canal server is running now ......

可能第一次打开的时候日志里会出现com.alibaba.druid.pool.DruidDataSource - testWhileIdle is true, validationQuery not set这个错误,不用管,千万别去改其他配置,第二次看就会没有了,一定能启动成功。

6.建一个java程序验证是否搭建好了:
首先第一次我们要:vim conf/canal.properties
找到canal.instance.parser.parallelThreadSize = 16
把这一行的注释符号去掉(java才能成功运行)
然后重启canal:
sh bin/restart.sh

Java maven项目:
pom.xml:

<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.client</artifactId>
    <version>1.1.1</version>
</dependency>

SimpleClient.java:

import java.net.InetSocketAddress;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry.Column;
import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
import com.alibaba.otter.canal.protocol.CanalEntry.EntryType;
import com.alibaba.otter.canal.protocol.CanalEntry.RowChange;
import com.alibaba.otter.canal.protocol.CanalEntry.RowData;
import com.alibaba.otter.canal.protocol.Message;

public class SimpleClient {

    public static void main(String[] args) throws Exception {
        CanalConnector connector = CanalConnectors.newSingleConnector(
                new InetSocketAddress("192.168.56.230", 11111), "example", "", "");

        connector.connect();
        connector.subscribe(".*\\..*");
        connector.rollback();

        while (true) {
            Message message = connector.getWithoutAck(100);
            long batchId = message.getId();
            if (batchId == -1 || message.getEntries().isEmpty()) {
                System.out.println("sleep");
                Thread.sleep(1000);
                continue;
            }
            printEntries(message.getEntries());
            connector.ack(batchId);
        }
    }

    private static void printEntries(List<Entry> entries) throws Exception {
        for (Entry entry : entries) {
            if (entry.getEntryType() != EntryType.ROWDATA) {
                continue;
            }

            RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());
            for (RowData rowData : rowChange.getRowDatasList()) {
                switch (rowChange.getEventType()) {
                case INSERT:
                case UPDATE:
                    System.out.print("UPSERT ");
                    printColumns(rowData.getAfterColumnsList());

                    if ("retl_buffer".equals(entry.getHeader().getTableName())) {
                        String tableName = rowData.getAfterColumns(1).getValue();
                        String pkValue = rowData.getAfterColumns(2).getValue();
                        System.out.println("SELECT * FROM " + tableName + " WHERE id = " + pkValue);
                    }
                    break;

                case DELETE:
                    System.out.print("DELETE ");
                    printColumns(rowData.getBeforeColumnsList());
                    break;

                default:
                    break;
                }
            }
        }
    }

    private static void printColumns(List<Column> columns) {
        String line = columns.stream()
                .map(column -> column.getName() + "=" + column.getValue())
                .collect(Collectors.joining(","));
        System.out.println(line);
    }

}

当在mysql里面进行delete操作时如下,根据程序没操作时输出sleep,当在mysql里执行一个delete指令,则输出:

在这里插入图片描述

  • 3
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
### 回答1: Canal是一个用于MySQL数据同步的工具,当出现“更新数据空指针”错误时,可能是由以下几个原因引起的: 1. 数据库连接问题:Canal无法连接到MySQL数据库,导致同步过程中出现了空指针异常。 2. 数据库配置问题:Canal的配置文件中可能存在错误或者缺少必要的配置信息,导致Canal无法正确地访问数据库。 3. MySQL数据库版本问题:Canal可能无法兼容某些MySQL数据库版本,导致同步出现异常,进而引发空指针异常。 4. Canal本身问题:Canal本身的Bug或者异常,可能导致同步数据时出现空指针异常。 针对以上可能的原因,可以尝试检查Canal的配置文件、MySQL数据库的连接状态、CanalMySQL数据库的版本兼容性等问题,以及检查Canal本身的Bug是否已经得到修复。 ### 回答2: 在编程中,当我们使用指针时,如果我们没有正确初始化或者分配内存给指针,就会发生空指针异常。空指针意味着指针没有指向任何有效的内存地址,这意味着它无法访问数据或执行任何操作。 当我们使用Canal更新数据时,如果我们尚未为指针分配内存或者指针指向了无效的内存地址,就会出现空指针异常。这可能发生在以下情况下: 1. 未初始化指针:如果我们没有为指针分配内存或者没有对其进行初始化操作,指针将是无效的,并且无法访问或更新相关数据。 2. 内存分配失败:在某些情况下,系统可能无法为指针分配所需的内存,导致指针为空并且无法进行数据更新。 3. 引用已释放的内存:如果我们在更新Canal数据之前释放了指针所引用的内存,则指针将变为空,无法再次使用。 为了避免空指针异常,我们需要在使用指针之前始终进行正确的内存分配和初始化操作。此外,我们还应该定期检查指针是否为空,并确保在更新数据之前保持指针有效。 ### 回答3: 在使用canal更新数据时,可能会遇到空指针的问题。空指针是指指针变量没有指向任何内存地址,当程序尝试访问或操作空指针时,就会引发空指针异常。 出现空指针的原因有多种可能。一种常见的情况是程序没有正确初始化指针变量,导致其指向为空。另一种可能是在程序的执行过程中,指针变量原本指向的内存地址被释放或者回收,但程序仍尝试使用这个指针变量来读取或写入数据,就会引发空指针异常。 当使用canal进行数据更新时,如果在更新操作之前没有对相关指针进行正确的初始化或者判断,在执行更新操作时可能会出现空指针异常。例如,如果在更新操作中涉及到了一个空指针所指向的数据,当程序试图访问该空指针的时候,就会引发空指针异常。 为了避免空指针异常,我们可以在进行数据更新前,对相关的指针变量进行合理的判断和初始化。可以使用if语句或者其他方式,判断指针是否为空,若为空,则不执行更新操作,并对此进行处理。另外,可以规范代码编写规范,避免在使用指针时出现潜在的问题。此外,还可以通过使用try-catch语句来捕获空指针异常,并进行相应的处理,以保证程序的正常运行。 总之,空指针异常在使用canal更新数据时可能会出现,出现空指针异常的原因主要是因为指针变量没有正确初始化或者指针指向的内存地址被释放等问题。避免空指针异常的方法包括正确的初始化和判断指针变量,规范的编码规范和使用异常处理等。
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值