canal本质就是"冒充"从库,通过订阅mysql bin-log来获取数据库的更改信息。

mysql配置(my.cnf)

mysql需要配置my.cnf开启bin-log日志并且将bin-log日志格式设置为row, 同时为了防止bin-log日志占用过多磁盘,可以设置一下过期时间,

[mysqld]
log-bin=mysql-bin # 打开binlog
binlog-format=ROW # ROW格式
server_id=1 # mysql Replication 需要设置 在mysql集群里唯一 expire_logs_days=7 # binlog文件保存7天
max_binlog_size = 500m # 每个binlog日志文件大小

canal配置

除了kafka之外,canal还支持将数据库修改的消息投递到rocketMQ, 或者不经过消息队列直接投递到canal的客户端,然后再在客户端实现自己的代码(如写入其他存储/其他消息队列) ,但是只能选其一。而如果选择canal客户端的方式, 一个canal server也只能将消息投递到一个canal client。

但是可以开启多个canal服务端和客户端(同一个实例,即对mysql来说只算是一个从库), 他们通过zookeeper保证只有一个服务端和客户端是有效的,其他只是作为HA的冗余。

然后需要修改canal目录下(以下为近最小配置)

conf/example/instance.properties

## mysql serverId
canal.instance.mysql.slaveId = 1234 # 数据库address
canal.instance.master.address = 127.0.0.1:3306 # 数据库账号密码
canal.instance.dbUsername = canal
canal.instance.dbPassword = canal # 需要订阅的数据库.表名 默认全部
canal.instance.filter.regex = .\*\\\\..\* # 去掉转义符其实就是 .*\..* # topic名 固定
canal.mq.topic=canal # 动态topic
# canal.mq.dynamicTopic=mytest,.*,mytest.user,mytest\\..*,.*\\..* # 库名.表名: 唯一主键,多个表之间用逗号分隔
# canal.mq.partitionHash=mytest.person:id,mytest.role:id

其中动态topic 和 主键hash看上去有点难理解,去看其他人的博客找到的解释和例子如下

动态topic

canal 1.1.3版本之后, 支持配置格式:schema 或 schema.table,多个配置之间使用逗号分隔

例子1:test.test 指定匹配的单表,发送到以 test_test为名字的topic上

例子2:.\…* 匹配所有表,每个表都会发送到各自表名的topic上

例子3:test 指定匹配对应的库,一个库的所有表都会发送到库名的topic上

例子4:test.* 指定匹配的表达式,针对匹配的表会发送到各自表名的topic上

例子5:test,test1.test1,指定多个表达式,会将test库的表都发送到test的topic上,test1.test1的表发送到对应的test1_test1 topic上,其余的表发送到默认的canal.mq.topic值

支持指定topic名称匹配, 配置格式:topicName:schema 或 schema.table,多个配置之间使用逗号分隔, 多组之间使用 ; 分隔

例子:test:test,test1.test1;test2:test2,test3.test1 针对匹配的表会发送到指定的topic上

————————————————

版权声明:本文为CSDN博主「BillowX_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_35852328/article/details/87600871

主键

canal 1.1.3版本之后, 支持配置格式:schema.table:pk1^pk2,多个配置之间使用逗号分隔

例子1:test.test:pk1^pk2 指定匹配的单表,对应的hash字段为pk1 + pk2

例子2:.\…:id 正则匹配,指定所有正则匹配的表对应的hash字段为id

例子3:.\…
:pkpkpk 正则匹配,指定所有正则匹配的表对应的hash字段为表主键(自动查找)

例子4: 匹配规则啥都不写,则默认发到0这个partition上

例子5:.\…* ,不指定pk信息的正则匹配,将所有正则匹配的表,对应的hash字段为表名

按表hash: 一张表的所有数据可以发到同一个分区,不同表之间会做散列 (会有热点表分区过大问题)

例子6: test.test:id,.\…* , 针对test的表按照id散列,其余的表按照table散列

注意:大家可以结合自己的业务需求,设置匹配规则,多条匹配规则之间是按照顺序进行匹配(命中一条规则就返回)

————————————————

版权声明:本文为CSDN博主「BillowX_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_35852328/article/details/87600871

最后实现消费kafka上canal topic上消息的代码

这里以go为例,可以写入到elasticsearch/redis/其他

package main

import (
"bytes"
"context"
"encoding/json"
"fmt"
"github.com/Shopify/sarama"
"github.com/elastic/go-elasticsearch/esapi"
"github.com/elastic/go-elasticsearch/v6"
"os"
) var esClient *elasticsearch.Client func init() {
var err error
config := elasticsearch.Config{}
config.Addresses = []string{"http://127.0.0.1:9200"}
esClient, err = elasticsearch.NewClient(config)
checkErr(err)
} type Msg struct {
Data []struct {
Id string `json:"id"`
A string `json:"a"`
} `json:"data"`
Type string `json:"type"`
DataBase string `json:"database"`
Table string `json:"table"`
} func checkErr(err error) {
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
} type Consumer struct{} func (c *Consumer) Setup(sarama.ConsumerGroupSession) error {
return nil
} func (c *Consumer) Cleanup(sarama.ConsumerGroupSession) error {
return nil
} func (consumer *Consumer) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
for message := range claim.Messages() {
// fmt.Printf("Message claimed: value = %s, timestamp = %v, topic = %s", string(message.Value), message.Timestamp, message.Topic)
msg := &Msg{}
err := json.Unmarshal(message.Value, msg)
checkErr(err)
if msg.DataBase == "test" && msg.Table == "tbltest" {
if msg.Type == "INSERT" {
for k, _ := range msg.Data {
// 写elasticsearch 逻辑
body := map[string]interface{}{
"id": msg.Data[k].Id,
"a": msg.Data[k].A,
}
jsonBody, _ := json.Marshal(body)
req := esapi.IndexRequest{
Index: msg.DataBase,
DocumentID: msg.Table + "_" + msg.Data[k].Id,
Body: bytes.NewReader(jsonBody),
}
res, err := req.Do(context.Background(), esClient)
checkErr(err)
fmt.Println(res.String())
res.Body.Close()
session.MarkMessage(message, "")
}
}
}
}
return nil
} func main() {
consumer := &Consumer{} config := sarama.NewConfig()
config.Version = sarama.MaxVersion
client, err := sarama.NewConsumerGroup([]string{"127.0.0.1:9092"}, "tg", config)
checkErr(err)
ctx := context.Background() client.Consume(ctx, []string{"canal"}, consumer)
}

canal+kafka订阅Mysql binlog将数据异构到elasticsearch(或其他存储方式)的更多相关文章

  1. 基于Spark Streaming + Canal + Kafka对Mysql增量数据实时进行监测分析

    Spark Streaming可以用于实时流项目的开发,实时流项目的数据源除了可以来源于日志.文件.网络端口等,常常也有这种需求,那就是实时分析处理MySQL中的增量数据.面对这种需求当然我们可以通过 ...

  2. Canal实时解析mysql binlog数据实战

    一.说明 通过canal实时监听mysql binlog日志文件的变化,并将数据解析出来 二.环境准备 1.创建maven项目并修改pom.xml配置文件 <dependencies> & ...

  3. Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~

    导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...

  4. mysql binlog恢复数据实战

    在前面,我们了解了mysql binlog日志的作用以及使用方法:  http://www.php20.cn/article/237 在后面讲到了,可以通过binlog进行恢复数据,那么,具体步骤是怎 ...

  5. 利用flume+kafka+storm+mysql构建大数据实时系统

    架构图

  6. MySql binlog恢复数据

    1. 直接导入数据库 mysqlbinlog --database=testdb mysql-bin. | mysql -uroot -f 2. 导出成SQL文 (1) 从binlog输出为SQL m ...

  7. MySQL Binlog与数据变更

    如果对满足WHERE条件数据执行UPDATE,而UPDATE未导致前后数据发生变化,这种情况下会产生二进制日志么? ========================================== ...

  8. Canal:同步mysql增量数据工具,一篇详解核心知识点

    老刘是一名即将找工作的研二学生,写博客一方面是总结大数据开发的知识点,一方面是希望能够帮助伙伴让自学从此不求人.由于老刘是自学大数据开发,博客中肯定会存在一些不足,还希望大家能够批评指正,让我们一起进 ...

  9. 使用canal增量同步mysql数据库信息到ElasticSearch

    本文介绍如何使用canal增量同步mysql数据库信息到ElasticSearch.(注意:是增量!!!) 1.简介 1.1 canal介绍 Canal是一个基于MySQL二进制日志的高性能数据同步系 ...

随机推荐

  1. 52、Spark Streaming之输入DStream之基础数据源以及基于HDFS的实时wordcount程序

    一.概述 1.Socket:之前的wordcount例子,已经演示过了,StreamingContext.socketTextStream() 2.HDFS文件 基于HDFS文件的实时计算,其实就是, ...

  2. 微信小程序 Flex局部元素被挤压问题

    关于Flex布局不在此处赘述,需要了解的可以查阅官方文档:基本的布局方法——Flex布局 当使用Flex布局,想实现如下图1的效果时,代码编写如下: 图1: <!-- wxml文件 --> ...

  3. Eclipse安装jbpm插件

    1.1   eclipse mar 和neon有什么区别? Eclipse 是一个开放源代码的.基于Java的可扩展开发平台.就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境. . ...

  4. Lomok @Data使用

    看了廖师兄的Springboot视频发现很多很好玩的小工具,lombok就是其中一个.lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具,简单来 ...

  5. 20189220 余超《Linux内核原理与分析》第六周作业

    系统调用的三层机制 实验过程 1.克隆MenuOS rm menu -rf //强制删除当前menu git clone http://git.shiyanlou.com/mengning/menu. ...

  6. 010 @ControllerAdvice

    一:说明 1.说明 这个注解是用于写一个异常捕获的处理类. 这里介绍全局捕获异常,自定义异常捕获 2.ps 在这里,顺便写一下基础的自定义异常类,以后方便用于业务异常继承 二:全局异常捕获 1.处理类 ...

  7. Wise Force Deleter 强制删除文件工具

    https://www.xitmi.com/3321.html   Wise Force Deleter v1.49 中文绿色版 强制删除文件工具

  8. Python3基础 list clear 清空列表中的内容

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  9. 网页视频直播、微信视频直播技术解决方案:EasyNVR与EasyDSS流媒体服务器组合之区分不同场景下的直播接入需求

    背景分析 熟悉EasyNVR产品的朋友们都知道,EasyNVR不仅可以独成体系,而且还可以跟其他系列产品相配合,形成各种不同类型的解决方案,满足各种不同应用场景的实际需求.针对很多设备现场没有固定公网 ...

  10. 两种Redis持久化原理的详解

    Redis为持久化提供了两种方式: RDB:在指定的时间间隔能对你的数据进行快照存储. AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据. 本文将通过下面内容的介 ...