java 通过Canal监控MySql变化

一 开启MySql日志记录功能

        在mysql的 my.cnf (linux)文件中位置[mysqld]后面添加如下内容:

log-bin=mysql-bin

binlog-format=ROW

二  Linux 环境 Canal 安装

  1. 上传canal.deployer-1.1.tar 到指定位置
  2. 解压文件 tar -xvf canal.deployer-1.1.1.tar
  3. 进入文件 –>conf->example->instance.properties
  4. 编辑 instance.properties,配置数据库信息及用户(用户需要有相应的权限  例: canal)     
      10行  canal.instance.master.address=127.0.0.1:3306 
      34行  canal.instance.dbUsername=   canal
      35行  canal.instance.dbPassword=    passwd
      37行  canal.instance.defaultDatabaseName =   sid

     canal 用户创建及授权sql:

CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%' IDENTIFIED BY 'canal' WITH GRANT OPTION;
FLUSH PRIVILEGES;

5.如果想增加canal 实例

  1. 进入文件 –>conf
  2. 复制example文件夹,粘贴在同级目录下 ,修改文件夹名字(例:my-demo
  3. 修改my-demo 目录instance.properties配置文件的 canal.instance.mysql.slaveId=  (多个实例的slavld不可以重复)
  4. 在conf文件夹里的canal.properties配置文件里修改 canal.destinations= my-demo ,红色为上一步的 例中 的名字  ,如果有多个实例   canal.destinations=  后面可以用 逗号隔开写多个实例名

6. 启动  ->bin    ./ startup.sh

   关闭 –>bin    ./stop.sh

 查看服务是否启动成功

cd logs/canal/canal.log     
cat canal.log

服务启动成功如下:

## the canal server is running now .....

三  java代码监控

1 maven 依赖


	com.alibaba.otter
	canal.client
	1.0.25

2 监控类CanalMysqlMonitorServer

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
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;

/**
  */
@Component
public class CanalMysqlMonitorServer implements ApplicationRunner {
	private static final Logger log = Logger.getLogger(CanalMysqlMonitorServer.class);

	@Value("${canal.ip}")
	private String CANALIP;
	@Value("${canal.port}")
	private String CANALPORT;

	public void geEntries() {
		CanalConnector connector = CanalConnectors
				.newSingleConnector(new InetSocketAddress(CANALIP, Integer.valueOf(CANALPORT)), "my-demo", "", "");
		int batchSize = 1000;
		connector.connect();
		connector.subscribe("schenameName.table1,schenameName.table2");
		connector.rollback();
		try {
			while (true) {
				Message message = connector.getWithoutAck(batchSize);
				long batchId = message.getId();
				int size = message.getEntries().size();
				if (batchId == -1 || size == 0) {
				} else {
					printEntry(message.getEntries());
				}
				connector.ack(batchId); // 提交确认
			}
		} finally {
			connector.disconnect();
		}
	}

	private void printEntry(List list) {
		for (Entry entry : list) {
			if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN
					|| entry.getEntryType() == EntryType.TRANSACTIONEND) {
				continue;
			}
			RowChange rowChage = null;
			try {
				rowChage = RowChange.parseFrom(entry.getStoreValue());
			} catch (Exception e) {
			}
			EventType eventType = rowChage.getEventType();
			if (entry.getHeader().getSchemaName().equals("schemaName")) {
				if (entry.getHeader().getTableName().equals("table1")) {
					log.info("table1 changed.");
					List deleteUserId = new ArrayList();
					List updateUserId = new ArrayList();
					for (RowData rowData : rowChage.getRowDatasList()) {
						if (eventType == eventType.DELETE) {
							deleteUserId.add(rowData.getBeforeColumnsList().get(1).getValue());
						} else if (eventType == eventType.INSERT || eventType == eventType.UPDATE) {
							updateUserId.add(rowData.getAfterColumnsList().get(1).getValue());
							updateUserId.add(rowData.getBeforeColumnsList().get(1).getValue());
						}
					}
				}
			}
		}
	}

	@Override
	public void run(ApplicationArguments args) throws Exception {
		geEntries();
	}

 

你可能感兴趣的:(Java,数据库)