【Canal】Canal學習筆記

目錄

一、Canal 介紹

1.1 Canal 概述

1.2 Canal 原理

二、Canal 安裝和使用

2.1 mysql 準備

2.1.1 開啓 mysql 的 binlog 模式

2.1.2 創建同步賬號

2.1.3 重啓 mysql 容器

2.2 Canal 容器安裝和使用

2.2.1 下載鏡像和安裝

2.2.2 Canal 配置

2.3 Canal 微服務搭建

2.3.1 安裝 Canal 開源項目到本地 maven 倉庫

2.3.3 創建 CanalDataEventListerner.java :

2.3.4 新建啓動類

2.3.5 編寫微服務配置文件

2.4 測試


一、Canal 介紹

1.1 Canal 概述

Canal是阿里巴巴旗下的一款開源項目,純Java開發。基於數據庫增量日誌解析,提供增量數據訂閱&消費。

簡單來說就是用來監控數據庫數據的變化,從而獲得新增數據或修改數據的項目框架,目前主要支持了MySQL。

 

1.2 Canal 原理

原理:

  • canal 模擬 mysql slave 的交互協議,僞裝自己爲 mysql slave, 向mysql master 發送 dump 協議
  • mysql master 收到 dump 請求,開始推送 binary log 給 slave(即 canal)
  • canal 解析 binary log 對象(原始爲byte流)

由於 canal是基於mysql的主從模式實現的,所以必須先開啓 binlog

 

二、Canal 安裝和使用

2.1 mysql 準備

2.1.1 開啓 mysql 的 binlog 模式

由於 mysql 是使用 docker 部署的,進入 docker 修改 mysql 的配置

# 進入 mysql 的 docker 容器內
docker exec -it mysql /bin/bash

# 進入 mysql 對應的配置文件
cd /etc/mysql/mysql.conf.d

# 修改配置文件
vim mysqld.cnf

  

log-bin=/var/lib/mysql/mysql-bin # 指定日誌文件存儲的位置
server-id=12345 # 當前這個mysql數據庫的唯一標識

 

2.1.2 創建同步賬號

由於 Canal 要進入 mysql 讀取數據,出於安全考慮,需要對 Canal 創建用戶並賦予權限

# 創建賬號 %表示能在任意機器登錄  by 'xxx' 表示密碼爲canal
create user canal@'%' IDENTIFIED by 'canal';


# 授權 依次爲:查詢權限、主從複製權限、主從複製客戶端權限、超級權限 
# *.*  表示 任意數據庫.任意表  都擁有相關權限
# 結合表示: 任意機器上以canal賬號登錄的用戶對mysql中任意數據庫和任意表都擁有上述權限
GRANT SELECT, PEPLICATION SLAVE, REPLICATION CLIENT, SUPER ON *.* TO 'canal'@'%'';

# 刷新數據庫
FLUSH PRIVILEGES;

 

2.1.3 重啓 mysql 容器

docker restart canal

 

2.2 Canal 容器安裝和使用

2.2.1 下載鏡像和安裝

# 下載鏡像
docker pull docker.io/canal/canal-server

# 安裝
docker run -p 11111:11111 --name canal -d docker.io/canal/canal-server
#-p 端口映射

2.2.2 Canal 配置

進入 Canal 容器

# 進入 canal 容器
docker exec -it canal /bin/bash

# 進入配置文件夾
cd /home/admin/canal-server/conf

  

修改 Canal 的數據庫唯一標識,改成唯一的

  

修改同步配置

vi ./example/instance.properties

  

  

  

  

 

2.3 Canal 微服務搭建

2.3.1 安裝 Canal 開源項目到本地 maven 倉庫

在搭建 Canal 時使用了一個開源項目,實現了 Springboot 和 Canal 的集成。

https://github.com/chenqian56131/spring-boot-starter-canal

搭建:

找到項目目錄,使用命令安裝到本地 maven 倉庫

mvn install

    

  

 

2.3.2 創建微服務項目

創建 maven 項目,並加入依賴

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!--   canal依賴     -->
    <dependency>
        <groupId>com.xpand</groupId>
        <artifactId>starter-canal</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

 

2.3.3 創建 CanalDataEventListerner.java :

package com.changgou.canal;

import com.alibaba.otter.canal.protocol.CanalEntry;
import com.changgou.content.feign.ContentFeign;
import com.xpand.starter.canal.annotation.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

/**
 * 實現mysql數據監聽
 */
@CanalEventListener
@Slf4j
public class CanalDataEventListener222 {

    @Autowired
    private ContentFeign contentFeign;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * @InsertListenPoint 增加監聽
     * @param eventType 當前操作的類型: 增加數據
     * @param rowData 發生變更的一行數據
     */
    @InsertListenPoint
    public void onEventInsert(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
        for (CanalEntry.Column column : rowData.getAfterColumnsList()) {
            log.info("增加: 列名:" + column.getName() + "------ 變更的數據:" + column.getValue());
        }
    }

    /**
     * @UpdateListenPoint 修改監聽
     * @param eventType 當前操作的類型: 增加數據
     * @param rowData 發生變更的一行數據
     */
    @UpdateListenPoint
    public void onEventUpdate(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
        log.info("===================================================================================");
        for (CanalEntry.Column column : rowData.getBeforeColumnsList()) {
            log.info("修改前: 列名:" + column.getName() + "------ 變更的數據:" + column.getValue());
        }
        log.info("===================================================================================");
        for (CanalEntry.Column column : rowData.getAfterColumnsList()) {
            log.info("修改後: 列名:" + column.getName() + "------ 變更的數據:" + column.getValue());
        }
    }

    /**
     * @DeleteListenPoint 刪除監聽
     * @param eventType 當前操作的類型: 增加數據
     * @param rowData 發生變更的一行數據
     */
    @DeleteListenPoint
    public void onEventDel(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
        for (CanalEntry.Column column : rowData.getBeforeColumnsList()) {
            log.info("刪除前:列名:" + column.getName() + "------ 變更的數據:" + column.getValue());
        }
    }

    /**
     * @ListenPoint 自定義監聽
     * @param eventType 當前操作的類型: 增加數據
     * @param rowData 發生變更的一行數據
     */
    @ListenPoint(
            destination = "example", // 指定Canal實例的地址
            schema = {"changgou_content"}, // 指定監聽的數據庫
            table = {"tb_content", "tb_content_category"}, // 指定監控的表
            eventType = {
                    CanalEntry.EventType.DELETE,
                    CanalEntry.EventType.UPDATE,
                    CanalEntry.EventType.INSERT} // 監聽類型
    )
    public void onEventCustomUpdate(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
        for (CanalEntry.Column column : rowData.getBeforeColumnsList()) {
            log.info("自定義操作前: 列名:" + column.getName() + "------ 變更的數據:" + column.getValue());
        }
        for (CanalEntry.Column column : rowData.getAfterColumnsList()) {
            log.info("自定義操作後: 列名:" + column.getName() + "------ 變更的數據:" + column.getValue());
        }
    }
}

 

2.3.4 新建啓動類

import com.xpand.starter.canal.annotation.EnableCanalClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * Canal微服務,監聽數據庫變化並響應
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaClient
@EnableCanalClient
public class CanalApplication {
    public static void main(String[] args) {
        SpringApplication.run(CanalApplication.class, args);
    }
}

 

2.3.5 編寫微服務配置文件

# 192.168.47.142 爲安裝了redis、canal的遠端服務器
server:
  port: 18082
spring:
  application:
    name: canal
  redis:
    host: 192.168.47.142
    port: 6379
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
hystrix:
  command:
    default:
      execution:
        timeout:
          # 若enabled設置爲false,則請求超時交給ribbon控制
          enabled: true
        isolation:
          strategy: SEMAPHORE
canal:
  client:
    instances:
      example:
        host: 192.168.47.142
        port: 11111

 

2.4 測試

項目運行後,修改數據庫即可看到控制檯打印出修改的內容了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章