首页 > 数据库 >使用 Canal 实时从 MySql 向其它库同步数据

使用 Canal 实时从 MySql 向其它库同步数据

时间:2024-01-20 23:13:26浏览次数:54  
标签:Canal canal 同步 数据库 MySql 实时 server mysql employee

目前绝大多数项目还是采用 mysql 作为数据存储,对于用户访问量较高的网站来说,mysql 读写性能有限,我们通常会把 mysql 中的数据实时同步到 Redis、mongodb、elastic search 等中间件中,应对高并发访问场景,减轻 mysql 压力,防止数据库宕机。在项目开发中,为了不会原有代码进行侵入,采用 canal 中间件实现 mysql 向其它库的实时同步,是一种很不错的方案。

canal 译意为水道/管道/沟渠,主要用途是基于 mysql 数据库增量日志解析,提供增量数据订阅和消费,其工作原理是:模拟 mysql slave 的交互协议,伪装自己为 mysql slave ,向 mysql master 发送 dump 协议,mysql master 收到 dump 请求,开始推送 binary log 给 canal,canal 解析 binary log 提供出对具体表数据的增删改操作内容。

本篇博客将采用 docker-compose 搭建 mysql 和 canal,并采用代码方式演示如果使用 canal 从mysql 中同步数据,监听对数据表的增删改操作。在本篇博客的最后会提供源代码下载。

Canal 的 gitHub 地址为:https://github.com/alibaba/canal


一、部署 mysql 和 canal

本篇博客使用虚拟机进行部署,我的虚拟机操作系统是 CentOS7(ip 地址是 192.168.136.128),已经安装好了 docker 和 docker-compose ,首先我们先创建好相关的目录,我创建的主目录是 /app/canal,具体结构如下:

image

在 /app/canal 创建一个 mysql 目录,在 mysql 下创建一个 data 目录,并创建了 mysql 的配置文件 my.cnf

首先列出 mysql 的配置文件 my.cnf 的内容,主要配置是开启 binlog 日志:

[mysqld]

# 开启 binlog
log-bin=mysql-bin

# canal 需要使用 ROW 模式
binlog-format=ROW

# 如果你只想同步部分数据库的话,可以进行如下配置
# 如果同步多个数据库的话,可以配置多行。
# 如果不配置的话,默认是 mysql 所有库都进行同步
# binlog-do-db=canaldb
# binlog-do-db=mytestdb

# 不要和 canal 的 slaveId 重复,mysql 默认是 1
server-id=1

# 数据目录
datadir=/var/lib/mysql

symbolic-links=0
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

然后在 /app/canal 下创建 docker-compose.yml 文件,内容如下:

version: "3.5"
services:
  mysql-server:
    image: mysql:5.7.42
    container_name: mysql-server
    restart: always
    ports:
      - 3306:3306
    volumes:
      # mysql的数据存放目录映射
      - /app/canal/mysql/data:/var/lib/mysql
      # mysql的配置文件映射
      - /app/canal/mysql/my.cnf:/etc/mysql/my.cnf
    environment:
      # mysql的root密码设置
      - MYSQL_ROOT_PASSWORD=root
    networks:
      - canal_net

  canal-server:
    image: canal/canal-server:v1.1.7
    container_name: canal-server
    restart: always
    ports:
      - 11111:11111
    environment:
      # 设置连接 canal 服务的用户名和密码
      - CANAL_ADMIN_USER=admin
      - CANAL_ADMIN_PASSWORD=password
      # 设置 canal 实例的名称
      - canal.destinations=jobs
      # 设置 canal 实例作为 mysql 从库的 server_id
      - canal.instance.mysql.slaveId=100
      # 设置连接 mysql 的地址
      - canal.instance.master.address=mysql-server:3306
      # 设置连接 mysql 的账号密码
      - canal.instance.dbUsername=root
      - canal.instance.dbPassword=root
      # 设置要解析的表(可以使用正则表达式),多个之间配置用英文逗号分隔
      - canal.instance.filter.regex=canaldb.t_employee
    networks:
      - canal_net
    depends_on:
      - mysql-server

  # 网络配置
networks:
  canal_net:
    driver: bridge

然后在 /app/canal 目录下,运行 docker-compose up -d 即可启动 mysql 和 canal 服务。

image

在 canal 服务配置中 canal.instance.filter.regex 用来配置要同步的数据库表,可以配置正则表达式:

多个正则之间以英文逗号分隔,转义符需要使用双斜杠(\\)。常见例子如下:

1. 所有表: .* or .\\..

2. canal 数据库下所有表: canal\\..*

3. canal 数据库下的所有以 canal 开头的表:canal\\.canal.*

4. canal 数据库下的一张表:canal.test1

5. 多个正则表达式组合使用,然后以英文逗号隔开:canal\\..*,mysql.test1,mysql.test2 

我们上面配置的是 canaldb.t_employee ,也就是仅同步 canaldb 数据库下的 t_employee 表,因此在部署完 mysql 之后,需要运行以下 sql 脚本在数据库中简单出该表,并添加一些示例数据:

DROP TABLE IF EXISTS `t_employee`;
CREATE TABLE `t_employee`  (
  `e_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '员工id',
  `e_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '员工姓名',
  `e_age` int(11) NOT NULL DEFAULT 0 COMMENT '员工年龄',
  PRIMARY KEY (`e_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `t_employee` VALUES (1, '任肥肥', 41);
INSERT INTO `t_employee` VALUES (2, '侯胖胖', 42);
INSERT INTO `t_employee` VALUES (3, '乔豆豆', 40);

二、实时同步数据

新建一个 springboot 工程,具体结构如下所示:

image

由于工程代码非常简单,这里就直接进行介绍,先看 pom 文件引用的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.jobs</groupId>
    <artifactId>springboot_canal</artifactId>
    <version>1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.5</version>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
        <!--引入 canal 的 springboot 依赖-->
        <dependency>
            <groupId>top.javatool</groupId>
            <artifactId>canal-spring-boot-starter</artifactId>
            <version>1.2.1-RELEASE</version>
        </dependency>
    </dependencies>
</project>

这里最主要就是引入了 canal-spring-boot-starter 这个依赖,

该依赖包是第三方爱好者提供,github 网址为:https://github.com/NormanGyllenhaal/canal-client

我们需要创建一个实体类,其字段需要与要同步数据的 mysql 数据库表保持一致,具体细节如下:

package com.jobs.pojo;

import lombok.Data;

//注意:
//这里的属性名称,需要与数据库表中的字段名称,保持一致
@Data
public class Employee {

    private Long e_id;

    private String e_name;

    private Integer e_age;

}

然后再开发一个 handler 用于处理从 canal 服务获取到的解析记录(对数据的增删改记录)即可:

package com.jobs.handler;

import com.jobs.pojo.Employee;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;

@CanalTable("t_employee")
@Component
public class EmployeeHandler implements EntryHandler<Employee> {

    @Override
    public void insert(Employee employee) {
        System.out.println("添加了:" + employee);
        //这里可以将数据添加到同步的目标库中,比如 redis 缓存
    }

    @Override
    public void update(Employee before, Employee after) {
        System.out.println("更新前:" + before);
        System.out.println("更新后:" + after);
        //这里可以将数据更新到同步的目标库中,比如 redis 缓存
    }

    @Override
    public void delete(Employee employee) {
        System.out.println("删除了:" + employee);
        //这里可以将数据从同步的目标库中删除掉,比如 redis 缓存
    }
}

最后在工程的 application.yml 文件中配置好连接 canal 服务的信息:

canal:
  # canal 服务部署时,配置的 destination 值,此处要保持一直
  destination: jobs
  # canal服务地址
  server: 192.168.136.128:11111
  # 连接 canal 服务的用户名和密码
  user-name: admin
  password: password

三、验证成果

启动 springboot 工程,然后使用 navcat 连接到 mysql 数据库,对 canaldb 下的表 t_employee 中的记录进行增删改:

首先我们在 mysql 中添加一条新纪录:李墩墩38 岁,然后程序就监听到数据添加事件,控制台打印结果如下:

image

然后我们在 mysql 中修改李墩墩的数据,修改为蔺赞赞36岁,然后程序就监听到数据修改事件,控制台打印结果如下:

image

最后我们在 mysql 中删除任肥肥这条记录,然后程序就监听到数据修改事件,控制台打印结果如下:

image

本篇博客的 Demo 代码,仅仅是把数据打印出来,在实际开发中,大家可以根据自己的业务,进行相应的操作。


到此为止使用 Canal 服务从 mysql 实时同步数据的内容已经介绍完毕,大家可以下载源代码自行体验:

本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/springboot_canal.zip

标签:Canal,canal,同步,数据库,MySql,实时,server,mysql,employee
From: https://www.cnblogs.com/studyjobs/p/17977308

相关文章

  • mysql中的各种索引大总结
    文章目录为啥不用二叉搜索树?为啥不用平衡二叉(avl)树?为啥不用b-树?为啥用b+树?(重点)索引聚簇索引聚簇索引的局限聚集的数据的优点非聚簇索引介绍组合索引覆盖索引前缀索引前缀索引选择算法全文索引hash索引b-tree索引自适应哈希索引小咸鱼的技术窝b-tree索引使用的是b+树的数据结构,树......
  • 深度了解mysql事务mvcc实现原理
    一:事务概念:一组原子性的sql查询语句,也可以看作是一个工作单元特点:要么全部执行成功,要么全部执行失败一个有效的事务需满足的条件(ACID)原子性(Atomicity)一个事务必须被视为一个单独的内部最小的,”不可分“的工作单元,以确保事务要么全部执行,要么全部执行失败,当一个事务具有原子性的时候......
  • MySQL-13.MySQL约束
    1.约束(constraint)概述1.1为什么需要约束数据完整性(DataIntegrity)是指数据的精确性(Accuracy)和可靠性(Reliability)。它是防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成的无效操作或错误信息而提出的。为了保证数据的完整性,SQL规范以约束的方式对表数据......
  • 云计算-http实时通讯
    短链接请求示例在HTTP/1.0中,默认使用的是短连接。如果需要使用长连接:通过Connection:Keep-alive来实现长连接。浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web资源,如JavaScript文件、图......
  • 数据库学习笔记(二)—— MySQL 之 存储引擎和索引篇
    存储引擎和索引 前言关于MySQL的学习着实有些混乱,虽然才到学习笔记二,但学习笔记四都已经写完了,其他写一点,可以说是东一榔头西一棒槌;写出的东西也不忍直视,省略了很多细节,还基本上都是到处搬运的,可即便是搬运,也都绞尽脑汁了。网上的知识大多都模糊不清,甚至还错误百出,为了......
  • 将MySQL数据库数据转换为PGSQL数据库 --- 实操可以
    利用navicate,傻瓜操作即可。选中要迁移的数据库,用navicate上面的工具,数据传输,传输到要迁移的数据库(可以在不同的连接之间传输的)https://huaweicloud.csdn.net/63356c9ed3efff3090b5653e.html......
  • MySQL三大范式
    MySQL三大范式数据库设计的三范式(NormalForm)是一组关于关系数据库设计的规范,目的是为了减少冗余数据、提高数据存储的效率,并确保数据的一致性。三范式分为以下三个层次:第一范式(1NF):表中每列的属性不可再分数据表中的每一列都是不可再分的基本数据项,而且在每个记录中的每一列都......
  • 【MySQL 8+】CRUD等操作修改数据库的表后,数据库中表相关信息与数据库工具所展示的信息
    相关转载:①mysql8.0数据库中表的行数不显示,大小也不显示_-CSDN问答②MySQL8.0存储表的行数和修改日期不自动更新的问题_mysql表插入数据,但是修改日期无值-CSDN博客=============================================================个人总结:本人一开始上手的就是MySQL8+的版......
  • 盘点编写 sql 上的那些骚操作(针对mysql而言)
    前言咋说呢,最近交接了一个XXX统计系统到我手上,点进去系统主页,看了下实现了哪些功能,页面看着很简单就那么几个统计模块,本来想着就那么几张报表的crud来着,看了下代码也还好体量也不大,于是乎美滋滋的随波逐流了,后来出现了一个bug说什么数据统计的不对,想着快速给他改掉,顺着控制层,一路摸......
  • MYSQL-数据表基本
    1、创建表createtable表名(列名类型是否可以为空,列名类型是否可以为空)ENGINE=InnoDBDEFAULTCHARSET=utf82、删除表droptable表名3、清空表deletefrom表名truncatetable表名4、修改表添加列:altertable表名add列名类型删除列:alter......