首先要Canal服务端下载:链接: https://pan.baidu.com/s/1FwEnqPC1mwNXKRwJuMiLdg 密码: r8xf

连接数据库的时候需要给予连接数据库权限:在my.ini配置文件里加上 log-bin=mysql-bin 这个就行了

连接数据库的账号需要授权

CREATE USER cqlpz IDENTIFIED BY 'cqlpz';

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

FLUSH PRIVILEGES; 创建一个账号并给予权限

解压出来有4个目录

2.conf 里面canal.properties 配置canal自己的 比如多个服务连接,canal缓存名称

这是example里面的内容;

两个properties就是配置自己的数据库连接,meta.dat相当于启动canal服务过后的额缓存信息

3.lib 就是canal需要的jar

4.logs 日志文件

maven引入jar

 1 <dependency>
2 <groupId>com.alibaba.otter</groupId>
3 <artifactId>canal.client</artifactId>
4 <version>1.0.25</version>
5 </dependency>
6 <dependency>
7 <groupId>redis.clients</groupId>
8 <artifactId>jedis</artifactId>
9 <version>2.9.0</version>
10 </dependency>

java代码

1.连接canal服务

 // 创建链接
CanalConnector connector = CanalConnectors.newSingleConnector(
new InetSocketAddress(AddressUtils.getHostIp(), 端口),
"canal名称(虚拟数据名)",
"数据库账号",
"数据库密码");

2.连接某个数据库

connector.connect();
connector.subscribe("监控的数据库\\..*");
connector.rollback();

3.获取操作的事件

Message message = connector.getWithoutAck(数量); // 获取指定数量的数据
List<Entry> entrys=message.getEntries();
for (Entry entry : entrys) {
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN ||entry.getEntryType() == EntryType.TRANSACTIONEND) {
continue;
}
RowChange rowChage = null;
try {
rowChage = RowChange.parseFrom(entry.getStoreValue());
} catch (InvalidProtocolBufferException e) {
System.out.println("获取数据失败:"+e.getMessage());
}
EventType eventType = rowChage.getEventType();
for (RowData rowData : rowChage.getRowDatasList()) {
if (eventType.equals(EventType.DELETE)) {
rowData.getBeforeColumnsList();//删除的所有数据
} else if (eventType.equals(EventType.INSERT)) {
rowData.getAfterColumnsList();//添加的所有数据
}else if(eventType.equals(EventType.UPDATE)) {
rowData.getAfterColumnsList();//修改的所有数据
}
}

完整的java类

public class ClientSample {
private static Logger logger = LoggerFactory.getLogger(ClientSample.class); public void startCanalThread(){
Thread thread = new StartCanalThread();
thread.start();
}
/**
* canal 线程
*/
public class StartCanalThread extends Thread {
@Override
public void run() {
// 创建链接
CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("localhost", 11111),
"longpizi",
"longpizi",
"cqlongpizi");
connector.connect();
connector.subscribe("test\\..*");
connector.rollback();
try {
while (true) {
// 获取指定数量的数据
Message message = connector.getWithoutAck(1000);
long batchId = message.getId();
if (batchId != -1 && message.getEntries().size() > 0) {
printEntry(message.getEntries());
}
connector.ack(batchId); // 提交确认
Thread.sleep(2000);
} }catch (Exception e){
logger.error("Canal线程异常,已终止:"+e.getMessage());
} finally {
//中断Canal连接
connector.disconnect();
}
}
} /**
* 数据库执行的操作
* @param entrys
*/
private static void printEntry( List<Entry> entrys) {
for (Entry entry : entrys) {
//操作事物 忽略
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) { continue; }
RowChange rowChage = null;//执行事件信息
String database=null;//执行的数据库
String table=null;//执行的表
try {
database=entry.getHeader().getSchemaName();
table=entry.getHeader().getTableName();
rowChage = RowChange.parseFrom(entry.getStoreValue());
} catch (InvalidProtocolBufferException e) {
logger.error("获取数据失败:"+e.getMessage());
}
//获取执行的事件
EventType eventType = rowChage.getEventType();
for (RowData rowData : rowChage.getRowDatasList()) {
//删除操作
if (eventType.equals(EventType.DELETE)) {
redisDelete(rowData.getBeforeColumnsList(),database,table);
}
//添加操作
else if (eventType.equals(EventType.INSERT)) {
redisInsert(rowData.getAfterColumnsList(),database,table);
}
//修改操作
else if(eventType.equals(EventType.UPDATE)) {
redisUpdate(rowData.getAfterColumnsList(),database,table);
}
//修改表结构
else if(eventType.equals(EventType.ALTER)){
logger.info("修改表结构");
}
}
}
} /**
* 数据库执行了添加操作
* @param columns
* @param database
* @param table
*/
private static void redisInsert( List<Column> columns,String database,String table){
JSONObject json=new JSONObject();
for (Column column : columns) {
json.put(column.getName(), column.getValue());
}
System.out.println("数据库:"+database+"==>表:"+table+"==>添加数据:"+JSON.toJSONString(json));
} /**
* 数据库执行了修改操作
* @param columns
* @param database
* @param table
*/
private static void redisUpdate( List<Column> columns,String database,String table){
JSONObject json=new JSONObject();
for (Column column : columns) {
json.put(column.getName(), column.getValue());
}
System.out.println("数据库:"+database+"==>表:"+table+"==>修改数据:"+JSON.toJSONString(json));
} /**
* 数据库执行了删除操作
* @param columns
* @param database
* @param table
*/
private static void redisDelete( List<Column> columns,String database,String table){
JSONObject json=new JSONObject();
for (Column column : columns) {
json.put(column.getName(), column.getValue());
}
System.out.println("数据库:"+database+"==>表:"+table+"==>删除数据:"+JSON.toJSONString(json));
}
}

这样就可把操作的数据更新到redis里面了

Canal监控Mysql同步到Redis(菜鸟也能搭建)的更多相关文章

  1. mysql同步之otter/canal环境搭建完整详细版

    接上一篇mysql 5.7多源复制(用于生产库多主库合并到一个查询从库). 这一篇详细介绍otter/canal环境搭建以及当同步出现异常时如何排查.本文主要参考https://blog.csdn.n ...

  2. Zabbix监控mysql配置及故障告警配置

    本文主要介绍zabbix监控mysql的配置,包含使用zabbix自带模板监控mysql相关信息及自定义key监控mysql同步情况.同时介绍了触发器的创建及zabbix通过邮件方式告警配置. 一.配 ...

  3. Canal 实战 | 第一篇:SpringBoot 整合 Canal + RabbitMQ 实现监听 MySQL 数据库同步更新 Redis 缓存

    一. Canal 简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同 ...

  4. canal整合springboot实现mysql数据实时同步到redis

    业务场景: 项目里需要频繁的查询mysql导致mysql的压力太大,此时考虑从内存型数据库redis里查询,但是管理平台里会较为频繁的修改增加mysql里的数据 问题来了: 如何才能保证mysql的数 ...

  5. 转载:阿里canal实现mysql binlog日志解析同步redis

    from: http://www.cnblogs.com/duanxz/p/5062833.html 背景 早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求.不过早期的数 ...

  6. Docker安装canal、mysql进行简单测试与实现redis和mysql缓存一致性

    一.简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费. 早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求 ...

  7. 【菜鸟玩Linux开发】通过MySQL自动同步刷新Redis

    在服务端开发过程中,一般会使用MySQL等关系型数据库作为最终的存储引擎,Redis其实也可以作为一种键值对型的数据库,但在一些实际场景中,特别是关系型结构并不适合使用Redis直接作为数据库.这俩家 ...

  8. zabbix3.0.4监控mysql主从同步

    zabbix3.0.4监控mysql主从同步 1.监控mysql主从同步原理: 执行一个命令 mysql -u zabbix -pzabbix -e 'show slave status\G' 我们在 ...

  9. 监控mysql主从同步状态脚本

    监控mysql主从同步状态脚本 示例一: cat check_mysql_health #!/bin/sh slave_is=($(mysql -S /tmp/mysql3307.sock -uroo ...

随机推荐

  1. CodeForces - 748F Santa Clauses and a Soccer Championship

    题意:有k对队伍,每对队伍之间将举行两次比赛,两支队伍各主办一次.住宿的地方要求在两支队伍家乡的最短路的结点上或者在两支队伍的家乡.问在选择住宿处最少的情况下,怎么组成这k对队伍? 分析: 1.因为n ...

  2. 8. react 基础 - props 默认值和类型限制 与 Props , State , render 函数 关系

    一. PropTypes 与 DefaultProps 官方文档 1. PropTypes 属性校验 引入 PropTypes import PropTypes from 'prop-types'; ...

  3. JavaScript之基于原型链的继承

    本文介绍下js的OOP中的继承. 上图的要点为:Foo函数在创建时会自动生成内置属性prototype,而typeof Foo.prototype是object类型的. 上图的要点为:Foo.prot ...

  4. linux上大文件切割成小文件传输

    使用tar命令进行压缩,使用split进行切割 压缩并分割: tar -zcvf - admin- |split -b 100m -d admin-.tar.gz 解压: 先合并成tar包在解压 ca ...

  5. Linux无法连接网络解决方案

    上次在VM中装好Linux以后,用xshell可以连接上Linux,可是今天在启动虚拟机打开Linux以后,发现又没有网络连接了,因为要用xshell连接的话首先要知道Linux的ipv4地址,在li ...

  6. Golang的学习方法

  7. JavaScript—瀑布流

    现在网页中需要翻页的列表,好多都已经改为瀑布流了.所以这个思路还是特别重要的 HTML Css 页面 因为每个图片的高度不一样所以她的 top 和left 我们待会通过JS计算 动态生成 js部分 思 ...

  8. bzoj4311向量(线段树分治+斜率优化)

    第二道线段树分治. 首先设当前向量是(x,y),剩余有两个不同的向量(u1,v1)(u2,v2),假设u1>u2,则移项可得,若(u1,v1)优于(u2,v2),则-x/y>(v1-v2) ...

  9. 计算机网络(3): ICMP报文

  10. Tensorflow函数——tf.set_random_seed(seed)

    设置图级随机seed. 依赖于随机seed的操作实际上从两个seed中获取:图级和操作级seed. 这将设置图级别的seed. 其与操作级seed的相互作用如下: 1.如果没有设置图形级别和操作see ...