mysql本身是支持主从的(master slave),原理就是master产生的binlog日志记录了所有的增删改语句,将binlog发送到slave节点进行执行即可完成数据的同步。

canal是阿里开源的一个中间件,它就是通过解析binlog来完成数据变更的监听的。

https://github.com/alibaba/canal

可以看到,canal是这样工作的:canal有一个server工程,该server自己伪装为mysql的一个slave节点,然后向master请求所有的变更日志。同时canal有一个client工程,通过添加client的sdk,我们就可以在项目里监听到server端传来的数据变更信息,从而达到监听数据变化的目的。

安装配置canal

在这里https://github.com/alibaba/canal/releases,下载canal releases包,如https://github.com/alibaba/canal/releases/download/canal-1.0.22/canal.deployer-1.0.22.tar.gz。

这个就是server端,下载后解压,如图

打开conf/example下的instance.properties文件,编辑#################################################

## mysql serverId

canal.instance.mysql.slaveId = 1234

# position info

canal.instance.master.address = 127.0.0.1:3306

canal.instance.master.journal.name =

canal.instance.master.position =

canal.instance.master.timestamp =

#canal.instance.standby.address =

#canal.instance.standby.journal.name =

#canal.instance.standby.position =

#canal.instance.standby.timestamp =

# username/password

canal.instance.dbUsername = canal

canal.instance.dbPassword = canal

canal.instance.defaultDatabaseName = test

canal.instance.connectionCharset = UTF-8

# table regex

canal.instance.filter.regex = .*\\..*

# table black regex

canal.instance.filter.black.regex =

#################################################

address设置为mysql的连接地址,defaultDatabaseName设置为自己要监听的库名,如test。

在mysql命令行,创建一个新用户,作为slaveCREATE USER canal IDENTIFIED BY 'canal';

GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';

-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;

FLUSH PRIVILEGES;

对应配置文件里的canal用户。到此配置完毕。

执行bin目录下的startup.sh

启动后可以在logs目录下查看日志。在example目录下的example.log,如果没有报错,说明启动成功。

canal客户端编写

服务端启动完毕后,在客户端即可监听test库的变化。

新建一个java maven项目,pom.xml里添加依赖

com.alibaba.otter

canal.client

1.0.12

package com.mindata;

import com.alibaba.otter.canal.client.CanalConnector;

import com.alibaba.otter.canal.client.CanalConnectors;

import com.alibaba.otter.canal.common.utils.AddressUtils;

import com.alibaba.otter.canal.protocol.CanalEntry;

import com.alibaba.otter.canal.protocol.Message;

import java.net.InetSocketAddress;

import java.util.List;

/**

* A Camel Application

*/

public class MainApp {

/**

* A main() so we can easily run these routing rules in our IDE

*/

public static void main(String... args) throws Exception {

// 创建链接

CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(AddressUtils.getHostIp(),

11111), "example", "", "");

int batchSize = 1000;

int emptyCount = 0;

try {

connector.connect();

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

connector.rollback();

int totalEmptyCount = 120;

while (emptyCount < totalEmptyCount) {

Message message = connector.getWithoutAck(batchSize); // 获取指定数量的数据

long batchId = message.getId();

int size = message.getEntries().size();

if (batchId == -1 || size == 0) {

emptyCount++;

System.out.println("empty count : " + emptyCount);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

} else {

emptyCount = 0;

// System.out.printf("message[batchId=%s,size=%s] \n", batchId, size);

printEntry(message.getEntries());

}

connector.ack(batchId); // 提交确认

// connector.rollback(batchId); // 处理失败, 回滚数据

}

System.out.println("empty too many times, exit");

} finally {

connector.disconnect();

}

}

private static void printEntry(List entrys) {

for (CanalEntry.Entry entry : entrys) {

if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry

.EntryType

.TRANSACTIONEND) {

continue;

}

CanalEntry.RowChange rowChage = null;

try {

rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());

} catch (Exception e) {

throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),

e);

}

CanalEntry.EventType eventType = rowChage.getEventType();

System.out.println(String.format("================> binlog[%s:%s] , name[%s,%s] , eventType : %s",

entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),

entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),

eventType));

for (CanalEntry.RowData rowData : rowChage.getRowDatasList()) {

if (eventType == CanalEntry.EventType.DELETE) {

printColumn(rowData.getBeforeColumnsList());

} else if (eventType == CanalEntry.EventType.INSERT) {

printColumn(rowData.getAfterColumnsList());

} else {

System.out.println("-------> before");

printColumn(rowData.getBeforeColumnsList());

System.out.println("-------> after");

printColumn(rowData.getAfterColumnsList());

}

}

}

}

private static void printColumn(List columns) {

for (CanalEntry.Column column : columns) {

System.out.println(column.getName() + " : " + column.getValue() + " update=" + column.getUpdated());

}

}

}

注意newSingleConnector那里,设置canal server的ip和端口,端口默认为11111。example是和conf目录下的相对应。

如果你在这里新建个目录abc,目录里也放一个instance.properties,那么就可以在客户端监听abc。

启动客户端,查看控制台输出。

启动后,就可以打印empty count,此时你可以操作数据库里的test库,做任何增删改的操作,然后就能在控制台看到打印的语句。

可以看到,修改的是test库里的History表,before代表修改前,id=3,calltime字段值为3,after修改后,calltime为22.customer列我没有修改,所以值为242没变。

这样就获得了对应的库里,某个表的任何一列的变化的解析。

监听mysql表内容变化 使用canal_2 监听mysql表内容变化,使用canal相关推荐

  1. mysql cmd 实时监控_mysql实时监听sql语句

    [临时配置] 1.首先使用cmd命令行终端连接mysql C:\Users\houxin>mysql -h127.0.0.1 -uroot -p 输入密码,连接成功 2.设置数据库执行的日志文件 ...

  2. java 持久监听blockqueue的变化_Curator目录监听

    Curator目录监听 write by donaldhan, 2018-06-29 09:40 引言 上一篇文章,我们简单看一下Curator的CDRWA相关的构造器,及Curator框架实现,[C ...

  3. php 如何让html表单当中的数据在修改mysql的时候自动变更_怎么用php把html表单内容写入数据库?...

    慕工程0101907 1:首先要使用PHP的超全局变量 $_GET 和 $_POST 用于收集表单数据(form-data)2:然后使用INSERT INTO 语句用于向数据库表中插入新记录.具体示例 ...

  4. mysql gh 划线,gh-ost:在线DDL修改MySQL表结构工具

    在之前,我分享过一次pt-online-schema-change在线DDL的工具实践记录,在实际使用过程中,发现部门的很多老系统大量使用了触发器,从而无法使用这个工具,非常遗憾!导致很多DDL变更都 ...

  5. 高可用Mysql架构_Mysql主从复制、Mysql双主热备、Mysql双主双从、Mysql读写分离(Mycat中间件)、Mysql分库分表架构(Mycat中间件)的演变...

    [Mysql主从复制] 解决的问题 数据分布:比如一共150台机器,分别往电信.网通.移动各放50台,这样无论在哪个网络访问都很快.其次按照地域,比如国内国外,北方南方,这样地域性访问解决了. 负载均 ...

  6. 不用Oracle?基于MySQL数据库下亿级数据的分库分表

    墨墨导读:本文以一个实际的项目应用为例,层层向大家剖析如何进行数据库的优化.项目背景是企业级的统一消息处理平台,客户数据在5千万加,每分钟处理消息流水1千万,每天消息流水1亿左右. 数据库在金融行业怎 ...

  7. 基于MySQL数据库下亿级数据的分库分表

    来自:www.cnblogs.com/jpfss/ 移动互联网时代,海量的用户数据每天都在产生,基于用户使用数据等这样的分析,都需要依靠数据统计和分析,当数据量小时,数据库方面的优化显得不太重要,一旦 ...

  8. 干掉MySQL!阿里云MVP专家的分库分表设计,搞得太棒了!

    孙玄,江湖人称"玄姐",前58集团技术委员会主席,前转转二手交易平台首席架构师.今天想跟你聊点儿企业里那些年薪百万的架构师,他们的架构设计思维是如何升级的,以及他们是如何玩转 My ...

  9. mysql技术内幕innodb存储引擎——表索引算法和锁_(转)Mysql技术内幕InnoDB存储引擎-表索引算法和锁...

    表 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC% ...

最新文章

  1. ASP.NET杂谈-一切都从web.config说起(2)(ConfigSections详解-上 )
  2. 书评 - 《展望敏捷软件测试》
  3. Curator实现分布式锁的基本原理-构造函数
  4. MyEclipse移动开发教程:迁移HTML5移动项目到PhoneGap(二)
  5. Chapter7-10_Deep Learning for Question Answering (1/2)
  6. 測试新浪微博@小冰 为代码机器人的一些方法
  7. L-BFGS算法/Broyden族/BFGS算法/阻尼牛顿法的Python实现代码
  8. 牛逼了 这 7 个 Python 入门实战项目,我打 99.99 分
  9. aspen怎么做灵敏度分析_灵敏度分析 aspen
  10. 【安全资讯】熊猫烧香之后15年,网络变安全了吗?
  11. 字符串函数---atoi()函数详解及实现(完整版)
  12. Microsoft Visio 2010 安装失败 安装界面闪退
  13. Facebook广告投放:WC广告的优点和缺点
  14. 软件安全实验——lab10(二、TCP/IP攻击实验)
  15. 重装系统遇上reboot and select proper boot device ...问题解决方案
  16. 织梦DedeCMS文章列表页自动统计当前栏目文档总数的方法
  17. 看90后开发的游戏如何闯进AppStore前十
  18. 桌面显示电脑配置的PE_你还用软件看电脑配置?分享三种无需软件查看配置的方法...
  19. IT外包行业到底需要什么样的老板?
  20. PHPCMS本地项目二次开发流程

热门文章

  1. rda冗余分析步骤_文献综述,步骤与问题!
  2. python len函数_Python 初学者必备的常用内置函数
  3. java 多态性 变量_java – 与实例变量的多态性
  4. html对话框跳转页面,html5各种页面切换效果和模态对话框用法总结
  5. 怎么查到运行的时间_“我的成考录取通知书怎么还没来,它是不是迷路了?”...
  6. 湖南工业大学计算机专硕调剂,2020考研调剂:湖南工业大学生物信息实验室2020考研调剂信息...
  7. php核心语法,PHP核心语法总结
  8. exp imp 及参数
  9. java 混淆 js_Vue javascript和css混淆
  10. 基于JAVA+Servlet+JSP+MYSQL的高校社团管理系统