文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot整合Canal数据同步的方法

2023-06-29 09:39

关注

这篇文章主要介绍“SpringBoot整合Canal数据同步的方法”,在日常操作中,相信很多人在SpringBoot整合Canal数据同步的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot整合Canal数据同步的方法”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

SpringBoot整合Canal数据同步的方法

1、CentOS7编译安装MySQL5.7.24

2、Mysql设置binLog配置

(1)检查binlog功能是否有开启
(2)如果显示状态为OFF表示该功能未开启,开启binlog功能

mysql> show variables like 'log_bin';+---------------+-------+| Variable_name | Value |+---------------+-------+| log_bin | OFF |+---------------+-------+1 row in set (0.00 sec)

1,修改 mysql 的配置文件 my.cnf
vi /etc/my.cnf
追加内容:

log-bin=mysql-bin #binlog文件名binlog_format=ROW #选择row模式server_id=1 #mysql实例id,不能和canal的slaveId重复

2,重启 mysql:
service mysql restart

3,登录 mysql 客户端,查看 log_bin 变量

mysql> show variables like 'log_bin';+---------------+-------+| Variable_name | Value |+---------------+-------+| log_bin | ON|+---------------+-------+1 row in set (0.00 sec)如果显示状态为ON表示该功能已开启

(3)在mysql里面添加以下的相关用户和权限

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

3、Linux下载安装Canal服务

下载地址:
https://github.com/alibaba/canal/releases
(1)下载之后,放到目录中,解压文件

mkdir /usr/local/canalcd /usr/local/canalcanal.deployer-1.1.4.tar.gztar zxvf canal.deployer-1.1.4.tar.gz

(2)修改配置文件
vi conf/example/instance.properties

#需要改成自己的数据库信息canal.instance.master.address=39.106.224.236:3306#需要改成自己的数据库用户名与密码canal.instance.dbUsername=canalcanal.instance.dbPassword=canal#需要改成同步的数据库表规则  #1、同步所有的表canal.instance.filter.regex=.*\\..*  #2、需要同步的那个库中的那个表#canal.instance.filter.regex=guli_ucenter.ucenter_member

mysql 数据解析关注的表,Perl正则表达式.
多个正则之间以逗号(,)分隔,转义符需要双斜杠(\)
常见例子:

(3)进入bin目录下启动

./startup.sh

4、Boot项目中引入依赖

 <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!--mysql-->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>        </dependency>        <dependency>            <groupId>commons-dbutils</groupId>            <artifactId>commons-dbutils</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-jdbc</artifactId>        </dependency>        <dependency>            <groupId>com.alibaba.otter</groupId>            <artifactId>canal.client</artifactId>        </dependency>    </dependencies>

5 、修改properties配置文件

# mysql数据库连接spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8spring.datasource.username=rootspring.datasource.password=123456

6、修改Application启动类

SpringBoot整合Canal数据同步的方法

7、创建Canal配置类自动监听

注意:run()方法中自行修改Linux虚拟机Ip地址后直接使用!

package com.atguigu.canal.client;import com.alibaba.otter.canal.client.CanalConnector;import com.alibaba.otter.canal.client.CanalConnectors;import com.alibaba.otter.canal.protocol.CanalEntry.*;import com.alibaba.otter.canal.protocol.Message;import com.google.protobuf.InvalidProtocolBufferException;import org.apache.commons.dbutils.DbUtils;import org.apache.commons.dbutils.QueryRunner;import org.springframework.stereotype.Component;import javax.annotation.Resource;import javax.sql.DataSource;import java.net.InetSocketAddress;import java.sql.Connection;import java.sql.SQLException;import java.util.List;import java.util.Queue;import java.util.concurrent.ConcurrentLinkedQueue;@Componentpublic class CanalClient {    //sql队列    private Queue<String> SQL_QUEUE = new ConcurrentLinkedQueue<>();    @Resource    private DataSource dataSource;        public void run() {        CanalConnector connector = CanalConnectors.newSingleConnector(new                        InetSocketAddress("39.106.224.236",                11111), "example", "", "");        int batchSize = 1000;        try {            connector.connect();            connector.subscribe(".*\\..*");            connector.rollback();            try {                while (true) {                    //尝试从master那边拉去数据batchSize条记录,有多少取多少                    Message message = connector.getWithoutAck(batchSize);                    long batchId = message.getId();                    int size = message.getEntries().size();                    if (batchId == -1 || size == 0) {                        Thread.sleep(1000);                    } else {                        dataHandle(message.getEntries());                    }                    connector.ack(batchId);                    //当队列里面堆积的sql大于一定数值的时候就模拟执行                    if (SQL_QUEUE.size() >= 1) {                        executeQueueSql();                    }                }            } catch (InterruptedException e) {                e.printStackTrace();            } catch (InvalidProtocolBufferException e) {                e.printStackTrace();            }        } finally {            connector.disconnect();        }    }        public void executeQueueSql() {        int size = SQL_QUEUE.size();        for (int i = 0; i < size; i++) {            String sql = SQL_QUEUE.poll();            System.out.println("[sql]----> " + sql);            this.execute(sql.toString());        }    }        private void dataHandle(List<Entry> entrys) throws            InvalidProtocolBufferException {        for (Entry entry : entrys) {            if (EntryType.ROWDATA == entry.getEntryType()) {                RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());                EventType eventType = rowChange.getEventType();                if (eventType == EventType.DELETE) {                    saveDeleteSql(entry);                } else if (eventType == EventType.UPDATE) {                    saveUpdateSql(entry);                } else if (eventType == EventType.INSERT) {                    saveInsertSql(entry);                }            }        }    }        private void saveUpdateSql(Entry entry) {        try {            RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());            List<RowData> rowDatasList = rowChange.getRowDatasList();            for (RowData rowData : rowDatasList) {                List<Column> newColumnList = rowData.getAfterColumnsList();                StringBuffer sql = new StringBuffer("update " +                        entry.getHeader().getTableName() + " set ");                for (int i = 0; i < newColumnList.size(); i++) {                    sql.append(" " + newColumnList.get(i).getName()                            + " = '" + newColumnList.get(i).getValue() + "'");                    if (i != newColumnList.size() - 1) {                        sql.append(",");                    }                }                sql.append(" where ");                List<Column> oldColumnList = rowData.getBeforeColumnsList();                for (Column column : oldColumnList) {                    if (column.getIsKey()) {//暂时只支持单一主键                        sql.append(column.getName() + "=" + column.getValue());                        break;                    }                }                SQL_QUEUE.add(sql.toString());            }        } catch (InvalidProtocolBufferException e) {            e.printStackTrace();        }    }        private void saveDeleteSql(Entry entry) {        try {            RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());            List<RowData> rowDatasList = rowChange.getRowDatasList();            for (RowData rowData : rowDatasList) {                List<Column> columnList = rowData.getBeforeColumnsList();                StringBuffer sql = new StringBuffer("delete from " +                        entry.getHeader().getTableName() + " where ");                for (Column column : columnList) {                    if (column.getIsKey()) {//暂时只支持单一主键                        sql.append(column.getName() + "=" + column.getValue());                        break;                    }                }                SQL_QUEUE.add(sql.toString());            }        } catch (InvalidProtocolBufferException e) {            e.printStackTrace();        }    }        private void saveInsertSql(Entry entry) {        try {            RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());            List<RowData> rowDatasList = rowChange.getRowDatasList();            for (RowData rowData : rowDatasList) {                List<Column> columnList = rowData.getAfterColumnsList();                StringBuffer sql = new StringBuffer("insert into "+entry.getHeader().getTableName() + " (");                for (int i = 0; i < columnList.size(); i++) {                    sql.append(columnList.get(i).getName());                    if (i != columnList.size() - 1) {                        sql.append(",");                    }                }                sql.append(") VALUES (");                for (int i = 0; i < columnList.size(); i++) {                    sql.append("'" + columnList.get(i).getValue() + "'");                    if (i != columnList.size() - 1) {                        sql.append(",");                    }                }                sql.append(")");                SQL_QUEUE.add(sql.toString());            }        } catch (InvalidProtocolBufferException e) {            e.printStackTrace();        }    }        public void execute(String sql) {        Connection con = null;        try {            if(null == sql) return;            con = dataSource.getConnection();            QueryRunner qr = new QueryRunner();            int row = qr.execute(con, sql);            System.out.println("update: "+ row);        } catch (SQLException e) {            e.printStackTrace();        } finally {            DbUtils.closeQuietly(con);        }    }}

到此,关于“SpringBoot整合Canal数据同步的方法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯