Canal监控Mysql同步到Redis(菜鸟也能搭建)

首先要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里面了

posted @ 2018-08-15 10:38  iviv  阅读(5894)  评论(0编辑  收藏  举报