背景:

1. 一些项目的基础功能会有Audit Trace, 以记录系统用户所做过的所有记录。

2. 实时备份数据,比如mysql主从复制,一个用于面向应用,一个用于对应用数据库的实时备份。

3. 实时收集关系型数据库变更,将数据保存在nosql数据库中,以提供快速检索,一个较为实用的场景就是实现地将mysql数据变更同步到elastic search 或者 mongo db。

下面,将介绍如何通过canal,将mysql 数据变更同步到elastic search 。

首先我们了解一下什么是canal?

mysql主备复制实现


从上层来看,复制分成三步:

  1. master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);
  2. slave将master的binary log events拷贝到它的中继日志(relay log);
  3. slave重做中继日志中的事件,将改变反映它自己的数据。

canal的工作原理:

原理相对比较简单:

    1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议
    2. mysql master收到dump请求,开始推送binary log给slave(也就是canal)
    3. canal解析binary log对象(原始为byte流)

安装步骤:

访问:https://github.com/alibaba/canal/releases ,会列出所有历史的发布版本包 下载方式,比如以1.0.17版本为例子:

wget https://github.com/alibaba/canal/releases/download/canal-1.0.17/canal.deployer-1.0.17.tar.gz

mkdir /tmp/canal
tar zxvf canal.deployer-1.0.17.tar.gz -C /tmp/canal

配置修改

vi conf/example/instance.properties
#################################################
## mysql serverId
canal.instance.mysql.slaveId =
#position info,需要改成自己的数据库信息
canal.instance.master.address = 127.0.0.1:
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 =
canal.instance.connectionCharset = UTF- #table regex
canal.instance.filter.regex = .\.. #################################################

准备启动

sh bin/startup.sh

查看日志

vi logs/canal/canal.log

关闭

sh bin/stop.sh

下面试下在代码中,获取到mysql变更:

首先安装下 canal 客户端 nuget包

Install-Package CanalSharp.Client

static void Main(string[] args)
{
//canal 配置的 destination,默认为 example
var destination = "example";
//创建一个简单 CanalClient 连接对象(此对象不支持集群)传入参数分别为 canal 地址、端口、destination、用户名、密码
var connector = CanalConnectors.NewSingleConnector("192.168.1.23", , destination, "", "");
//连接 Canal
connector.Connect();
//订阅,同时传入 Filter。Filter是一种过滤规则,通过该规则的表数据变更才会传递过来
//允许所有数据 .*\\..*
//允许某个库数据 库名\\..*
//允许某些表 库名.表名,库名.表名
connector.Subscribe(".*\\..*");
while (true)
{
//获取数据 1024表示数据大小 单位为字节
var message = connector.Get();
//批次id 可用于回滚
var batchId = message.Id;
if (batchId == - || message.Entries.Count <= )
{
Thread.Sleep();
continue;
} PrintEntry(message.Entries);
}
} /// <summary>
/// 输出数据
/// </summary>
/// <param name="entrys">一个entry表示一个数据库变更</param>
private static void PrintEntry(List<Entry> entrys)
{
foreach (var entry in entrys)
{
if (entry.EntryType == EntryType.Transactionbegin || entry.EntryType == EntryType.Transactionend)
{
continue;
} RowChange rowChange = null; try
{
//获取行变更
rowChange = RowChange.Parser.ParseFrom(entry.StoreValue);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
} if (rowChange != null)
{ //by the changed entry's table name and record id. get the changed order(full info with any children records) form mysql and save it to es. //to do it, boys ! //变更类型 insert/update/delete 等等
EventType eventType = rowChange.EventType;
//输出binlog信息 表名 数据库名 变更类型
Console.WriteLine(
$"================> binlog[{entry.Header.LogfileName}:{entry.Header.LogfileOffset}] , name[{entry.Header.SchemaName},{entry.Header.TableName}] , eventType :{eventType}"); //输出 insert/update/delete 变更类型列数据
foreach (var rowData in rowChange.RowDatas)
{
if (eventType == EventType.Delete)
{
PrintColumn(rowData.BeforeColumns.ToList());
}
else if (eventType == EventType.Insert)
{
PrintColumn(rowData.AfterColumns.ToList());
}
else
{
Console.WriteLine("-------> before");
PrintColumn(rowData.BeforeColumns.ToList());
Console.WriteLine("-------> after");
PrintColumn(rowData.AfterColumns.ToList());
}
}
}
}
} /// <summary>
/// 输出每个列的详细数据
/// </summary>
/// <param name="columns"></param>
private static void PrintColumn(List<Column> columns)
{
foreach (var column in columns)
{
//输出列明 列值 是否变更
Console.WriteLine($"{column.Name} : {column.Value} update= {column.Updated}");
}
}
}

运行代码,去到数据库中改一下某行数据:

可以看到我们代码收集到变更信息:

本篇就介绍到这里了, 至于如何将变更同步到es,那是属于es操作的范畴,可参考 https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/elasticsearch-net.html

以上内容源于:

https://github.com/alibaba/canal/wiki/QuickStart

https://github.com/dotnetcore/CanalSharp

mysql数据库变更监控(canal)的更多相关文章

  1. centos 7中监控mysql 数据库脚本(监控端口)

    centos 7中监控mysql 数据库脚本(监控端口) 监控mysql数据库的方法如下: 1.监控端口 netstat -nltp |grep 3306 2.监控进程 ps -ef |grep 33 ...

  2. zabbix实现mysql数据库的监控(三)

    上面一章“zabbix实现mysql数据库的监控(二)”使用MPM来监控mysql,但是遇到安装问题始终解决不了,这里改用percona-monitoring-plugins进行zabbxi上监控my ...

  3. zabbix实现mysql数据库的监控(二)

    上章我们把zabbix的服务端和客户端都部署完成了,本章接着进行两部分的设置: 1  添加对mysql数据库主机的监控 2  添加对mysql数据库的监控 一.对数据库服务器主机监控 1 创建主机 步 ...

  4. MySQL数据库重点监控指标

    MySQL数据库重点监控指标 QPS queries per seconds 每秒中查询数量 show global status like 'Question%'; Queries/seconds ...

  5. zabbix实现mysql数据库的监控(四)

    前面介绍的内容都是用第三方开发好的插件进行mysql监控的,可能有些我们关心的监控内容并不在其中,这时一种常用的方法就是定义我们自己的脚本并将它整合到zabbix中,从而在原有监控的基础上进行有力的补 ...

  6. zabbix实现mysql数据库的监控(一)

    zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案.它能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问 ...

  7. mysql数据库重点监控

    1. QPS  每秒钟查询数量     查询总数/秒数 queries per seconds show global status like 'Question%' 2.TPS   每秒钟的事物数 ...

  8. 使用 Docker 部署 Grafana + Prometheus 监控 MySQL 数据库

    一.背景 在平时开发过程当中需要针对 MySQL 数据库进行监控,这里我们可以使用 Grafana 和 Prometheus 来实现监控功能.Grafana 是一款功能强大的仪表盘面板,支持多种数据源 ...

  9. canal —— 阿里巴巴mysql数据库binlog的增量订阅&消费组件

    阿里巴巴mysql数据库binlog的增量订阅&消费组件canal ,转载自  https://github.com/alibaba/canal 最新更新 canal QQ讨论群已经建立,群号 ...

随机推荐

  1. 手推Apriori算法------挖掘频繁项集

    版权声明:本文为博主原创文章,未经博主允许不得转载. Apriori算法: 使用一种称为逐层搜索的迭代方法,其中K项集用于搜索(K+1)项集. 首先,通过扫描数据库,统计每个项的计数,并收集满足最小支 ...

  2. iOS组件化开发入门 —— 提交自己的私有库

    前言:本人也是初次接触组件化开发,感觉现有的资料太繁杂,就简单整理了一下,在此跟大家分享一些入手的经验,主要就是描述cocoapods的私有库封装和提交.组件化开发是个大的议题,涉及到架构思路.设计模 ...

  3. bzoj1216 操作系统(优先队列模拟)

    1216: [HNOI2003]操作系统 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1172  Solved: 649[Submit][Statu ...

  4. http2及server push

      本文主要研究下java9+springboot2+undertow2启用http2及server push maven <parent> <groupId>org.spri ...

  5. HBuilder发行原装安装包操作记录

    1.在左侧"项目管理器"中选择项目: 2.点击菜单栏中的"发行-->发行为原生安装包": 3.在弹出的App云端打包中填写相关信息: IOS开发者证书配置 ...

  6. C# 相关概念

    解决方案 在磁盘上由 .sln 文件表示,是一个或多个相关项目的容器. 例如,如果为 Python 应用程序编写 C++ 扩展,该 C++ 项目可以驻留在同一解决方案中. 解决方案还可以包含 Web ...

  7. js作用域、异步——学习笔记

    所有的 for if switch while do 等等,都属于块级作用域,里面声明的对象,外面也能访问.但function 函数里的作用域,在函数外是访问不到的. 但函数作用域里面可以访问外面. ...

  8. Android 仿 新闻阅读器 菜单弹出效果(附源码DEMO)

    这一系列博文都是:(android高仿系列)今日头条 --新闻阅读器 (一) 开发中碰到问题之后实现的,觉得可能有的开发者用的到或则希望独立成一个小功能DEMO,所以就放出来这么一个DEMO. 原本觉 ...

  9. Python学习日记之正则表达式re模块

    用在线网页测试正则表达式时,JavaScript不支持 零宽度正回顾后发断言 (?<=exp)测试时一直匹配失败 但re模块是支持 (?<=exp) 的 终于脱坑

  10. 左耳听风 ARTS Week 001

    要求:1.每周至少做一个 leetcode 的算法题 2.阅读并点评至少一篇英文技术文章 3.学习至少一个技术技巧 4.分享一篇有观点和思考的技术文章 1.每周至少做一个 leetcode 的算法题 ...