Canal的简单使用(监控数据库数据的变化)
原文:https://www.cnblogs.com/java-spring/p/8930740.html
canal可以用来监控数据库数据的变化,从而获得新增数据,或者修改的数据,用于实际工作中,比较实用,特此记录一下
Canal简介
canal是应阿里巴巴存在杭州和美国的双机房部署,存在跨机房同步的业务需求而提出的。
阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务
基于日志增量订阅&消费支持的业务:
数据库镜像
数据库实时备份
多级索引 (卖家和买家各自分库索引)
search build
业务cache刷新
价格变化等重要业务消息
keyword:数据库同步,增量订阅&消费。
首先,下载canal安装包:
https://github.com/alibaba/canal/releases

安装步骤:
在opt下(或者其他目录)创建一个canal文件夹

因为canal解压后并没有整体的文件夹,是把里面的内容一下解压出来的
然后进入canal文件夹,将安装包canal.deployer-1.0.24.tar.gz传输进来
解压:
tar -zxvf canal.deployer-1.0.24.tar.gz

可以删除安装包canal.deployer-1.0.24.tar.gz了
修改canal配置文件
vi conf/example/instance.properties

修改红框内的内容
canal.instance.dbUsername = **** #数据库用户名
canal.instance.dbPassword = **** #数据库密码
canal.instance.defaultDatabaseName = **** #指定需要同步的数据库
canal.instance.connectionCharset = UTF-8 #指定编码方式
然后保存:
esc :wq
配置mysql数据库
vi /etc/my.cnf
添加以下三行内容,如果原来存在,则不需要添加,只需对当前配置项进行修改即可
log-bin=mysql-bin #添加这一行就ok
binlog-format=ROW #选择row模式
server-id=1 #配置mysql replaction需要定义,不能和canal的slaveId重复

然后保存:
esc :wq
配置canal用户
用root用户登录mysql:
mysql -uroot -p
回车,输入密码
创建“canal”用户:
create user canal identified by 'canal';
有可能会出现如下情况:

直接刷新:
FLUSH PRIVILEGES;
然后再次创建“canal”用户

为“canal”用户赋予相应权限:
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
然后刷新权限:
FLUSH PRIVILEGES;
退出mysql
exit;
重启mysql服务
sudo service mysqld restart

cd到bin目录,启动canal-server
cd bin/ ./startup.sh
查看启动状态:
tail -f -n 50 ../logs/canal/canal.log

用客户端代码进行检测

package com.test; import java.net.InetSocketAddress;
import java.util.List; import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry.Column;
import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
import com.alibaba.otter.canal.protocol.CanalEntry.EntryType;
import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
import com.alibaba.otter.canal.protocol.CanalEntry.RowChange;
import com.alibaba.otter.canal.protocol.CanalEntry.RowData;
import com.alibaba.otter.canal.protocol.Message; public class TestCanal { public static void main(String args[]) {
// 创建链接
CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("***canal所在的主机ip***", 11111),
"example", "", "");
int batchSize = 1000;
int emptyCount = 0;
try {
connector.connect();
connector.subscribe(".*\\..*");
connector.rollback();
int totalEmtryCount = 1200;
while (emptyCount < totalEmtryCount) {
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) {
e.printStackTrace();
}
} 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<Entry> entrys) {
for (Entry entry : entrys) {
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN
|| entry.getEntryType() == EntryType.TRANSACTIONEND) {
continue;
} RowChange rowChage = null;
try {
rowChage = RowChange.parseFrom(entry.getStoreValue());
} catch (Exception e) {
throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),
e);
} 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 (RowData rowData : rowChage.getRowDatasList()) {
if (eventType == EventType.DELETE) {
printColumn(rowData.getBeforeColumnsList());
} else if (eventType == 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<Column> columns) {
for (Column column : columns) {
System.out.println(column.getName() + " : " + column.getValue() + " update=" + column.getUpdated());
}
} }

直接启动mian函数

然后任意选择一张表,插入数据库一条数据

控制台输出内容

更多信息可以参考:
谈谈对Canal( 增量数据订阅与消费 )的理解
http://www.importnew.com/25189.html
https://blog.csdn.net/my201110lc/article/details/78836270
Canal的简单使用(监控数据库数据的变化)的更多相关文章
- 监控SQL:通过SQL Server的DDL触发器来监控数据库结构的变化(1)
原文:监控SQL:通过SQL Server的DDL触发器来监控数据库结构的变化(1) 如果你要同步不同数据库之间的数据,首先会想到的是数据库复制技术,但如果让你同步数据库的结构,你会想到什么呢? 下面 ...
- 用Maven整合SpringMVC+Spring+Hibernate 框架,实现简单的插入数据库数据功能
一.搭建開始前的准备 1.我用的MyEclipse2014版,大家也能够用IDEA. 2.下载Tomcat(免安装解压包).MySQL(zip包下载地址 免安装解压包,优点就是双击启动,最后我会把ba ...
- sqlDependency监控数据库数据变化,自动通知
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- C#简单代码转移数据库数据
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Data;u ...
- postgreSQL数据库的监控及数据维护
目前postgreSQL数据库的管理,数据查询等都需要安装postgreSQL软件或安装pgadmin等,远程访问都需要先登录到服务器等繁琐的操作.如果是开发团队,那么每个开发,测试,管理人员都要经历 ...
- Oracle数据库的监控及数据维护
目前Oracle数据库的管理,数据查询等都需要安装Oracle软件或安装Oracle Client等,远程访问都需要先登录到服务器等繁琐的操作.如果是开发团队,那么每个开发,测试,管理人员都要经历这个 ...
- solr 简单搭建 数据库数据同步(待续)
原来在别的公司负责过文档检索模块的维护(意思就是不是俺开发的啦). 所以就略微接触和研究了下文档检索. 文档检索事实上是全文检索.是通过一种技术把N多文档进行一定规律的分割归类,然后创建易于搜索的索引 ...
- 数据库数据在Java占用内存简单估算
数据库数据在Java占用内存简单估算 结论: 1.数据库记录放在JAVA里,用对象(ORM一般的处理方式)须要4倍左右的内存空间.用HashMap这样的KV保存须要10倍空间; 2.假设你主要数据是t ...
- Postgresql数据库数据简单的导入导出
Postgresql数据库数据简单的导入导出 博客分类: DataBase postgres 命令操作: 数据的导出:pg_dump -U postgres(用户名) (-t 表名) 数据库名( ...
随机推荐
- ELK之在CentOS7.5上使用rpm包安装配置ELK7版本
一,安装环境查看 二,软件版本选用 jdk 1.8.0_171 elasticsearch 7.1.1 kibana 7.1.1 logstash 7.1.1 三,安装配置 1,安装JDK 过程不详述 ...
- 上下文管理器之__enter__和__exit__
目录 前言 with as是如何工作的 自定制open方法 更多的示例 返回主目录 前言 回到顶部 有个学生在第四轮面试中被CTO问到:如何自定义实现with open的功能.然后就一脸懵逼的回来找我 ...
- 欧姆龙 EntherNet/IP(CIP报文格式)
Enthip/IP_ CIP报文格式 测试Demo在文章末尾 注册请求帧: 0x65 0x00 注册请求命令 2byte 0x04,0x00 header长度2byte < 封装头& ...
- Core JSON及JSON解析
JSON (JavaScript Object Notation) 是一种基于文档的标准数据交换格式,它可以让应用程序通过网络交换数据.JSON独立于编程语言(Ruby, Java/EE, JavaS ...
- mybatis 找不到映射器xml文件 (idea)
原因是: idea不会编译src的java目录的xml文件 所以解决思路就是:将IDEA maven项目中src源代码下的xml等资源文件编译进classes文件夹 具体操作方法就是:配置maven的 ...
- layuiAdmin (单页版)常见问题与解决方案
最近项目开发中用到了layuiAdmin的单页版进行开发,期间遇到一些问题,在此总结一二: 单页版缓存问题 由于单页面版本的视图文件和静态资源模块都是动态加载的,所以可能存在浏览器的本地缓存问题,因此 ...
- 99%的人都理解错了GET与POST的区别
原文链接:https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3 ...
- (JavaScript) 百度地图与腾讯地图坐标转换
/** * 坐标转换,百度地图坐标转换成腾讯地图坐标 * lng 腾讯经度(pointy) * lat 腾讯纬度(pointx) * 经度>纬度 */ function bMapToQQMap( ...
- [官网]Windows 10 版本信息
对应于服务选项的 Windows 10 当前版本 https://docs.microsoft.com/zh-cn/windows/release-information/ 所有的日期都按照 ISO ...
- 有关Linux服务器的一些配置
1.Redis部署 1.版本 redis-3.0.72.上传解压 3.编译 make && make install 问题:/bin/sh: cc: command not found ...