基于canal中间件对redis缓存进行处理

开启mysql binlog

问题点
由于我是安装的5.8版本以上的mysql,并没有my.cnf文件。于是需要自己去创建一个文件取各个my.cnf配置文件的先后顺序是:

  • /etc/my.cnf

  • /etc/mysql/my.cnf

  • /usr/local/mysql/etc/my.cnf

  • ~/.my.cnf
    我是直接配置在/etc环境下面,配置文件如下,配置好了之后

  • 配置文件重点注意


log-bin=mysql-bin #添加这一行就ok
binlog-format=ROW #选择row模式 
server_id=1
#配置好了并且重启后输入
show variables like 'log_bin'; 
看是否开启binlog

在navicat输入查看
在这里插入图片描述

重启mysql服务,具体操作如下

  • 启动mysql服务
    sudo /usr/local/MySQL/support-files/mysql.server start
  • 停止服务
    == sudo /usr/local/MySQL/support-files/mysql.server stop ==
  • 重启服务
    == sudo /usr/local/MySQL/support-files/mysql.server restart ==

my.cnf文件配置

Last login: Sat Feb 27 22:44:06 on ttys003
mac@macdeMacBook-Pro ~ % cd /etc
mac@macdeMacBook-Pro /etc % ls
afpovertcp.cfg				ntp_opendirectory.conf
aliases					openldap
aliases.db				pam.d
apache2					passwd
asl					paths
asl.conf				paths.d
auto_home				periodic
auto_master				pf.anchors
autofs.conf				pf.conf
bashrc					pf.os
bashrc_Apple_Terminal			php-NOTICE-PLANNED-REMOVAL.txt
com.apple.screensharing.agent.launchd	php-fpm.conf.default
csh.cshrc				php-fpm.d
csh.login				php.ini.default
csh.logout				postfix
cups					ppp
defaults				profile
emond.d					protocols
find.codes				racoon
ftpusers				rc.common
gettytab				rc.netboot
group					resolv.conf
hosts					rmtab
hosts.equiv				rpc
irbrc					rtadvd.conf
kern_loader.conf			security
krb5.keytab				services
localtime				shells
locate.rc				snmp
mail.rc					ssh
man.conf				ssl
manpaths				sudo_lecture
manpaths.d				sudoers
master.passwd				sudoers.d
my.cnf					syslog.conf
nanorc					ttys
networks				uucp
newsyslog.conf				wfs
newsyslog.d				xtab
nfs.conf				zprofile
notify.conf				zshrc
ntp.conf				zshrc_Apple_Terminal
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
Password:
mac@macdeMacBook-Pro /etc % cat my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.6/en/server-configuration-defaults.html
# *** DO NOT EDIT THIS FILE. It's a template which will be copied to the
# *** default location during install, and will be replaced if you
# *** upgrade to a newer version of MySQL.
 
[mysqld]
 
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
 
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
log_bin = /usr/local/mysql/logs/mysql-bin
binlog-format = ROW
# These are commonly set, remove the # and set as required.
# basedir = .....
# datadir = .....
# port = .....
# server_id = .....
# socket = .....
 
#服务端口号 默认3306
port = 3306
server_id = 1
# mysql安装根目录
basedir = /usr/local/mysql
# mysql数据文件所在位置
datadir = /usr/local/mysql/data
# pid

# 设置socke文件所在目录
socket = /usr/local/mysql/data/mysql.sock
 
# 跳过密码登录
# skip-grant-tables
 
# 数据库默认字符集,主流字符集支持一些特殊表情符号(特殊表情符占用4个字节)
# character-set-server = utf8mb4
 
# 数据库字符集对应一些排序等规则,注意要和character-set-server对应
# collation-server = utf8mb4_general_ci
 
# 设置client连接mysql时的字符集,防止乱码
# init_connect='SET NAMES utf8mb4'
 
# 是否对sql语句大小写敏感,1表示不敏感,8.0需要在初始化时候设置
# lower_case_table_names = 1
 
# 最大连接数
max_connections = 1000
 
#最大错误连接数
max_connect_errors = 1200
 
 
# wait_timeout = 1814400
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M 
 
 
# 二进制日志目录
# 自动删除过期日志的天数
expire_logs_days = 10
# 限制单个文件大小
max_binlog_size = 100M
 
# 查询日志
general_log = 1
# 查询日志文件位置
general_log_file = /usr/local/mysql/logs/query.log
 
# 数据库错误日志文件
log_error = /usr/local/mysql/logs/error.log
 
 
# sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
mac@macdeMacBook-Pro /etc % sudo /usr/local/mysql/support-files/mysql.server restart
Shutting down MySQL
... SUCCESS! 
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/mysql/data/macdeMacBook-Pro.local.pid).
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
mac@macdeMacBook-Pro /etc % sudo /usr/local/mysql/support-files/mysql.server restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/mysql/data/macdeMacBook-Pro.local.pid).
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
mac@macdeMacBook-Pro /etc % sudo /usr/local/mysql/support-files/mysql.server restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/mysql/data/macdeMacBook-Pro.local.pid).
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
mac@macdeMacBook-Pro /etc % echo my.cnf    
my.cnf
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
Password:
mac@macdeMacBook-Pro /etc % rm my.cnf      
override rw-r--r--  root/wheel for my.cnf? y
rm: my.cnf: Permission denied
mac@macdeMacBook-Pro /etc % sudo rm my.cnf
mac@macdeMacBook-Pro /etc % ls
afpovertcp.cfg				openldap
aliases					pam.d
aliases.db				passwd
apache2					paths
asl					paths.d
asl.conf				periodic
auto_home				pf.anchors
auto_master				pf.conf
autofs.conf				pf.os
bashrc					php-NOTICE-PLANNED-REMOVAL.txt
bashrc_Apple_Terminal			php-fpm.conf.default
com.apple.screensharing.agent.launchd	php-fpm.d
csh.cshrc				php.ini.default
csh.login				postfix
csh.logout				ppp
cups					profile
defaults				protocols
emond.d					racoon
find.codes				rc.common
ftpusers				rc.netboot
gettytab				resolv.conf
group					rmtab
hosts					rpc
hosts.equiv				rtadvd.conf
irbrc					security
kern_loader.conf			services
krb5.keytab				shells
localtime				snmp
locate.rc				ssh
mail.rc					ssl
man.conf				sudo_lecture
manpaths				sudoers
manpaths.d				sudoers.d
master.passwd				syslog.conf
nanorc					ttys
networks				uucp
newsyslog.conf				wfs
newsyslog.d				xtab
nfs.conf				zprofile
notify.conf				zshrc
ntp.conf				zshrc_Apple_Terminal
ntp_opendirectory.conf
mac@macdeMacBook-Pro /etc % sudo vim my.cnf
mac@macdeMacBook-Pro /etc % sudo /usr/local/mysql/support-files/mysql.server restart
 ERROR! MySQL server PID file could not be found!
Starting MySQL
.. SUCCESS! 
mac@macdeMacBook-Pro /etc % vim my.cnf

  # Here follows entries for some specific programs
  # The MySQL server
  [mysqld]
  character-set-server=utf8
  init_connect='SET NAMES utf8
  port        = 3306
  socket      = /tmp/mysql.sock
  skip-external-locking
  key_buffer_size = 16M
  max_allowed_packet = 1M
  table_open_cache = 64
  sort_buffer_size = 512K
  net_buffer_length = 8K
  read_buffer_size = 256K
  read_rnd_buffer_size = 512K
  myisam_sort_buffer_size = 8M
  character-set-server=utf8
  init_connect='SET NAMES utf8'
# Don't listen on a TCP/IP port at all. This can be a security enhancement,
# if all processes that need to connect to mysqld run on the same host.
# All interaction with mysqld must be made via Unix sockets or named pipes.
# Note that using this option without enabling named pipes on Windows
# (via the "enable-named-pipe" option) will render mysqld useless!
"my.cnf" [readonly] 125L, 4743C

canal配置

1)下载canal
下载地址
原理介绍
在这里插入图片描述

1.和mysql主从复制的原理差不多,canal 就是相当于一个slave,会订阅master的binlog,当binlog发生改变的时候,matser会启用一个dumpthread 去下载,然后传递给slave

下好了之后 直接解压:

  • 解压命令
  • 我移了一下位置,命令为mv /Users/mac/Downloads/canal.deployer-1.1.5-SNAPSHOT.tar.gz /Users/mac/alibabacanal
  • tar zxvf canal*.tar.gz

修改配置

在这里插入图片描述

// 这些其实里面都有备注看仔细点就好 重点配置下面的东西 
修改conf/example/instance.properties 
/ 修改mysql数据库的连接地址
canal.instance.master.address=127.0.0.1:3306
// 修改mysql的账号和密码
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
// 表示对mysql所有的表进行监听  实际项目中需要指定监听的库和表名
canal.instance.filter.regex=.*\\..*

修改之后去启动canal,执行语句如下

  • sudo sh …/bin/startup.sh
    踩坑点
    我有一次停止后,再启用就报错,说端口占用了。记得查询一下端口,然后kill掉,再启动。
  • sudo lsof -i :8080
  • sudo kill -9 653
    如何检查是否已经启动成功
    去查看logs/canal/canal.log 日志进行查看
    出现如此,代表着成功

java代码实现canal客户端

public class CanalClient {
    public static void main(String args[]) {
        // 连接我们的CanalServer端
        CanalConnector connector = CanalConnectors.newSingleConnector(new
                InetSocketAddress("127.0.0.1",
                11111), "example", "", "");
        int batchSize = 100;
        try {
            connector.connect();
            // 表示监听2020_order库下的tbl_order表   2020_order.*表示监听该库下所有表
            connector.subscribe("study.student");
            connector.rollback();
            while (true) {
                // 获取指定数量的数据
                Message message = connector.getWithoutAck(batchSize);
                long batchId = message.getId();
                int size = message.getEntries().size();
                System.out.println("batchId = " + batchId);
                System.out.println("size = " + size);
                System.out.println(message.getEntries());
                if (batchId == -1 || size == 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    printEntry(message.getEntries());
                }
                // 提交确认
                connector.ack(batchId);
                // connector.rollback(batchId); // 处理失败, 回滚数据
            }
        } finally {
            connector.disconnect();
        }
    }

    private static void printEntry(List<CanalEntry.Entry> entrys) {
        for (CanalEntry.Entry entry : entrys) {
            if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) {
                continue;
            }
            CanalEntry.RowChange rowChage = null;
            try {
                rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
            } catch (Exception e) {
                throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),
                        e);
            }
            CanalEntry.EventType eventType = rowChage.getEventType();
            System.out.println(String.format("================> binlog[%s:%s] , name[%s,%s] , eventType : %s",
                    //logfileOffset可以拿到bin-log的postion
                    entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
                    entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
                    eventType));

            for (CanalEntry.RowData rowData : rowChage.getRowDatasList()) {
                if (eventType == CanalEntry.EventType.DELETE) {
                    redisDelete(rowData.getBeforeColumnsList());
                } else if (eventType == CanalEntry.EventType.INSERT) {
                    redisInsert(rowData.getAfterColumnsList());
                } else {
                    System.out.println("-------> before");
                    printColumn(rowData.getBeforeColumnsList());
                    System.out.println("-------> after");
                    redisUpdate(rowData.getBeforeColumnsList(), rowData.getAfterColumnsList());
                }
            }
        }
    }

    private static void printColumn(List<CanalEntry.Column> columns) {
        for (CanalEntry.Column column : columns) {
            System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());
        }
    }

    private static void redisInsert(List<CanalEntry.Column> columns) {
        JSONObject json = new JSONObject();
        for (CanalEntry.Column column : columns) {
            json.put(column.getName(), column.getValue());
        }
        if (columns.size() > 0) {
            RedisUtil.stringSet(columns.get(0).getValue(), json.toJSONString());
        }
    }

    private static void redisUpdate(List<CanalEntry.Column> beforColums,List<CanalEntry.Column> columns) {
        JSONObject json = new JSONObject();
        for (CanalEntry.Column column : columns) {
            json.put(column.getName(), column.getValue());
        }
        if (columns.size() > 0) {
            RedisUtil.stringSet(""+beforColums.get(0).getValue(), json.toJSONString());
        }
    }

    private static void redisDelete(List<CanalEntry.Column> columns) {
        JSONObject json = new JSONObject();
        for (CanalEntry.Column column : columns) {
            json.put(column.getName(), column.getValue());
        }
        if (columns.size() > 0) {
            RedisUtil.delKey(columns.get(0).getValue());
        }
    }

}

public class RedisUtil {
    private static Jedis jedis = null;

    public static synchronized Jedis getJedis() {
        if (jedis == null) {
            jedis = new Jedis("127.0.0.1", 6379);
        }
        return jedis;
    }

    public static boolean existKey(String key) {
        return getJedis().exists(key);
    }

    public static void delKey(String key) {
        getJedis().del(key);
    }

    public static String stringGet(String key) {
        return getJedis().get(key);
    }

    public static String stringSet(String key, String value) {
        return getJedis().set(key, value);
    }

    public static void hashSet(String key, String field, String value) {
        getJedis().hset(key, field, value);
    }

}

canal高可用机制

  • canal宕机
    如果canal宕机的话,再次启动canal,canal也会将在宕机过程中的操作的mysql数据,一样同步给客户端。因为会记录上次发送的postion

  • 客户端宕机
    如果客户端宕机的话,再次启动客户端,canal也会将在宕机过程中的操作的mysql数据,一样同步给客户端。

基于rocketmq实现 还未写

在这里插入图片描述

修改连接模型  默认支持tcp, kafka, RocketMQ
canal.serverMode = kafka
 
#kafka连接地址,如果kafka集群的话这里配置只一个地址也是没问题的,如果需要配置可以多个用逗号:,分开
canal.mq.servers = 127.0.0.1:9092

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值